Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/mdiff.py @ 2749:d13e4ffaa79d
[darcs2hg] Windows compatibilty patct
Originally submitted by Daiju Kito
1. single quote didn't work in several cases
2. os.unlink tries to delete tmpfile when it's called. It won't wait like unix.
author | Sébastien Pierre <sebastien@xprima.com> |
---|---|
date | Tue, 01 Aug 2006 09:51:36 -0400 |
parents | a20a1bb0c396 |
children | 345bac2bc4ec |
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 # |
75840796e8e2
mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents:
184
diff
changeset
|
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
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 |
1637 | 8 from demandload import demandload |
2470
fe1689273f84
use demandload more.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2251
diff
changeset
|
9 import bdiff, mpatch |
fe1689273f84
use demandload more.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2251
diff
changeset
|
10 demandload(globals(), "re struct util") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
11 |
2251
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
12 def splitnewlines(text): |
2248
b914f0557832
fix diffs containing embedded "\r".
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2078
diff
changeset
|
13 '''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
|
14 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
|
15 if lines: |
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
16 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
|
17 lines.pop() |
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
18 else: |
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
19 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
|
20 return lines |
2248
b914f0557832
fix diffs containing embedded "\r".
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2078
diff
changeset
|
21 |
1637 | 22 def unidiff(a, ad, b, bd, fn, r=None, text=False, |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
23 showfunc=False, ignorews=False, ignorewsamount=False, |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
24 ignoreblanklines=False): |
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
|
25 |
35 | 26 if not a and not b: return "" |
1379 | 27 epoch = util.datestr((0, 0)) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
28 |
1379 | 29 if not text and (util.binary(a) or util.binary(b)): |
1015
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
582
diff
changeset
|
30 l = ['Binary file %s has changed\n' % fn] |
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
|
31 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
|
32 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
|
33 if a is None: |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
34 l1 = "--- %s\t%s\n" % ("/dev/null", epoch) |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
35 else: |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
36 l1 = "--- %s\t%s\n" % ("a/" + fn, ad) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
37 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd) |
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
38 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
|
39 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
|
40 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
|
41 a = splitnewlines(a) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
42 l1 = "--- %s\t%s\n" % ("a/" + fn, 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
|
43 if b is None: |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
44 l2 = "+++ %s\t%s\n" % ("/dev/null", epoch) |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
45 else: |
fde8fb2cbede
Fix diff against an empty file (issue124) and add a test for this.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1637
diff
changeset
|
46 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
47 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
|
48 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
|
49 else: |
2251
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
50 al = splitnewlines(a) |
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
51 bl = splitnewlines(b) |
1637 | 52 l = list(bunidiff(a, b, al, bl, "a/" + fn, "b/" + fn, |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
53 showfunc=showfunc, ignorews=ignorews, |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
54 ignorewsamount=ignorewsamount, |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
55 ignoreblanklines=ignoreblanklines)) |
278
777e388c06d6
unidiff: handle empty diffs more gracefully
mpm@selenic.com
parents:
272
diff
changeset
|
56 if not l: return "" |
272
467cea2bf2d8
diff: use tab to separate date from filename
mpm@selenic.com
parents:
264
diff
changeset
|
57 # difflib uses a space, rather than a tab |
1540
8ca9f5b17257
minor optimization: save some string trash
twaldmann@thinkmo.de
parents:
1452
diff
changeset
|
58 l[0] = "%s\t%s\n" % (l[0][:-2], ad) |
8ca9f5b17257
minor optimization: save some string trash
twaldmann@thinkmo.de
parents:
1452
diff
changeset
|
59 l[1] = "%s\t%s\n" % (l[1][:-2], bd) |
170 | 60 |
61 for ln in xrange(len(l)): | |
62 if l[ln][-1] != '\n': | |
63 l[ln] += "\n\ No newline at end of file\n" | |
64 | |
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
|
65 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
|
66 l.insert(0, "diff %s %s\n" % |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
361
diff
changeset
|
67 (' '.join(["-r %s" % rev for rev in r]), fn)) |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
361
diff
changeset
|
68 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
69 return "".join(l) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
70 |
1637 | 71 # somewhat self contained replacement for difflib.unified_diff |
72 # t1 and t2 are the text to be diffed | |
73 # l1 and l2 are the text broken up into lines | |
74 # header1 and header2 are the filenames for the diff output | |
75 # context is the number of context lines | |
76 # showfunc enables diff -p output | |
77 # ignorews ignores all whitespace changes in the diff | |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
78 # ignorewsamount ignores changes in the amount of whitespace |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
79 # ignoreblanklines ignores changes whose lines are all blank |
1637 | 80 def bunidiff(t1, t2, l1, l2, header1, header2, context=3, showfunc=False, |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
81 ignorews=False, ignorewsamount=False, ignoreblanklines=False): |
1637 | 82 def contextend(l, len): |
83 ret = l + context | |
84 if ret > len: | |
85 ret = len | |
86 return ret | |
87 | |
88 def contextstart(l): | |
89 ret = l - context | |
90 if ret < 0: | |
91 return 0 | |
92 return ret | |
93 | |
94 def yieldhunk(hunk, header): | |
95 if header: | |
96 for x in header: | |
97 yield x | |
98 (astart, a2, bstart, b2, delta) = hunk | |
99 aend = contextend(a2, len(l1)) | |
100 alen = aend - astart | |
101 blen = b2 - bstart + aend - a2 | |
102 | |
103 func = "" | |
104 if showfunc: | |
105 # walk backwards from the start of the context | |
106 # to find a line starting with an alphanumeric char. | |
107 for x in xrange(astart, -1, -1): | |
108 t = l1[x].rstrip() | |
109 if funcre.match(t): | |
110 func = ' ' + t[:40] | |
111 break | |
112 | |
113 yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen, | |
114 bstart + 1, blen, func) | |
115 for x in delta: | |
116 yield x | |
117 for x in xrange(a2, aend): | |
118 yield ' ' + l1[x] | |
119 | |
120 header = [ "--- %s\t\n" % header1, "+++ %s\t\n" % header2 ] | |
121 | |
122 if showfunc: | |
123 funcre = re.compile('\w') | |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
124 if ignorewsamount: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
125 wsamountre = re.compile('[ \t]+') |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
126 wsappendedre = re.compile(' \n') |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
127 if ignoreblanklines: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
128 wsblanklinesre = re.compile('\n') |
1637 | 129 if ignorews: |
130 wsre = re.compile('[ \t]') | |
131 | |
132 # bdiff.blocks gives us the matching sequences in the files. The loop | |
133 # below finds the spaces between those matching sequences and translates | |
134 # them into diff output. | |
135 # | |
136 diff = bdiff.blocks(t1, t2) | |
137 hunk = None | |
138 for i in xrange(len(diff)): | |
139 # The first match is special. | |
140 # we've either found a match starting at line 0 or a match later | |
141 # in the file. If it starts later, old and new below will both be | |
142 # empty and we'll continue to the next match. | |
143 if i > 0: | |
144 s = diff[i-1] | |
145 else: | |
146 s = [0, 0, 0, 0] | |
147 delta = [] | |
148 s1 = diff[i] | |
149 a1 = s[1] | |
150 a2 = s1[0] | |
151 b1 = s[3] | |
152 b2 = s1[2] | |
153 | |
154 old = l1[a1:a2] | |
155 new = l2[b1:b2] | |
156 | |
157 # bdiff sometimes gives huge matches past eof, this check eats them, | |
158 # and deals with the special first match case described above | |
159 if not old and not new: | |
160 continue | |
161 | |
2580
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
162 if ignoreblanklines: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
163 wsold = wsblanklinesre.sub('', "".join(old)) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
164 wsnew = wsblanklinesre.sub('', "".join(new)) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
165 if wsold == wsnew: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
166 continue |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
167 |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
168 if ignorewsamount: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
169 wsold = wsamountre.sub(' ', "".join(old)) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
170 wsold = wsappendedre.sub('\n', wsold) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
171 wsnew = wsamountre.sub(' ', "".join(new)) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
172 wsnew = wsappendedre.sub('\n', wsnew) |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
173 if wsold == wsnew: |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
174 continue |
a20a1bb0c396
diff: add -b/-B options
Haakon Riiser <haakon.riiser@fys.uio.no>
parents:
2470
diff
changeset
|
175 |
1637 | 176 if ignorews: |
177 wsold = wsre.sub('', "".join(old)) | |
178 wsnew = wsre.sub('', "".join(new)) | |
179 if wsold == wsnew: | |
180 continue | |
181 | |
182 astart = contextstart(a1) | |
183 bstart = contextstart(b1) | |
184 prev = None | |
185 if hunk: | |
186 # join with the previous hunk if it falls inside the context | |
187 if astart < hunk[1] + context + 1: | |
188 prev = hunk | |
189 astart = hunk[1] | |
190 bstart = hunk[3] | |
191 else: | |
192 for x in yieldhunk(hunk, header): | |
193 yield x | |
194 # we only want to yield the header if the files differ, and | |
195 # we only want to yield it once. | |
196 header = None | |
197 if prev: | |
198 # we've joined the previous hunk, record the new ending points. | |
199 hunk[1] = a2 | |
200 hunk[3] = b2 | |
201 delta = hunk[4] | |
202 else: | |
203 # create a new hunk | |
204 hunk = [ astart, a2, bstart, b2, delta ] | |
205 | |
206 delta[len(delta):] = [ ' ' + x for x in l1[astart:a1] ] | |
207 delta[len(delta):] = [ '-' + x for x in old ] | |
208 delta[len(delta):] = [ '+' + x for x in new ] | |
209 | |
210 if hunk: | |
211 for x in yieldhunk(hunk, header): | |
212 yield x | |
213 | |
120
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
214 def patchtext(bin): |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
215 pos = 0 |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
216 t = [] |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
217 while pos < len(bin): |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
218 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
|
219 pos += 12 |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
220 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
|
221 pos += l |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
222 return "".join(t) |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
223 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
224 def patch(a, bin): |
1379 | 225 return mpatch.patches(a, [bin]) |
432 | 226 |
1379 | 227 patches = mpatch.patches |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1723
diff
changeset
|
228 patchedsize = mpatch.patchedsize |
432 | 229 textdiff = bdiff.bdiff |