comparison mercurial/patch.py @ 3716:ab5600428b08

handle files with both git binary patches and copy/rename ops
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Mon, 27 Nov 2006 22:03:31 -0200
parents 70c3ee224c08
children 9e248cfd8b94
comparison
equal deleted inserted replaced
3715:6cb3aca69cdc 3716:ab5600428b08
112 if not diffs_seen: 112 if not diffs_seen:
113 os.unlink(tmpname) 113 os.unlink(tmpname)
114 return None, message, user, date 114 return None, message, user, date
115 return tmpname, message, user, date 115 return tmpname, message, user, date
116 116
117 GP_PATCH = 1 << 0 # we have to run patch
118 GP_FILTER = 1 << 1 # there's some copy/rename operation
119 GP_BINARY = 1 << 2 # there's a binary patch
120
117 def readgitpatch(patchname): 121 def readgitpatch(patchname):
118 """extract git-style metadata about patches from <patchname>""" 122 """extract git-style metadata about patches from <patchname>"""
119 class gitpatch: 123 class gitpatch:
120 "op is one of ADD, DELETE, RENAME, MODIFY or COPY" 124 "op is one of ADD, DELETE, RENAME, MODIFY or COPY"
121 def __init__(self, path): 125 def __init__(self, path):
131 gitre = re.compile('diff --git a/(.*) b/(.*)') 135 gitre = re.compile('diff --git a/(.*) b/(.*)')
132 pf = file(patchname) 136 pf = file(patchname)
133 gp = None 137 gp = None
134 gitpatches = [] 138 gitpatches = []
135 # Can have a git patch with only metadata, causing patch to complain 139 # Can have a git patch with only metadata, causing patch to complain
136 dopatch = False 140 dopatch = 0
137 141
138 lineno = 0 142 lineno = 0
139 for line in pf: 143 for line in pf:
140 lineno += 1 144 lineno += 1
141 if line.startswith('diff --git'): 145 if line.startswith('diff --git'):
148 gp.lineno = lineno 152 gp.lineno = lineno
149 elif gp: 153 elif gp:
150 if line.startswith('--- '): 154 if line.startswith('--- '):
151 if gp.op in ('COPY', 'RENAME'): 155 if gp.op in ('COPY', 'RENAME'):
152 gp.copymod = True 156 gp.copymod = True
153 dopatch = 'filter' 157 dopatch |= GP_FILTER
154 gitpatches.append(gp) 158 gitpatches.append(gp)
155 gp = None 159 gp = None
156 if not dopatch: 160 dopatch |= GP_PATCH
157 dopatch = True
158 continue 161 continue
159 if line.startswith('rename from '): 162 if line.startswith('rename from '):
160 gp.op = 'RENAME' 163 gp.op = 'RENAME'
161 gp.oldpath = line[12:].rstrip() 164 gp.oldpath = line[12:].rstrip()
162 elif line.startswith('rename to '): 165 elif line.startswith('rename to '):
172 gp.op = 'ADD' 175 gp.op = 'ADD'
173 gp.mode = int(line.rstrip()[-3:], 8) 176 gp.mode = int(line.rstrip()[-3:], 8)
174 elif line.startswith('new mode '): 177 elif line.startswith('new mode '):
175 gp.mode = int(line.rstrip()[-3:], 8) 178 gp.mode = int(line.rstrip()[-3:], 8)
176 elif line.startswith('GIT binary patch'): 179 elif line.startswith('GIT binary patch'):
177 if not dopatch: 180 dopatch |= GP_BINARY
178 dopatch = 'binary'
179 gp.binary = True 181 gp.binary = True
180 if gp: 182 if gp:
181 gitpatches.append(gp) 183 gitpatches.append(gp)
182 184
183 if not gitpatches: 185 if not gitpatches:
184 dopatch = True 186 dopatch = GP_PATCH
185 187
186 return (dopatch, gitpatches) 188 return (dopatch, gitpatches)
187 189
188 def dogitpatch(patchname, gitpatches, cwd=None): 190 def dogitpatch(patchname, gitpatches, cwd=None):
189 """Preprocess git patch so that vanilla patch can handle it""" 191 """Preprocess git patch so that vanilla patch can handle it"""
310 for gp in gitpatches: 312 for gp in gitpatches:
311 files[gp.path] = (gp.op, gp) 313 files[gp.path] = (gp.op, gp)
312 314
313 fuzz = False 315 fuzz = False
314 if dopatch: 316 if dopatch:
315 if dopatch in ('filter', 'binary'): 317 filterpatch = dopatch & (GP_FILTER | GP_BINARY)
318 if filterpatch:
316 patchname = dogitpatch(patchname, gitpatches, cwd=cwd) 319 patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
317 try: 320 try:
318 if dopatch != 'binary': 321 if dopatch & GP_PATCH:
319 fuzz = __patch(patchname) 322 fuzz = __patch(patchname)
320 finally: 323 finally:
321 if dopatch == 'filter': 324 if filterpatch:
322 os.unlink(patchname) 325 os.unlink(patchname)
323 326
324 return fuzz 327 return fuzz
325 328
326 def diffopts(ui, opts={}, untrusted=False): 329 def diffopts(ui, opts={}, untrusted=False):