@@ -1306,6 +1306,9 @@ def processContent(self, git_mode, relPath, contents):
1306
1306
return LargeFileSystem .processContent (self , git_mode , relPath , contents )
1307
1307
1308
1308
class Command :
1309
+ delete_actions = ( "delete" , "move/delete" , "purge" )
1310
+ add_actions = ( "add" , "move/add" )
1311
+
1309
1312
def __init__ (self ):
1310
1313
self .usage = "usage: %prog [options]"
1311
1314
self .needsGit = True
@@ -2524,7 +2527,6 @@ def map_in_client(self, depot_path):
2524
2527
return ""
2525
2528
2526
2529
class P4Sync (Command , P4UserMap ):
2527
- delete_actions = ( "delete" , "move/delete" , "purge" )
2528
2530
2529
2531
def __init__ (self ):
2530
2532
Command .__init__ (self )
@@ -2612,20 +2614,7 @@ def checkpoint(self):
2612
2614
if self .verbose :
2613
2615
print ("checkpoint finished: " + out )
2614
2616
2615
- def cmp_shelved (self , path , filerev , revision ):
2616
- """ Determine if a path at revision #filerev is the same as the file
2617
- at revision @revision for a shelved changelist. If they don't match,
2618
- unshelving won't be safe (we will get other changes mixed in).
2619
-
2620
- This is comparing the revision that the shelved changelist is *based* on, not
2621
- the shelved changelist itself.
2622
- """
2623
- ret = p4Cmd (["diff2" , "{0}#{1}" .format (path , filerev ), "{0}@{1}" .format (path , revision )])
2624
- if verbose :
2625
- print ("p4 diff2 path %s filerev %s revision %s => %s" % (path , filerev , revision , ret ))
2626
- return ret ["status" ] == "identical"
2627
-
2628
- def extractFilesFromCommit (self , commit , shelved = False , shelved_cl = 0 , origin_revision = 0 ):
2617
+ def extractFilesFromCommit (self , commit , shelved = False , shelved_cl = 0 ):
2629
2618
self .cloneExclude = [re .sub (r"\.\.\.$" , "" , path )
2630
2619
for path in self .cloneExclude ]
2631
2620
files = []
@@ -2650,17 +2639,6 @@ def extractFilesFromCommit(self, commit, shelved=False, shelved_cl = 0, origin_r
2650
2639
file ["type" ] = commit ["type%s" % fnum ]
2651
2640
if shelved :
2652
2641
file ["shelved_cl" ] = int (shelved_cl )
2653
-
2654
- # For shelved changelists, check that the revision of each file that the
2655
- # shelve was based on matches the revision that we are using for the
2656
- # starting point for git-fast-import (self.initialParent). Otherwise
2657
- # the resulting diff will contain deltas from multiple commits.
2658
-
2659
- if file ["action" ] != "add" and \
2660
- not self .cmp_shelved (path , file ["rev" ], origin_revision ):
2661
- sys .exit ("change {0} not based on {1} for {2}, cannot unshelve" .format (
2662
- commit ["change" ], self .initialParent , path ))
2663
-
2664
2642
files .append (file )
2665
2643
fnum = fnum + 1
2666
2644
return files
@@ -2775,7 +2753,10 @@ def streamOneP4File(self, file, contents):
2775
2753
relPath = self .stripRepoPath (file ['depotFile' ], self .branchPrefixes )
2776
2754
relPath = self .encodeWithUTF8 (relPath )
2777
2755
if verbose :
2778
- size = int (self .stream_file ['fileSize' ])
2756
+ if 'fileSize' in self .stream_file :
2757
+ size = int (self .stream_file ['fileSize' ])
2758
+ else :
2759
+ size = 0 # deleted files don't get a fileSize apparently
2779
2760
sys .stdout .write ('\r %s --> %s (%i MB)\n ' % (file ['depotFile' ], relPath , size / 1024 / 1024 ))
2780
2761
sys .stdout .flush ()
2781
2762
@@ -3029,7 +3010,7 @@ def hasBranchPrefix(self, path):
3029
3010
print ('Ignoring file outside of prefix: {0}' .format (path ))
3030
3011
return hasPrefix
3031
3012
3032
- def commit (self , details , files , branch , parent = "" ):
3013
+ def commit (self , details , files , branch , parent = "" , allow_empty = False ):
3033
3014
epoch = details ["time" ]
3034
3015
author = details ["user" ]
3035
3016
jobs = self .extractJobsFromCommit (details )
@@ -3043,7 +3024,10 @@ def commit(self, details, files, branch, parent = ""):
3043
3024
files = [f for f in files
3044
3025
if self .inClientSpec (f ['path' ]) and self .hasBranchPrefix (f ['path' ])]
3045
3026
3046
- if not files and not gitConfigBool ('git-p4.keepEmptyCommits' ):
3027
+ if gitConfigBool ('git-p4.keepEmptyCommits' ):
3028
+ allow_empty = True
3029
+
3030
+ if not files and not allow_empty :
3047
3031
print ('Ignoring revision {0} as it would produce an empty commit.'
3048
3032
.format (details ['change' ]))
3049
3033
return
@@ -3384,10 +3368,10 @@ def searchParent(self, parent, branch, target):
3384
3368
else :
3385
3369
return None
3386
3370
3387
- def importChanges (self , changes , shelved = False , origin_revision = 0 ):
3371
+ def importChanges (self , changes , origin_revision = 0 ):
3388
3372
cnt = 1
3389
3373
for change in changes :
3390
- description = p4_describe (change , shelved )
3374
+ description = p4_describe (change )
3391
3375
self .updateOptionDict (description )
3392
3376
3393
3377
if not self .silent :
@@ -3457,7 +3441,7 @@ def importChanges(self, changes, shelved=False, origin_revision=0):
3457
3441
print ("Parent of %s not found. Committing into head of %s" % (branch , parent ))
3458
3442
self .commit (description , filesForCommit , branch , parent )
3459
3443
else :
3460
- files = self .extractFilesFromCommit (description , shelved , change , origin_revision )
3444
+ files = self .extractFilesFromCommit (description )
3461
3445
self .commit (description , files , self .branch ,
3462
3446
self .initialParent )
3463
3447
# only needed once, to connect to the previous commit
@@ -3953,7 +3937,7 @@ def __init__(self):
3953
3937
]
3954
3938
self .verbose = False
3955
3939
self .noCommit = False
3956
- self .destbranch = "refs/remotes/p4/ unshelved"
3940
+ self .destbranch = "refs/remotes/p4- unshelved"
3957
3941
3958
3942
def renameBranch (self , branch_name ):
3959
3943
""" Rename the existing branch to branch_name.N
@@ -3985,6 +3969,32 @@ def findLastP4Revision(self, starting_point):
3985
3969
3986
3970
sys .exit ("could not find git-p4 commits in {0}" .format (self .origin ))
3987
3971
3972
+ def createShelveParent (self , change , branch_name , sync , origin ):
3973
+ """ Create a commit matching the parent of the shelved changelist 'change'
3974
+ """
3975
+ parent_description = p4_describe (change , shelved = True )
3976
+ parent_description ['desc' ] = 'parent for shelved changelist {}\n ' .format (change )
3977
+ files = sync .extractFilesFromCommit (parent_description , shelved = False , shelved_cl = change )
3978
+
3979
+ parent_files = []
3980
+ for f in files :
3981
+ # if it was added in the shelved changelist, it won't exist in the parent
3982
+ if f ['action' ] in self .add_actions :
3983
+ continue
3984
+
3985
+ # if it was deleted in the shelved changelist it must not be deleted
3986
+ # in the parent - we might even need to create it if the origin branch
3987
+ # does not have it
3988
+ if f ['action' ] in self .delete_actions :
3989
+ f ['action' ] = 'add'
3990
+
3991
+ parent_files .append (f )
3992
+
3993
+ sync .commit (parent_description , parent_files , branch_name ,
3994
+ parent = origin , allow_empty = True )
3995
+ print ("created parent commit for {0} based on {1} in {2}" .format (
3996
+ change , self .origin , branch_name ))
3997
+
3988
3998
def run (self , args ):
3989
3999
if len (args ) != 1 :
3990
4000
return False
@@ -3994,9 +4004,8 @@ def run(self, args):
3994
4004
3995
4005
sync = P4Sync ()
3996
4006
changes = args
3997
- sync .initialParent = self .origin
3998
4007
3999
- # use the first change in the list to construct the branch to unshelve into
4008
+ # only one change at a time
4000
4009
change = changes [0 ]
4001
4010
4002
4011
# if the target branch already exists, rename it
@@ -4009,14 +4018,21 @@ def run(self, args):
4009
4018
sync .suppress_meta_comment = True
4010
4019
4011
4020
settings = self .findLastP4Revision (self .origin )
4012
- origin_revision = settings ['change' ]
4013
4021
sync .depotPaths = settings ['depot-paths' ]
4014
4022
sync .branchPrefixes = sync .depotPaths
4015
4023
4016
4024
sync .openStreams ()
4017
4025
sync .loadUserMapFromCache ()
4018
4026
sync .silent = True
4019
- sync .importChanges (changes , shelved = True , origin_revision = origin_revision )
4027
+
4028
+ # create a commit for the parent of the shelved changelist
4029
+ self .createShelveParent (change , branch_name , sync , self .origin )
4030
+
4031
+ # create the commit for the shelved changelist itself
4032
+ description = p4_describe (change , True )
4033
+ files = sync .extractFilesFromCommit (description , True , change )
4034
+
4035
+ sync .commit (description , files , branch_name , "" )
4020
4036
sync .closeStreams ()
4021
4037
4022
4038
print ("unshelved changelist {0} into {1}" .format (change , branch_name ))
0 commit comments