@@ -201,7 +201,7 @@ def isModeExec(mode):
201
201
def isModeExecChanged (src_mode , dst_mode ):
202
202
return isModeExec (src_mode ) != isModeExec (dst_mode )
203
203
204
- def p4CmdList (cmd , stdin = None , stdin_mode = 'w+b' ):
204
+ def p4CmdList (cmd , stdin = None , stdin_mode = 'w+b' , cb = None ):
205
205
cmd = p4_build_cmd ("-G %s" % (cmd ))
206
206
if verbose :
207
207
sys .stderr .write ("Opening pipe: %s\n " % cmd )
@@ -224,7 +224,10 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
224
224
try :
225
225
while True :
226
226
entry = marshal .load (p4 .stdout )
227
- result .append (entry )
227
+ if cb is not None :
228
+ cb (entry )
229
+ else :
230
+ result .append (entry )
228
231
except EOFError :
229
232
pass
230
233
exitCode = p4 .wait ()
@@ -950,10 +953,84 @@ class P4Sync(Command):
950
953
951
954
return branches
952
955
953
- ## Should move this out, doesn't use SELF.
954
- def readP4Files (self , files ):
956
+ # output one file from the P4 stream
957
+ # - helper for streamP4Files
958
+
959
+ def streamOneP4File (self , file , contents ):
960
+ if file ["type" ] == "apple" :
961
+ print "\n file %s is a strange apple file that forks. Ignoring" % \
962
+ file ['depotFile' ]
963
+ return
964
+
965
+ relPath = self .stripRepoPath (file ['depotFile' ], self .branchPrefixes )
966
+ if verbose :
967
+ sys .stderr .write ("%s\n " % relPath )
968
+
969
+ mode = "644"
970
+ if isP4Exec (file ["type" ]):
971
+ mode = "755"
972
+ elif file ["type" ] == "symlink" :
973
+ mode = "120000"
974
+ # p4 print on a symlink contains "target\n", so strip it off
975
+ last = contents .pop ()
976
+ last = last [:- 1 ]
977
+ contents .append (last )
978
+
979
+ if self .isWindows and file ["type" ].endswith ("text" ):
980
+ mangled = []
981
+ for data in contents :
982
+ data = data .replace ("\r \n " , "\n " )
983
+ mangled .append (data )
984
+ contents = mangled
985
+
986
+ if file ['type' ] in ('text+ko' , 'unicode+ko' , 'binary+ko' ):
987
+ contents = map (lambda text : re .sub (r'(?i)\$(Id|Header):[^$]*\$' ,r'$\1$' , text ), contents )
988
+ elif file ['type' ] in ('text+k' , 'ktext' , 'kxtext' , 'unicode+k' , 'binary+k' ):
989
+ contents = map (lambda text : re .sub (r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$' ,r'$\1$' , text ), contents )
990
+
991
+ self .gitStream .write ("M %s inline %s\n " % (mode , relPath ))
992
+
993
+ # total length...
994
+ length = 0
995
+ for d in contents :
996
+ length = length + len (d )
997
+
998
+ self .gitStream .write ("data %d\n " % length )
999
+ for d in contents :
1000
+ self .gitStream .write (d )
1001
+ self .gitStream .write ("\n " )
1002
+
1003
+ def streamOneP4Deletion (self , file ):
1004
+ relPath = self .stripRepoPath (file ['path' ], self .branchPrefixes )
1005
+ if verbose :
1006
+ sys .stderr .write ("delete %s\n " % relPath )
1007
+ self .gitStream .write ("D %s\n " % relPath )
1008
+
1009
+ # handle another chunk of streaming data
1010
+ def streamP4FilesCb (self , marshalled ):
1011
+
1012
+ if marshalled .has_key ('depotFile' ) and self .stream_have_file_info :
1013
+ # start of a new file - output the old one first
1014
+ self .streamOneP4File (self .stream_file , self .stream_contents )
1015
+ self .stream_file = {}
1016
+ self .stream_contents = []
1017
+ self .stream_have_file_info = False
1018
+
1019
+ # pick up the new file information... for the
1020
+ # 'data' field we need to append to our array
1021
+ for k in marshalled .keys ():
1022
+ if k == 'data' :
1023
+ self .stream_contents .append (marshalled ['data' ])
1024
+ else :
1025
+ self .stream_file [k ] = marshalled [k ]
1026
+
1027
+ self .stream_have_file_info = True
1028
+
1029
+ # Stream directly from "p4 files" into "git fast-import"
1030
+ def streamP4Files (self , files ):
955
1031
filesForCommit = []
956
1032
filesToRead = []
1033
+ filesToDelete = []
957
1034
958
1035
for f in files :
959
1036
includeFile = True
@@ -967,50 +1044,35 @@ class P4Sync(Command):
967
1044
filesForCommit .append (f )
968
1045
if f ['action' ] not in ('delete' , 'purge' ):
969
1046
filesToRead .append (f )
1047
+ else :
1048
+ filesToDelete .append (f )
970
1049
971
- filedata = []
972
- if len (filesToRead ) > 0 :
973
- filedata = p4CmdList ('-x - print' ,
974
- stdin = '\n ' .join (['%s#%s' % (f ['path' ], f ['rev' ])
975
- for f in filesToRead ]),
976
- stdin_mode = 'w+' )
977
-
978
- if "p4ExitCode" in filedata [0 ]:
979
- die ("Problems executing p4. Error: [%d]."
980
- % (filedata [0 ]['p4ExitCode' ]));
981
-
982
- j = 0 ;
983
- contents = {}
984
- while j < len (filedata ):
985
- stat = filedata [j ]
986
- j += 1
987
- text = ''
988
- while j < len (filedata ) and filedata [j ]['code' ] in ('text' , 'unicode' , 'binary' ):
989
- text += filedata [j ]['data' ]
990
- del filedata [j ]['data' ]
991
- j += 1
992
-
993
- if not stat .has_key ('depotFile' ):
994
- sys .stderr .write ("p4 print fails with: %s\n " % repr (stat ))
995
- continue
1050
+ # deleted files...
1051
+ for f in filesToDelete :
1052
+ self .streamOneP4Deletion (f )
996
1053
997
- if stat [ 'type' ] in ( 'text+ko' , 'unicode+ko' , 'binary+ko' ) :
998
- text = re . sub ( r'(?i)\$(Id|Header):[^$]*\$' , r'$\1$' , text )
999
- elif stat [ 'type' ] in ( 'text+k' , 'ktext' , 'kxtext' , 'unicode+k' , 'binary+k' ):
1000
- text = re . sub ( r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$' , r'$\1$' , text )
1054
+ if len ( filesToRead ) > 0 :
1055
+ self . stream_file = {}
1056
+ self . stream_contents = []
1057
+ self . stream_have_file_info = False
1001
1058
1002
- contents [stat ['depotFile' ]] = text
1059
+ # curry self argument
1060
+ def streamP4FilesCbSelf (entry ):
1061
+ self .streamP4FilesCb (entry )
1003
1062
1004
- for f in filesForCommit :
1005
- path = f ['path' ]
1006
- if contents . has_key ( path ):
1007
- f [ 'data' ] = contents [ path ]
1063
+ p4CmdList ( "-x - print" ,
1064
+ ' \n ' . join ([ '%s#%s' % ( f [ ' path' ], f ['rev' ])
1065
+ for f in filesToRead ]),
1066
+ cb = streamP4FilesCbSelf )
1008
1067
1009
- return filesForCommit
1068
+ # do the last chunk
1069
+ if self .stream_file .has_key ('depotFile' ):
1070
+ self .streamOneP4File (self .stream_file , self .stream_contents )
1010
1071
1011
1072
def commit (self , details , files , branch , branchPrefixes , parent = "" ):
1012
1073
epoch = details ["time" ]
1013
1074
author = details ["user" ]
1075
+ self .branchPrefixes = branchPrefixes
1014
1076
1015
1077
if self .verbose :
1016
1078
print "commit into %s" % branch
@@ -1023,7 +1085,6 @@ class P4Sync(Command):
1023
1085
new_files .append (f )
1024
1086
else :
1025
1087
sys .stderr .write ("Ignoring file outside of prefix: %s\n " % path )
1026
- files = self .readP4Files (new_files )
1027
1088
1028
1089
self .gitStream .write ("commit %s\n " % branch )
1029
1090
# gitStream.write("mark :%s\n" % details["change"])
@@ -1051,33 +1112,7 @@ class P4Sync(Command):
1051
1112
print "parent %s" % parent
1052
1113
self .gitStream .write ("from %s\n " % parent )
1053
1114
1054
- for file in files :
1055
- if file ["type" ] == "apple" :
1056
- print "\n file %s is a strange apple file that forks. Ignoring!" % file ['path' ]
1057
- continue
1058
-
1059
- relPath = self .stripRepoPath (file ['path' ], branchPrefixes )
1060
- if file ["action" ] in ("delete" , "purge" ):
1061
- self .gitStream .write ("D %s\n " % relPath )
1062
- else :
1063
- data = file ['data' ]
1064
-
1065
- mode = "644"
1066
- if isP4Exec (file ["type" ]):
1067
- mode = "755"
1068
- elif file ["type" ] == "symlink" :
1069
- mode = "120000"
1070
- # p4 print on a symlink contains "target\n", so strip it off
1071
- data = data [:- 1 ]
1072
-
1073
- if self .isWindows and file ["type" ].endswith ("text" ):
1074
- data = data .replace ("\r \n " , "\n " )
1075
-
1076
- self .gitStream .write ("M %s inline %s\n " % (mode , relPath ))
1077
- self .gitStream .write ("data %s\n " % len (data ))
1078
- self .gitStream .write (data )
1079
- self .gitStream .write ("\n " )
1080
-
1115
+ self .streamP4Files (new_files )
1081
1116
self .gitStream .write ("\n " )
1082
1117
1083
1118
change = int (details ["change" ])
0 commit comments