Mercurial > hg
annotate mercurial/mdiff.py @ 2281:7761597b5da3
prompt user for http authentication info
in interactive mode, mercurial now asks the user for the username and
password when the server requires it. the previous behavior was to fail
with an http 401.
based on patch from eric jaffe <jaffe.eric@gmail.com>.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Sun, 14 May 2006 17:37:17 -0700 |
parents | 35fb62a3a673 |
children | fe1689273f84 |
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 |
9 import struct, bdiff, util, mpatch | |
10 demandload(globals(), "re") | |
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, |
23 showfunc=False, ignorews=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
|
24 |
35 | 25 if not a and not b: return "" |
1379 | 26 epoch = util.datestr((0, 0)) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
27 |
1379 | 28 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
|
29 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
|
30 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
|
31 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
|
32 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
|
33 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
|
34 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
|
35 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
|
36 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
|
37 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
|
38 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
|
39 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
|
40 a = splitnewlines(a) |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
249
diff
changeset
|
41 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
|
42 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
|
43 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
|
44 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
|
45 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
|
46 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
|
47 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
|
48 else: |
2251
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
49 al = splitnewlines(a) |
35fb62a3a673
fix speed regression in mdiff caused by line split bugfix.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2248
diff
changeset
|
50 bl = splitnewlines(b) |
1637 | 51 l = list(bunidiff(a, b, al, bl, "a/" + fn, "b/" + fn, |
52 showfunc=showfunc, ignorews=ignorews)) | |
278
777e388c06d6
unidiff: handle empty diffs more gracefully
mpm@selenic.com
parents:
272
diff
changeset
|
53 if not l: return "" |
272
467cea2bf2d8
diff: use tab to separate date from filename
mpm@selenic.com
parents:
264
diff
changeset
|
54 # difflib uses a space, rather than a tab |
1540
8ca9f5b17257
minor optimization: save some string trash
twaldmann@thinkmo.de
parents:
1452
diff
changeset
|
55 l[0] = "%s\t%s\n" % (l[0][:-2], ad) |
8ca9f5b17257
minor optimization: save some string trash
twaldmann@thinkmo.de
parents:
1452
diff
changeset
|
56 l[1] = "%s\t%s\n" % (l[1][:-2], bd) |
170 | 57 |
58 for ln in xrange(len(l)): | |
59 if l[ln][-1] != '\n': | |
60 l[ln] += "\n\ No newline at end of file\n" | |
61 | |
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
|
62 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
|
63 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
|
64 (' '.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
|
65 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
66 return "".join(l) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
67 |
1637 | 68 # somewhat self contained replacement for difflib.unified_diff |
69 # t1 and t2 are the text to be diffed | |
70 # l1 and l2 are the text broken up into lines | |
71 # header1 and header2 are the filenames for the diff output | |
72 # context is the number of context lines | |
73 # showfunc enables diff -p output | |
74 # ignorews ignores all whitespace changes in the diff | |
75 def bunidiff(t1, t2, l1, l2, header1, header2, context=3, showfunc=False, | |
76 ignorews=False): | |
77 def contextend(l, len): | |
78 ret = l + context | |
79 if ret > len: | |
80 ret = len | |
81 return ret | |
82 | |
83 def contextstart(l): | |
84 ret = l - context | |
85 if ret < 0: | |
86 return 0 | |
87 return ret | |
88 | |
89 def yieldhunk(hunk, header): | |
90 if header: | |
91 for x in header: | |
92 yield x | |
93 (astart, a2, bstart, b2, delta) = hunk | |
94 aend = contextend(a2, len(l1)) | |
95 alen = aend - astart | |
96 blen = b2 - bstart + aend - a2 | |
97 | |
98 func = "" | |
99 if showfunc: | |
100 # walk backwards from the start of the context | |
101 # to find a line starting with an alphanumeric char. | |
102 for x in xrange(astart, -1, -1): | |
103 t = l1[x].rstrip() | |
104 if funcre.match(t): | |
105 func = ' ' + t[:40] | |
106 break | |
107 | |
108 yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen, | |
109 bstart + 1, blen, func) | |
110 for x in delta: | |
111 yield x | |
112 for x in xrange(a2, aend): | |
113 yield ' ' + l1[x] | |
114 | |
115 header = [ "--- %s\t\n" % header1, "+++ %s\t\n" % header2 ] | |
116 | |
117 if showfunc: | |
118 funcre = re.compile('\w') | |
119 if ignorews: | |
120 wsre = re.compile('[ \t]') | |
121 | |
122 # bdiff.blocks gives us the matching sequences in the files. The loop | |
123 # below finds the spaces between those matching sequences and translates | |
124 # them into diff output. | |
125 # | |
126 diff = bdiff.blocks(t1, t2) | |
127 hunk = None | |
128 for i in xrange(len(diff)): | |
129 # The first match is special. | |
130 # we've either found a match starting at line 0 or a match later | |
131 # in the file. If it starts later, old and new below will both be | |
132 # empty and we'll continue to the next match. | |
133 if i > 0: | |
134 s = diff[i-1] | |
135 else: | |
136 s = [0, 0, 0, 0] | |
137 delta = [] | |
138 s1 = diff[i] | |
139 a1 = s[1] | |
140 a2 = s1[0] | |
141 b1 = s[3] | |
142 b2 = s1[2] | |
143 | |
144 old = l1[a1:a2] | |
145 new = l2[b1:b2] | |
146 | |
147 # bdiff sometimes gives huge matches past eof, this check eats them, | |
148 # and deals with the special first match case described above | |
149 if not old and not new: | |
150 continue | |
151 | |
152 if ignorews: | |
153 wsold = wsre.sub('', "".join(old)) | |
154 wsnew = wsre.sub('', "".join(new)) | |
155 if wsold == wsnew: | |
156 continue | |
157 | |
158 astart = contextstart(a1) | |
159 bstart = contextstart(b1) | |
160 prev = None | |
161 if hunk: | |
162 # join with the previous hunk if it falls inside the context | |
163 if astart < hunk[1] + context + 1: | |
164 prev = hunk | |
165 astart = hunk[1] | |
166 bstart = hunk[3] | |
167 else: | |
168 for x in yieldhunk(hunk, header): | |
169 yield x | |
170 # we only want to yield the header if the files differ, and | |
171 # we only want to yield it once. | |
172 header = None | |
173 if prev: | |
174 # we've joined the previous hunk, record the new ending points. | |
175 hunk[1] = a2 | |
176 hunk[3] = b2 | |
177 delta = hunk[4] | |
178 else: | |
179 # create a new hunk | |
180 hunk = [ astart, a2, bstart, b2, delta ] | |
181 | |
182 delta[len(delta):] = [ ' ' + x for x in l1[astart:a1] ] | |
183 delta[len(delta):] = [ '-' + x for x in old ] | |
184 delta[len(delta):] = [ '+' + x for x in new ] | |
185 | |
186 if hunk: | |
187 for x in yieldhunk(hunk, header): | |
188 yield x | |
189 | |
120
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
190 def patchtext(bin): |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
191 pos = 0 |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
192 t = [] |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
193 while pos < len(bin): |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
194 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
|
195 pos += 12 |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
196 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
|
197 pos += l |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
198 return "".join(t) |
bae6f0328f63
Add a function to return the new text from a binary diff
mpm@selenic.com
parents:
75
diff
changeset
|
199 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
200 def patch(a, bin): |
1379 | 201 return mpatch.patches(a, [bin]) |
432 | 202 |
1379 | 203 patches = mpatch.patches |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1723
diff
changeset
|
204 patchedsize = mpatch.patchedsize |
432 | 205 textdiff = bdiff.bdiff |