annotate mercurial/mdiff.py @ 6871:13fe85fe396b

mdiff: compare content of binary files directly A plain Python string comparison stops when the first mismatch is found, whereas the call to md5 would need to compute the hash over the entire string and only then do the comparison.
author Martin Geisler <mg@daimi.au.dk>
date Sat, 09 Aug 2008 02:10:22 +0200
parents ac0bcd951c2c
children ca5ac40949dc
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
239
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
1 # mdiff.py - diff and patch routines for mercurial
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
2 #
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2580
diff changeset
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
239
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
4 #
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
5 # This software may be used and distributed according to the terms
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
6 # of the GNU General Public License, incorporated herein by reference.
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
7
6467
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
8 from i18n import _
6470
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6467
diff changeset
9 import bdiff, mpatch, re, struct, util
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
10
2251
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
11 def splitnewlines(text):
2248
b914f0557832 fix diffs containing embedded "\r".
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2078
diff changeset
12 '''like str.splitlines, but only split on newlines.'''
2251
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
13 lines = [l + '\n' for l in text.split('\n')]
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
14 if lines:
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
15 if lines[-1] == '\n':
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
16 lines.pop()
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
17 else:
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
18 lines[-1] = lines[-1][:-1]
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
19 return lines
2248
b914f0557832 fix diffs containing embedded "\r".
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2078
diff changeset
20
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
21 class diffopts(object):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
22 '''context is the number of context lines
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
23 text treats all files as text
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
24 showfunc enables diff -p output
2907
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2874
diff changeset
25 git enables the git extended patch format
3199
096f1c73cdc3 Add -D/--nodates options to hg diff/export that removes dates from diff headers
Stephen Darnell <stephen@darnell.plus.com>
parents: 3026
diff changeset
26 nodates removes dates from diff headers
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
27 ignorews ignores all whitespace changes in the diff
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
28 ignorewsamount ignores changes in the amount of whitespace
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
29 ignoreblanklines ignores changes whose lines are all blank'''
396
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
30
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
31 defaults = {
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
32 'context': 3,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
33 'text': False,
5863
3d1f9dcecdea diff: don't show function name by default
Matt Mackall <mpm@selenic.com>
parents: 5482
diff changeset
34 'showfunc': False,
2907
8b02af865990 Add diff --git option
Brendan Cully <brendan@kublai.com>
parents: 2874
diff changeset
35 'git': False,
3199
096f1c73cdc3 Add -D/--nodates options to hg diff/export that removes dates from diff headers
Stephen Darnell <stephen@darnell.plus.com>
parents: 3026
diff changeset
36 'nodates': False,
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
37 'ignorews': False,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
38 'ignorewsamount': False,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
39 'ignoreblanklines': False,
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
40 }
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
41
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
42 __slots__ = defaults.keys()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
43
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
44 def __init__(self, **opts):
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
45 for k in self.__slots__:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
46 v = opts.get(k)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
47 if v is None:
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
48 v = self.defaults[k]
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
49 setattr(self, k, v)
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
50
6467
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
51 try:
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
52 self.context = int(self.context)
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
53 except ValueError:
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
54 raise util.Abort(_('diff context lines count must be '
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
55 'an integer, not %r') % self.context)
65029a3aafc2 Let --unified default to diff.unified (issue 1076)
Patrick Mezard <pmezard@gmail.com>
parents: 5863
diff changeset
56
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
57 defaultopts = diffopts()
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
58
4878
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
59 def wsclean(opts, text):
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
60 if opts.ignorews:
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
61 text = re.sub('[ \t]+', '', text)
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
62 elif opts.ignorewsamount:
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
63 text = re.sub('[ \t]+', ' ', text)
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
64 text = re.sub('[ \t]+\n', '\n', text)
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
65 if opts.ignoreblanklines:
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
66 text = re.sub('\n+', '', text)
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
67 return text
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
68
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
69 def unidiff(a, ad, b, bd, fn1, fn2, r=None, opts=defaultopts):
4679
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
70 def datetag(date, addtab=True):
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
71 if not opts.git and not opts.nodates:
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
72 return '\t%s\n' % date
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
73 if addtab and ' ' in fn1:
4679
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
74 return '\t\n'
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
75 return '\n'
3026
d838bfac668d Remove dates from git export file lines - they confuse git-apply
Brendan Cully <brendan@kublai.com>
parents: 2907
diff changeset
76
35
9197c26a414b unidiff: punt on comparing empty files
mpm@selenic.com
parents: 0
diff changeset
77 if not a and not b: return ""
1379
8ee7ce877be2 Clean up mdiff imports
Matt Mackall <mpm@selenic.com>
parents: 1378
diff changeset
78 epoch = util.datestr((0, 0))
264
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
79
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
80 if not opts.text and (util.binary(a) or util.binary(b)):
6871
13fe85fe396b mdiff: compare content of binary files directly
Martin Geisler <mg@daimi.au.dk>
parents: 6470
diff changeset
81 if a and b and len(a) == len(b) and a == b:
4103
544838cc1158 Don't lie that "binary file has changed"
tailgunner@smtp.ru
parents: 3199
diff changeset
82 return ""
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
83 l = ['Binary file %s has changed\n' % fn1]
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
84 elif not a:
2251
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
85 b = splitnewlines(b)
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
86 if a is None:
4679
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
87 l1 = '--- /dev/null%s' % datetag(epoch, False)
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
88 else:
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
89 l1 = "--- %s%s" % ("a/" + fn1, datetag(ad))
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
90 l2 = "+++ %s%s" % ("b/" + fn2, datetag(bd))
264
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
91 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
92 l = [l1, l2, l3] + ["+" + e for e in b]
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
93 elif not b:
2251
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
94 a = splitnewlines(a)
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
95 l1 = "--- %s%s" % ("a/" + fn1, datetag(ad))
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
96 if b is None:
4679
826659bd8053 git patches: correct handling of filenames with spaces
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4361
diff changeset
97 l2 = '+++ /dev/null%s' % datetag(epoch, False)
1723
fde8fb2cbede Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1637
diff changeset
98 else:
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
99 l2 = "+++ %s%s" % ("b/" + fn2, datetag(bd))
264
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
100 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
101 l = [l1, l2, l3] + ["-" + e for e in a]
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
102 else:
2251
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
103 al = splitnewlines(a)
35fb62a3a673 fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2248
diff changeset
104 bl = splitnewlines(b)
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
105 l = list(bunidiff(a, b, al, bl, "a/" + fn1, "b/" + fn2, opts=opts))
278
777e388c06d6 unidiff: handle empty diffs more gracefully
mpm@selenic.com
parents: 272
diff changeset
106 if not l: return ""
272
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
107 # difflib uses a space, rather than a tab
3026
d838bfac668d Remove dates from git export file lines - they confuse git-apply
Brendan Cully <brendan@kublai.com>
parents: 2907
diff changeset
108 l[0] = "%s%s" % (l[0][:-2], datetag(ad))
d838bfac668d Remove dates from git export file lines - they confuse git-apply
Brendan Cully <brendan@kublai.com>
parents: 2907
diff changeset
109 l[1] = "%s%s" % (l[1][:-2], datetag(bd))
170
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
110
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
111 for ln in xrange(len(l)):
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
112 if l[ln][-1] != '\n':
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
113 l[ln] += "\n\ No newline at end of file\n"
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
114
396
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
115 if r:
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
116 l.insert(0, "diff %s %s\n" %
5482
e5eedd74e70f Use both the from and to name in mdiff.unidiff.
Dustin Sallings <dustin@spy.net>
parents: 5367
diff changeset
117 (' '.join(["-r %s" % rev for rev in r]), fn1))
396
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
118
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
119 return "".join(l)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
120
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
121 # somewhat self contained replacement for difflib.unified_diff
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
122 # t1 and t2 are the text to be diffed
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
123 # l1 and l2 are the text broken up into lines
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
124 # header1 and header2 are the filenames for the diff output
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
125 def bunidiff(t1, t2, l1, l2, header1, header2, opts=defaultopts):
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
126 def contextend(l, len):
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
127 ret = l + opts.context
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
128 if ret > len:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
129 ret = len
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
130 return ret
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
131
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
132 def contextstart(l):
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
133 ret = l - opts.context
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
134 if ret < 0:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
135 return 0
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
136 return ret
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
137
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
138 def yieldhunk(hunk, header):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
139 if header:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
140 for x in header:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
141 yield x
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
142 (astart, a2, bstart, b2, delta) = hunk
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
143 aend = contextend(a2, len(l1))
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
144 alen = aend - astart
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
145 blen = b2 - bstart + aend - a2
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
146
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
147 func = ""
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
148 if opts.showfunc:
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
149 # walk backwards from the start of the context
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
150 # to find a line starting with an alphanumeric char.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
151 for x in xrange(astart, -1, -1):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
152 t = l1[x].rstrip()
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
153 if funcre.match(t):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
154 func = ' ' + t[:40]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
155 break
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
156
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
157 yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen,
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
158 bstart + 1, blen, func)
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
159 for x in delta:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
160 yield x
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
161 for x in xrange(a2, aend):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
162 yield ' ' + l1[x]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
163
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
164 header = [ "--- %s\t\n" % header1, "+++ %s\t\n" % header2 ]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
165
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
166 if opts.showfunc:
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
167 funcre = re.compile('\w')
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
168
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
169 # bdiff.blocks gives us the matching sequences in the files. The loop
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
170 # below finds the spaces between those matching sequences and translates
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
171 # them into diff output.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
172 #
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
173 diff = bdiff.blocks(t1, t2)
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
174 hunk = None
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
175 for i in xrange(len(diff)):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
176 # The first match is special.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
177 # we've either found a match starting at line 0 or a match later
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
178 # in the file. If it starts later, old and new below will both be
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
179 # empty and we'll continue to the next match.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
180 if i > 0:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
181 s = diff[i-1]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
182 else:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
183 s = [0, 0, 0, 0]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
184 delta = []
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
185 s1 = diff[i]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
186 a1 = s[1]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
187 a2 = s1[0]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
188 b1 = s[3]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
189 b2 = s1[2]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
190
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
191 old = l1[a1:a2]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
192 new = l2[b1:b2]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
193
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
194 # bdiff sometimes gives huge matches past eof, this check eats them,
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
195 # and deals with the special first match case described above
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
196 if not old and not new:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
197 continue
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
198
4878
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
199 if opts.ignorews or opts.ignorewsamount or opts.ignoreblanklines:
372d93f03d3a diff: correctly handle combinations of whitespace options
Matt Mackall <mpm@selenic.com>
parents: 4679
diff changeset
200 if wsclean(opts, "".join(old)) == wsclean(opts, "".join(new)):
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
201 continue
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
202
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
203 astart = contextstart(a1)
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
204 bstart = contextstart(b1)
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
205 prev = None
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
206 if hunk:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
207 # join with the previous hunk if it falls inside the context
2874
4ec58b157265 refactor text diff/patch code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2859
diff changeset
208 if astart < hunk[1] + opts.context + 1:
1637
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
209 prev = hunk
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
210 astart = hunk[1]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
211 bstart = hunk[3]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
212 else:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
213 for x in yieldhunk(hunk, header):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
214 yield x
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
215 # we only want to yield the header if the files differ, and
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
216 # we only want to yield it once.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
217 header = None
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
218 if prev:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
219 # we've joined the previous hunk, record the new ending points.
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
220 hunk[1] = a2
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
221 hunk[3] = b2
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
222 delta = hunk[4]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
223 else:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
224 # create a new hunk
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
225 hunk = [ astart, a2, bstart, b2, delta ]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
226
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
227 delta[len(delta):] = [ ' ' + x for x in l1[astart:a1] ]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
228 delta[len(delta):] = [ '-' + x for x in old ]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
229 delta[len(delta):] = [ '+' + x for x in new ]
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
230
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
231 if hunk:
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
232 for x in yieldhunk(hunk, header):
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
233 yield x
3b1b44b917f4 Add new bdiff based unidiff generation.
mason@suse.com
parents: 1540
diff changeset
234
120
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
235 def patchtext(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
236 pos = 0
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
237 t = []
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
238 while pos < len(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
239 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
240 pos += 12
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
241 t.append(bin[pos:pos + l])
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
242 pos += l
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
243 return "".join(t)
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
244
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
245 def patch(a, bin):
1379
8ee7ce877be2 Clean up mdiff imports
Matt Mackall <mpm@selenic.com>
parents: 1378
diff changeset
246 return mpatch.patches(a, [bin])
432
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
247
4361
99c853a1408c add mdiff.get_matching_blocks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4108
diff changeset
248 # similar to difflib.SequenceMatcher.get_matching_blocks
99c853a1408c add mdiff.get_matching_blocks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4108
diff changeset
249 def get_matching_blocks(a, b):
99c853a1408c add mdiff.get_matching_blocks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4108
diff changeset
250 return [(d[0], d[2], d[1] - d[0]) for d in bdiff.blocks(a, b)]
99c853a1408c add mdiff.get_matching_blocks
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4108
diff changeset
251
5367
7530334bf301 revlog: generate trivial deltas against null revision
Matt Mackall <mpm@selenic.com>
parents: 4878
diff changeset
252 def trivialdiffheader(length):
7530334bf301 revlog: generate trivial deltas against null revision
Matt Mackall <mpm@selenic.com>
parents: 4878
diff changeset
253 return struct.pack(">lll", 0, 0, length)
7530334bf301 revlog: generate trivial deltas against null revision
Matt Mackall <mpm@selenic.com>
parents: 4878
diff changeset
254
1379
8ee7ce877be2 Clean up mdiff imports
Matt Mackall <mpm@selenic.com>
parents: 1378
diff changeset
255 patches = mpatch.patches
2078
441ea218414e Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents: 1723
diff changeset
256 patchedsize = mpatch.patchedsize
432
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
257 textdiff = bdiff.bdiff