Show More
@@ -8,9 +8,9 b'' | |||
|
8 | 8 | from demandload import demandload |
|
9 | 9 | from i18n import gettext as _ |
|
10 | 10 | from node import * |
|
11 | demandload(globals(), "cmdutil mdiff util") | |
|
12 |
demandload(globals(), |
|
|
13 | popen2''') | |
|
11 | demandload(globals(), "base85 cmdutil mdiff util") | |
|
12 | demandload(globals(), "cStringIO email.Parser errno os re shutil sha sys") | |
|
13 | demandload(globals(), "tempfile zlib") | |
|
14 | 14 | |
|
15 | 15 | # helper functions |
|
16 | 16 | |
@@ -128,6 +128,7 b' def readgitpatch(patchname):' | |||
|
128 | 128 | self.op = 'MODIFY' |
|
129 | 129 | self.copymod = False |
|
130 | 130 | self.lineno = 0 |
|
131 | self.binary = False | |
|
131 | 132 | |
|
132 | 133 | # Filter patch for git information |
|
133 | 134 | gitre = re.compile('diff --git a/(.*) b/(.*)') |
@@ -175,6 +176,10 b' def readgitpatch(patchname):' | |||
|
175 | 176 | gp.mode = int(line.rstrip()[-3:], 8) |
|
176 | 177 | elif line.startswith('new mode '): |
|
177 | 178 | gp.mode = int(line.rstrip()[-3:], 8) |
|
179 | elif line.startswith('GIT binary patch'): | |
|
180 | if not dopatch: | |
|
181 | dopatch = 'binary' | |
|
182 | gp.binary = True | |
|
178 | 183 | if gp: |
|
179 | 184 | gitpatches.append(gp) |
|
180 | 185 | |
@@ -185,6 +190,25 b' def readgitpatch(patchname):' | |||
|
185 | 190 | |
|
186 | 191 | def dogitpatch(patchname, gitpatches, cwd=None): |
|
187 | 192 | """Preprocess git patch so that vanilla patch can handle it""" |
|
193 | def extractbin(fp): | |
|
194 | line = fp.readline() | |
|
195 | while line and not line.startswith('literal '): | |
|
196 | line = fp.readline() | |
|
197 | if not line: | |
|
198 | return | |
|
199 | size = int(line[8:].rstrip()) | |
|
200 | dec = [] | |
|
201 | line = fp.readline() | |
|
202 | while line: | |
|
203 | line = line[1:-1] | |
|
204 | dec.append(base85.b85decode(line)) | |
|
205 | line = fp.readline() | |
|
206 | text = zlib.decompress(''.join(dec)) | |
|
207 | if len(text) != size: | |
|
208 | raise util.Abort(_('binary patch is %d bytes, not %d') % | |
|
209 | (len(text), size)) | |
|
210 | return text | |
|
211 | ||
|
188 | 212 | pf = file(patchname) |
|
189 | 213 | pfline = 1 |
|
190 | 214 | |
@@ -194,23 +218,37 b' def dogitpatch(patchname, gitpatches, cw' | |||
|
194 | 218 | try: |
|
195 | 219 | for i in range(len(gitpatches)): |
|
196 | 220 | p = gitpatches[i] |
|
197 | if not p.copymod: | |
|
221 | if not p.copymod and not p.binary: | |
|
198 | 222 | continue |
|
199 | 223 | |
|
200 | copyfile(p.oldpath, p.path, basedir=cwd) | |
|
201 | ||
|
202 | 224 | # rewrite patch hunk |
|
203 | 225 | while pfline < p.lineno: |
|
204 | 226 | tmpfp.write(pf.readline()) |
|
205 | 227 | pfline += 1 |
|
206 | tmpfp.write('diff --git a/%s b/%s\n' % (p.path, p.path)) | |
|
207 | line = pf.readline() | |
|
208 | pfline += 1 | |
|
209 | while not line.startswith('--- a/'): | |
|
210 | tmpfp.write(line) | |
|
228 | ||
|
229 | if p.binary: | |
|
230 | text = extractbin(pf) | |
|
231 | if not text: | |
|
232 | raise util.Abort(_('binary patch extraction failed')) | |
|
233 | if not cwd: | |
|
234 | cwd = os.getcwd() | |
|
235 | absdst = os.path.join(cwd, p.path) | |
|
236 | basedir = os.path.dirname(absdst) | |
|
237 | if not os.path.isdir(basedir): | |
|
238 | os.makedirs(basedir) | |
|
239 | out = file(absdst, 'wb') | |
|
240 | out.write(text) | |
|
241 | out.close() | |
|
242 | elif p.copymod: | |
|
243 | copyfile(p.oldpath, p.path, basedir=cwd) | |
|
244 | tmpfp.write('diff --git a/%s b/%s\n' % (p.path, p.path)) | |
|
211 | 245 | line = pf.readline() |
|
212 | 246 | pfline += 1 |
|
213 | tmpfp.write('--- a/%s\n' % p.path) | |
|
247 | while not line.startswith('--- a/'): | |
|
248 | tmpfp.write(line) | |
|
249 | line = pf.readline() | |
|
250 | pfline += 1 | |
|
251 | tmpfp.write('--- a/%s\n' % p.path) | |
|
214 | 252 | |
|
215 | 253 | line = pf.readline() |
|
216 | 254 | while line: |
@@ -270,16 +308,16 b' def patch(patchname, ui, strip=1, cwd=No' | |||
|
270 | 308 | |
|
271 | 309 | (dopatch, gitpatches) = readgitpatch(patchname) |
|
272 | 310 | |
|
311 | files, fuzz = {}, False | |
|
273 | 312 | if dopatch: |
|
274 |
if dopatch |
|
|
313 | if dopatch in ('filter', 'binary'): | |
|
275 | 314 | patchname = dogitpatch(patchname, gitpatches, cwd=cwd) |
|
276 | 315 | try: |
|
277 | files, fuzz = __patch(patchname) | |
|
316 | if dopatch != 'binary': | |
|
317 | files, fuzz = __patch(patchname) | |
|
278 | 318 | finally: |
|
279 | 319 | if dopatch == 'filter': |
|
280 | 320 | os.unlink(patchname) |
|
281 | else: | |
|
282 | files, fuzz = {}, False | |
|
283 | 321 | |
|
284 | 322 | for gp in gitpatches: |
|
285 | 323 | files[gp.path] = (gp.op, gp) |
@@ -340,6 +378,40 b' def updatedir(ui, repo, patches, wlock=N' | |||
|
340 | 378 | |
|
341 | 379 | return files |
|
342 | 380 | |
|
381 | def b85diff(fp, to, tn): | |
|
382 | '''print base85-encoded binary diff''' | |
|
383 | def gitindex(text): | |
|
384 | if not text: | |
|
385 | return '0' * 40 | |
|
386 | l = len(text) | |
|
387 | s = sha.new('blob %d\0' % l) | |
|
388 | s.update(text) | |
|
389 | return s.hexdigest() | |
|
390 | ||
|
391 | def fmtline(line): | |
|
392 | l = len(line) | |
|
393 | if l <= 26: | |
|
394 | l = chr(ord('A') + l - 1) | |
|
395 | else: | |
|
396 | l = chr(l - 26 + ord('a') - 1) | |
|
397 | return '%c%s\n' % (l, base85.b85encode(line, True)) | |
|
398 | ||
|
399 | def chunk(text, csize=52): | |
|
400 | l = len(text) | |
|
401 | i = 0 | |
|
402 | while i < l: | |
|
403 | yield text[i:i+csize] | |
|
404 | i += csize | |
|
405 | ||
|
406 | # TODO: deltas | |
|
407 | l = len(tn) | |
|
408 | fp.write('index %s..%s\nGIT binary patch\nliteral %s\n' % | |
|
409 | (gitindex(to), gitindex(tn), len(tn))) | |
|
410 | ||
|
411 | tn = ''.join([fmtline(l) for l in chunk(zlib.compress(tn))]) | |
|
412 | fp.write(tn) | |
|
413 | fp.write('\n') | |
|
414 | ||
|
343 | 415 | def diff(repo, node1=None, node2=None, files=None, match=util.always, |
|
344 | 416 | fp=None, changes=None, opts=None): |
|
345 | 417 | '''print diff of changes to files between two nodes, or node and |
@@ -496,6 +568,8 b' def diff(repo, node1=None, node2=None, f' | |||
|
496 | 568 | to = getfile(a).read(arev) |
|
497 | 569 | else: |
|
498 | 570 | header.append('new file mode %s\n' % mode) |
|
571 | if util.binary(tn): | |
|
572 | dodiff = 'binary' | |
|
499 | 573 | elif f in removed: |
|
500 | 574 | if f in srcs: |
|
501 | 575 | dodiff = False |
@@ -509,9 +583,14 b' def diff(repo, node1=None, node2=None, f' | |||
|
509 | 583 | else: |
|
510 | 584 | nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) |
|
511 | 585 | addmodehdr(header, omode, nmode) |
|
586 | if util.binary(to) or util.binary(tn): | |
|
587 | dodiff = 'binary' | |
|
512 | 588 | r = None |
|
513 | 589 | header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) |
|
514 | if dodiff: | |
|
590 | if dodiff == 'binary': | |
|
591 | fp.write(''.join(header)) | |
|
592 | b85diff(fp, to, tn) | |
|
593 | elif dodiff: | |
|
515 | 594 | text = mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts) |
|
516 | 595 | if text or len(header) > 1: |
|
517 | 596 | fp.write(''.join(header)) |
General Comments 0
You need to be logged in to leave comments.
Login now