Show More
@@ -8,9 +8,9 b'' | |||||
8 | from demandload import demandload |
|
8 | from demandload import demandload | |
9 | from i18n import gettext as _ |
|
9 | from i18n import gettext as _ | |
10 | from node import * |
|
10 | from node import * | |
11 | demandload(globals(), "cmdutil mdiff util") |
|
11 | demandload(globals(), "base85 cmdutil mdiff util") | |
12 |
demandload(globals(), |
|
12 | demandload(globals(), "cStringIO email.Parser errno os re shutil sha sys") | |
13 | popen2''') |
|
13 | demandload(globals(), "tempfile zlib") | |
14 |
|
14 | |||
15 | # helper functions |
|
15 | # helper functions | |
16 |
|
16 | |||
@@ -128,6 +128,7 b' def readgitpatch(patchname):' | |||||
128 | self.op = 'MODIFY' |
|
128 | self.op = 'MODIFY' | |
129 | self.copymod = False |
|
129 | self.copymod = False | |
130 | self.lineno = 0 |
|
130 | self.lineno = 0 | |
|
131 | self.binary = False | |||
131 |
|
132 | |||
132 | # Filter patch for git information |
|
133 | # Filter patch for git information | |
133 | gitre = re.compile('diff --git a/(.*) b/(.*)') |
|
134 | gitre = re.compile('diff --git a/(.*) b/(.*)') | |
@@ -175,6 +176,10 b' def readgitpatch(patchname):' | |||||
175 | gp.mode = int(line.rstrip()[-3:], 8) |
|
176 | gp.mode = int(line.rstrip()[-3:], 8) | |
176 | elif line.startswith('new mode '): |
|
177 | elif line.startswith('new mode '): | |
177 | gp.mode = int(line.rstrip()[-3:], 8) |
|
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 | if gp: |
|
183 | if gp: | |
179 | gitpatches.append(gp) |
|
184 | gitpatches.append(gp) | |
180 |
|
185 | |||
@@ -185,6 +190,25 b' def readgitpatch(patchname):' | |||||
185 |
|
190 | |||
186 | def dogitpatch(patchname, gitpatches, cwd=None): |
|
191 | def dogitpatch(patchname, gitpatches, cwd=None): | |
187 | """Preprocess git patch so that vanilla patch can handle it""" |
|
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 | pf = file(patchname) |
|
212 | pf = file(patchname) | |
189 | pfline = 1 |
|
213 | pfline = 1 | |
190 |
|
214 | |||
@@ -194,23 +218,37 b' def dogitpatch(patchname, gitpatches, cw' | |||||
194 | try: |
|
218 | try: | |
195 | for i in range(len(gitpatches)): |
|
219 | for i in range(len(gitpatches)): | |
196 | p = gitpatches[i] |
|
220 | p = gitpatches[i] | |
197 | if not p.copymod: |
|
221 | if not p.copymod and not p.binary: | |
198 | continue |
|
222 | continue | |
199 |
|
223 | |||
200 | copyfile(p.oldpath, p.path, basedir=cwd) |
|
|||
201 |
|
||||
202 | # rewrite patch hunk |
|
224 | # rewrite patch hunk | |
203 | while pfline < p.lineno: |
|
225 | while pfline < p.lineno: | |
204 | tmpfp.write(pf.readline()) |
|
226 | tmpfp.write(pf.readline()) | |
205 | pfline += 1 |
|
227 | pfline += 1 | |
206 | tmpfp.write('diff --git a/%s b/%s\n' % (p.path, p.path)) |
|
228 | ||
207 | line = pf.readline() |
|
229 | if p.binary: | |
208 | pfline += 1 |
|
230 | text = extractbin(pf) | |
209 | while not line.startswith('--- a/'): |
|
231 | if not text: | |
210 | tmpfp.write(line) |
|
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 | line = pf.readline() |
|
245 | line = pf.readline() | |
212 | pfline += 1 |
|
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 | line = pf.readline() |
|
253 | line = pf.readline() | |
216 | while line: |
|
254 | while line: | |
@@ -270,16 +308,16 b' def patch(patchname, ui, strip=1, cwd=No' | |||||
270 |
|
308 | |||
271 | (dopatch, gitpatches) = readgitpatch(patchname) |
|
309 | (dopatch, gitpatches) = readgitpatch(patchname) | |
272 |
|
310 | |||
|
311 | files, fuzz = {}, False | |||
273 | if dopatch: |
|
312 | if dopatch: | |
274 |
if dopatch |
|
313 | if dopatch in ('filter', 'binary'): | |
275 | patchname = dogitpatch(patchname, gitpatches, cwd=cwd) |
|
314 | patchname = dogitpatch(patchname, gitpatches, cwd=cwd) | |
276 | try: |
|
315 | try: | |
277 | files, fuzz = __patch(patchname) |
|
316 | if dopatch != 'binary': | |
|
317 | files, fuzz = __patch(patchname) | |||
278 | finally: |
|
318 | finally: | |
279 | if dopatch == 'filter': |
|
319 | if dopatch == 'filter': | |
280 | os.unlink(patchname) |
|
320 | os.unlink(patchname) | |
281 | else: |
|
|||
282 | files, fuzz = {}, False |
|
|||
283 |
|
321 | |||
284 | for gp in gitpatches: |
|
322 | for gp in gitpatches: | |
285 | files[gp.path] = (gp.op, gp) |
|
323 | files[gp.path] = (gp.op, gp) | |
@@ -340,6 +378,40 b' def updatedir(ui, repo, patches, wlock=N' | |||||
340 |
|
378 | |||
341 | return files |
|
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 | def diff(repo, node1=None, node2=None, files=None, match=util.always, |
|
415 | def diff(repo, node1=None, node2=None, files=None, match=util.always, | |
344 | fp=None, changes=None, opts=None): |
|
416 | fp=None, changes=None, opts=None): | |
345 | '''print diff of changes to files between two nodes, or node and |
|
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 | to = getfile(a).read(arev) |
|
568 | to = getfile(a).read(arev) | |
497 | else: |
|
569 | else: | |
498 | header.append('new file mode %s\n' % mode) |
|
570 | header.append('new file mode %s\n' % mode) | |
|
571 | if util.binary(tn): | |||
|
572 | dodiff = 'binary' | |||
499 | elif f in removed: |
|
573 | elif f in removed: | |
500 | if f in srcs: |
|
574 | if f in srcs: | |
501 | dodiff = False |
|
575 | dodiff = False | |
@@ -509,9 +583,14 b' def diff(repo, node1=None, node2=None, f' | |||||
509 | else: |
|
583 | else: | |
510 | nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) |
|
584 | nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) | |
511 | addmodehdr(header, omode, nmode) |
|
585 | addmodehdr(header, omode, nmode) | |
|
586 | if util.binary(to) or util.binary(tn): | |||
|
587 | dodiff = 'binary' | |||
512 | r = None |
|
588 | r = None | |
513 | header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) |
|
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 | text = mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts) |
|
594 | text = mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts) | |
516 | if text or len(header) > 1: |
|
595 | if text or len(header) > 1: | |
517 | fp.write(''.join(header)) |
|
596 | fp.write(''.join(header)) |
General Comments 0
You need to be logged in to leave comments.
Login now