@@ -3214,6 +3214,42 @@ def hasBranchPrefix(self, path):
3214
3214
print ('Ignoring file outside of prefix: {0}' .format (path ))
3215
3215
return hasPrefix
3216
3216
3217
+ def findShadowedFiles (self , files , change ):
3218
+ # Perforce allows you commit files and directories with the same name,
3219
+ # so you could have files //depot/foo and //depot/foo/bar both checked
3220
+ # in. A p4 sync of a repository in this state fails. Deleting one of
3221
+ # the files recovers the repository.
3222
+ #
3223
+ # Git will not allow the broken state to exist and only the most recent
3224
+ # of the conflicting names is left in the repository. When one of the
3225
+ # conflicting files is deleted we need to re-add the other one to make
3226
+ # sure the git repository recovers in the same way as perforce.
3227
+ deleted = [f for f in files if f ['action' ] in self .delete_actions ]
3228
+ to_check = set ()
3229
+ for f in deleted :
3230
+ path = decode_path (f ['path' ])
3231
+ to_check .add (path + '/...' )
3232
+ while True :
3233
+ path = path .rsplit ("/" , 1 )[0 ]
3234
+ if path == "/" or path in to_check :
3235
+ break
3236
+ to_check .add (path )
3237
+ to_check = ['%s@%s' % (wildcard_encode (p ), change ) for p in to_check
3238
+ if self .hasBranchPrefix (p )]
3239
+ if to_check :
3240
+ stat_result = p4CmdList (["-x" , "-" , "fstat" , "-T" ,
3241
+ "depotFile,headAction,headRev,headType" ], stdin = to_check )
3242
+ for record in stat_result :
3243
+ if record ['code' ] != 'stat' :
3244
+ continue
3245
+ if record ['headAction' ] in self .delete_actions :
3246
+ continue
3247
+ files .append ({
3248
+ 'action' : 'add' ,
3249
+ 'path' : record ['depotFile' ],
3250
+ 'rev' : record ['headRev' ],
3251
+ 'type' : record ['headType' ]})
3252
+
3217
3253
def commit (self , details , files , branch , parent = "" , allow_empty = False ):
3218
3254
epoch = details ["time" ]
3219
3255
author = details ["user" ]
@@ -3222,11 +3258,14 @@ def commit(self, details, files, branch, parent = "", allow_empty=False):
3222
3258
if self .verbose :
3223
3259
print ('commit into {0}' .format (branch ))
3224
3260
3261
+ files = [f for f in files
3262
+ if self .hasBranchPrefix (decode_path (f ['path' ]))]
3263
+ self .findShadowedFiles (files , details ['change' ])
3264
+
3225
3265
if self .clientSpecDirs :
3226
3266
self .clientSpecDirs .update_client_spec_path_cache (files )
3227
3267
3228
- files = [f for (f , path ) in ((f , decode_path (f ['path' ])) for f in files )
3229
- if self .inClientSpec (path ) and self .hasBranchPrefix (path )]
3268
+ files = [f for f in files if self .inClientSpec (decode_path (f ['path' ]))]
3230
3269
3231
3270
if gitConfigBool ('git-p4.keepEmptyCommits' ):
3232
3271
allow_empty = True
0 commit comments