8 |
8 |
9 import cStringIO, email.Parser, os, errno, re |
9 import cStringIO, email.Parser, os, errno, re |
10 import tempfile, zlib, shutil |
10 import tempfile, zlib, shutil |
11 |
11 |
12 from i18n import _ |
12 from i18n import _ |
13 from node import hex, nullid, short |
13 from node import hex, short |
14 import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error |
14 import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error |
15 import context |
15 import context |
16 |
16 |
17 gitre = re.compile('diff --git a/(.*) b/(.*)') |
17 gitre = re.compile('diff --git a/(.*) b/(.*)') |
18 |
18 |
1511 elif state not in ('hunk', 'git'): |
1511 elif state not in ('hunk', 'git'): |
1512 raise util.Abort(_('unsupported parser state: %s') % state) |
1512 raise util.Abort(_('unsupported parser state: %s') % state) |
1513 return changed |
1513 return changed |
1514 finally: |
1514 finally: |
1515 fp.close() |
1515 fp.close() |
1516 |
|
1517 def b85diff(to, tn): |
|
1518 '''print base85-encoded binary diff''' |
|
1519 def gitindex(text): |
|
1520 if not text: |
|
1521 return hex(nullid) |
|
1522 l = len(text) |
|
1523 s = util.sha1('blob %d\0' % l) |
|
1524 s.update(text) |
|
1525 return s.hexdigest() |
|
1526 |
|
1527 def fmtline(line): |
|
1528 l = len(line) |
|
1529 if l <= 26: |
|
1530 l = chr(ord('A') + l - 1) |
|
1531 else: |
|
1532 l = chr(l - 26 + ord('a') - 1) |
|
1533 return '%c%s\n' % (l, base85.b85encode(line, True)) |
|
1534 |
|
1535 def chunk(text, csize=52): |
|
1536 l = len(text) |
|
1537 i = 0 |
|
1538 while i < l: |
|
1539 yield text[i:i + csize] |
|
1540 i += csize |
|
1541 |
|
1542 tohash = gitindex(to) |
|
1543 tnhash = gitindex(tn) |
|
1544 if tohash == tnhash: |
|
1545 return "" |
|
1546 |
|
1547 # TODO: deltas |
|
1548 ret = ['index %s..%s\nGIT binary patch\nliteral %s\n' % |
|
1549 (tohash, tnhash, len(tn))] |
|
1550 for l in chunk(zlib.compress(tn)): |
|
1551 ret.append(fmtline(l)) |
|
1552 ret.append('\n') |
|
1553 return ''.join(ret) |
|
1554 |
1516 |
1555 class GitDiffRequired(Exception): |
1517 class GitDiffRequired(Exception): |
1556 pass |
1518 pass |
1557 |
1519 |
1558 def diffopts(ui, opts=None, untrusted=False, section='diff'): |
1520 def diffopts(ui, opts=None, untrusted=False, section='diff'): |
1787 if opts.git: |
1749 if opts.git: |
1788 header.insert(0, mdiff.diffline(revs, join(a), join(b), opts)) |
1750 header.insert(0, mdiff.diffline(revs, join(a), join(b), opts)) |
1789 |
1751 |
1790 if dodiff: |
1752 if dodiff: |
1791 if dodiff == 'binary': |
1753 if dodiff == 'binary': |
1792 text = b85diff(to, tn) |
1754 text = mdiff.b85diff(to, tn) |
1793 else: |
1755 else: |
1794 text = mdiff.unidiff(to, date1, |
1756 text = mdiff.unidiff(to, date1, |
1795 # ctx2 date may be dynamic |
1757 # ctx2 date may be dynamic |
1796 tn, util.datestr(ctx2.date()), |
1758 tn, util.datestr(ctx2.date()), |
1797 join(a), join(b), revs, opts=opts) |
1759 join(a), join(b), revs, opts=opts) |