##// END OF EJS Templates
mdiff: use absolute_import
Gregory Szorc -
r27484:0d7635dc default
parent child Browse files
Show More
@@ -1,375 +1,386
1 # mdiff.py - diff and patch routines for mercurial
1 # mdiff.py - diff and patch routines for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from __future__ import absolute_import
9 import bdiff, mpatch, util, base85, error
9
10 import re, struct, zlib
10 import re
11 import struct
12 import zlib
13
14 from .i18n import _
15 from . import (
16 base85,
17 bdiff,
18 error,
19 mpatch,
20 util,
21 )
11
22
12 def splitnewlines(text):
23 def splitnewlines(text):
13 '''like str.splitlines, but only split on newlines.'''
24 '''like str.splitlines, but only split on newlines.'''
14 lines = [l + '\n' for l in text.split('\n')]
25 lines = [l + '\n' for l in text.split('\n')]
15 if lines:
26 if lines:
16 if lines[-1] == '\n':
27 if lines[-1] == '\n':
17 lines.pop()
28 lines.pop()
18 else:
29 else:
19 lines[-1] = lines[-1][:-1]
30 lines[-1] = lines[-1][:-1]
20 return lines
31 return lines
21
32
22 class diffopts(object):
33 class diffopts(object):
23 '''context is the number of context lines
34 '''context is the number of context lines
24 text treats all files as text
35 text treats all files as text
25 showfunc enables diff -p output
36 showfunc enables diff -p output
26 git enables the git extended patch format
37 git enables the git extended patch format
27 nodates removes dates from diff headers
38 nodates removes dates from diff headers
28 nobinary ignores binary files
39 nobinary ignores binary files
29 noprefix disables the 'a/' and 'b/' prefixes (ignored in plain mode)
40 noprefix disables the 'a/' and 'b/' prefixes (ignored in plain mode)
30 ignorews ignores all whitespace changes in the diff
41 ignorews ignores all whitespace changes in the diff
31 ignorewsamount ignores changes in the amount of whitespace
42 ignorewsamount ignores changes in the amount of whitespace
32 ignoreblanklines ignores changes whose lines are all blank
43 ignoreblanklines ignores changes whose lines are all blank
33 upgrade generates git diffs to avoid data loss
44 upgrade generates git diffs to avoid data loss
34 '''
45 '''
35
46
36 defaults = {
47 defaults = {
37 'context': 3,
48 'context': 3,
38 'text': False,
49 'text': False,
39 'showfunc': False,
50 'showfunc': False,
40 'git': False,
51 'git': False,
41 'nodates': False,
52 'nodates': False,
42 'nobinary': False,
53 'nobinary': False,
43 'noprefix': False,
54 'noprefix': False,
44 'ignorews': False,
55 'ignorews': False,
45 'ignorewsamount': False,
56 'ignorewsamount': False,
46 'ignoreblanklines': False,
57 'ignoreblanklines': False,
47 'upgrade': False,
58 'upgrade': False,
48 }
59 }
49
60
50 __slots__ = defaults.keys()
61 __slots__ = defaults.keys()
51
62
52 def __init__(self, **opts):
63 def __init__(self, **opts):
53 for k in self.__slots__:
64 for k in self.__slots__:
54 v = opts.get(k)
65 v = opts.get(k)
55 if v is None:
66 if v is None:
56 v = self.defaults[k]
67 v = self.defaults[k]
57 setattr(self, k, v)
68 setattr(self, k, v)
58
69
59 try:
70 try:
60 self.context = int(self.context)
71 self.context = int(self.context)
61 except ValueError:
72 except ValueError:
62 raise error.Abort(_('diff context lines count must be '
73 raise error.Abort(_('diff context lines count must be '
63 'an integer, not %r') % self.context)
74 'an integer, not %r') % self.context)
64
75
65 def copy(self, **kwargs):
76 def copy(self, **kwargs):
66 opts = dict((k, getattr(self, k)) for k in self.defaults)
77 opts = dict((k, getattr(self, k)) for k in self.defaults)
67 opts.update(kwargs)
78 opts.update(kwargs)
68 return diffopts(**opts)
79 return diffopts(**opts)
69
80
70 defaultopts = diffopts()
81 defaultopts = diffopts()
71
82
72 def wsclean(opts, text, blank=True):
83 def wsclean(opts, text, blank=True):
73 if opts.ignorews:
84 if opts.ignorews:
74 text = bdiff.fixws(text, 1)
85 text = bdiff.fixws(text, 1)
75 elif opts.ignorewsamount:
86 elif opts.ignorewsamount:
76 text = bdiff.fixws(text, 0)
87 text = bdiff.fixws(text, 0)
77 if blank and opts.ignoreblanklines:
88 if blank and opts.ignoreblanklines:
78 text = re.sub('\n+', '\n', text).strip('\n')
89 text = re.sub('\n+', '\n', text).strip('\n')
79 return text
90 return text
80
91
81 def splitblock(base1, lines1, base2, lines2, opts):
92 def splitblock(base1, lines1, base2, lines2, opts):
82 # The input lines matches except for interwoven blank lines. We
93 # The input lines matches except for interwoven blank lines. We
83 # transform it into a sequence of matching blocks and blank blocks.
94 # transform it into a sequence of matching blocks and blank blocks.
84 lines1 = [(wsclean(opts, l) and 1 or 0) for l in lines1]
95 lines1 = [(wsclean(opts, l) and 1 or 0) for l in lines1]
85 lines2 = [(wsclean(opts, l) and 1 or 0) for l in lines2]
96 lines2 = [(wsclean(opts, l) and 1 or 0) for l in lines2]
86 s1, e1 = 0, len(lines1)
97 s1, e1 = 0, len(lines1)
87 s2, e2 = 0, len(lines2)
98 s2, e2 = 0, len(lines2)
88 while s1 < e1 or s2 < e2:
99 while s1 < e1 or s2 < e2:
89 i1, i2, btype = s1, s2, '='
100 i1, i2, btype = s1, s2, '='
90 if (i1 >= e1 or lines1[i1] == 0
101 if (i1 >= e1 or lines1[i1] == 0
91 or i2 >= e2 or lines2[i2] == 0):
102 or i2 >= e2 or lines2[i2] == 0):
92 # Consume the block of blank lines
103 # Consume the block of blank lines
93 btype = '~'
104 btype = '~'
94 while i1 < e1 and lines1[i1] == 0:
105 while i1 < e1 and lines1[i1] == 0:
95 i1 += 1
106 i1 += 1
96 while i2 < e2 and lines2[i2] == 0:
107 while i2 < e2 and lines2[i2] == 0:
97 i2 += 1
108 i2 += 1
98 else:
109 else:
99 # Consume the matching lines
110 # Consume the matching lines
100 while i1 < e1 and lines1[i1] == 1 and lines2[i2] == 1:
111 while i1 < e1 and lines1[i1] == 1 and lines2[i2] == 1:
101 i1 += 1
112 i1 += 1
102 i2 += 1
113 i2 += 1
103 yield [base1 + s1, base1 + i1, base2 + s2, base2 + i2], btype
114 yield [base1 + s1, base1 + i1, base2 + s2, base2 + i2], btype
104 s1 = i1
115 s1 = i1
105 s2 = i2
116 s2 = i2
106
117
107 def allblocks(text1, text2, opts=None, lines1=None, lines2=None, refine=False):
118 def allblocks(text1, text2, opts=None, lines1=None, lines2=None, refine=False):
108 """Return (block, type) tuples, where block is an mdiff.blocks
119 """Return (block, type) tuples, where block is an mdiff.blocks
109 line entry. type is '=' for blocks matching exactly one another
120 line entry. type is '=' for blocks matching exactly one another
110 (bdiff blocks), '!' for non-matching blocks and '~' for blocks
121 (bdiff blocks), '!' for non-matching blocks and '~' for blocks
111 matching only after having filtered blank lines. If refine is True,
122 matching only after having filtered blank lines. If refine is True,
112 then '~' blocks are refined and are only made of blank lines.
123 then '~' blocks are refined and are only made of blank lines.
113 line1 and line2 are text1 and text2 split with splitnewlines() if
124 line1 and line2 are text1 and text2 split with splitnewlines() if
114 they are already available.
125 they are already available.
115 """
126 """
116 if opts is None:
127 if opts is None:
117 opts = defaultopts
128 opts = defaultopts
118 if opts.ignorews or opts.ignorewsamount:
129 if opts.ignorews or opts.ignorewsamount:
119 text1 = wsclean(opts, text1, False)
130 text1 = wsclean(opts, text1, False)
120 text2 = wsclean(opts, text2, False)
131 text2 = wsclean(opts, text2, False)
121 diff = bdiff.blocks(text1, text2)
132 diff = bdiff.blocks(text1, text2)
122 for i, s1 in enumerate(diff):
133 for i, s1 in enumerate(diff):
123 # The first match is special.
134 # The first match is special.
124 # we've either found a match starting at line 0 or a match later
135 # we've either found a match starting at line 0 or a match later
125 # in the file. If it starts later, old and new below will both be
136 # in the file. If it starts later, old and new below will both be
126 # empty and we'll continue to the next match.
137 # empty and we'll continue to the next match.
127 if i > 0:
138 if i > 0:
128 s = diff[i - 1]
139 s = diff[i - 1]
129 else:
140 else:
130 s = [0, 0, 0, 0]
141 s = [0, 0, 0, 0]
131 s = [s[1], s1[0], s[3], s1[2]]
142 s = [s[1], s1[0], s[3], s1[2]]
132
143
133 # bdiff sometimes gives huge matches past eof, this check eats them,
144 # bdiff sometimes gives huge matches past eof, this check eats them,
134 # and deals with the special first match case described above
145 # and deals with the special first match case described above
135 if s[0] != s[1] or s[2] != s[3]:
146 if s[0] != s[1] or s[2] != s[3]:
136 type = '!'
147 type = '!'
137 if opts.ignoreblanklines:
148 if opts.ignoreblanklines:
138 if lines1 is None:
149 if lines1 is None:
139 lines1 = splitnewlines(text1)
150 lines1 = splitnewlines(text1)
140 if lines2 is None:
151 if lines2 is None:
141 lines2 = splitnewlines(text2)
152 lines2 = splitnewlines(text2)
142 old = wsclean(opts, "".join(lines1[s[0]:s[1]]))
153 old = wsclean(opts, "".join(lines1[s[0]:s[1]]))
143 new = wsclean(opts, "".join(lines2[s[2]:s[3]]))
154 new = wsclean(opts, "".join(lines2[s[2]:s[3]]))
144 if old == new:
155 if old == new:
145 type = '~'
156 type = '~'
146 yield s, type
157 yield s, type
147 yield s1, '='
158 yield s1, '='
148
159
149 def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
160 def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
150 def datetag(date, fn=None):
161 def datetag(date, fn=None):
151 if not opts.git and not opts.nodates:
162 if not opts.git and not opts.nodates:
152 return '\t%s\n' % date
163 return '\t%s\n' % date
153 if fn and ' ' in fn:
164 if fn and ' ' in fn:
154 return '\t\n'
165 return '\t\n'
155 return '\n'
166 return '\n'
156
167
157 if not a and not b:
168 if not a and not b:
158 return ""
169 return ""
159
170
160 if opts.noprefix:
171 if opts.noprefix:
161 aprefix = bprefix = ''
172 aprefix = bprefix = ''
162 else:
173 else:
163 aprefix = 'a/'
174 aprefix = 'a/'
164 bprefix = 'b/'
175 bprefix = 'b/'
165
176
166 epoch = util.datestr((0, 0))
177 epoch = util.datestr((0, 0))
167
178
168 fn1 = util.pconvert(fn1)
179 fn1 = util.pconvert(fn1)
169 fn2 = util.pconvert(fn2)
180 fn2 = util.pconvert(fn2)
170
181
171 if not opts.text and (util.binary(a) or util.binary(b)):
182 if not opts.text and (util.binary(a) or util.binary(b)):
172 if a and b and len(a) == len(b) and a == b:
183 if a and b and len(a) == len(b) and a == b:
173 return ""
184 return ""
174 l = ['Binary file %s has changed\n' % fn1]
185 l = ['Binary file %s has changed\n' % fn1]
175 elif not a:
186 elif not a:
176 b = splitnewlines(b)
187 b = splitnewlines(b)
177 if a is None:
188 if a is None:
178 l1 = '--- /dev/null%s' % datetag(epoch)
189 l1 = '--- /dev/null%s' % datetag(epoch)
179 else:
190 else:
180 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
191 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
181 l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2))
192 l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2))
182 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
193 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
183 l = [l1, l2, l3] + ["+" + e for e in b]
194 l = [l1, l2, l3] + ["+" + e for e in b]
184 elif not b:
195 elif not b:
185 a = splitnewlines(a)
196 a = splitnewlines(a)
186 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
197 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
187 if b is None:
198 if b is None:
188 l2 = '+++ /dev/null%s' % datetag(epoch)
199 l2 = '+++ /dev/null%s' % datetag(epoch)
189 else:
200 else:
190 l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))
201 l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))
191 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
202 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
192 l = [l1, l2, l3] + ["-" + e for e in a]
203 l = [l1, l2, l3] + ["-" + e for e in a]
193 else:
204 else:
194 al = splitnewlines(a)
205 al = splitnewlines(a)
195 bl = splitnewlines(b)
206 bl = splitnewlines(b)
196 l = list(_unidiff(a, b, al, bl, opts=opts))
207 l = list(_unidiff(a, b, al, bl, opts=opts))
197 if not l:
208 if not l:
198 return ""
209 return ""
199
210
200 l.insert(0, "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)))
211 l.insert(0, "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)))
201 l.insert(1, "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)))
212 l.insert(1, "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)))
202
213
203 for ln in xrange(len(l)):
214 for ln in xrange(len(l)):
204 if l[ln][-1] != '\n':
215 if l[ln][-1] != '\n':
205 l[ln] += "\n\ No newline at end of file\n"
216 l[ln] += "\n\ No newline at end of file\n"
206
217
207 return "".join(l)
218 return "".join(l)
208
219
209 # creates a headerless unified diff
220 # creates a headerless unified diff
210 # t1 and t2 are the text to be diffed
221 # t1 and t2 are the text to be diffed
211 # l1 and l2 are the text broken up into lines
222 # l1 and l2 are the text broken up into lines
212 def _unidiff(t1, t2, l1, l2, opts=defaultopts):
223 def _unidiff(t1, t2, l1, l2, opts=defaultopts):
213 def contextend(l, len):
224 def contextend(l, len):
214 ret = l + opts.context
225 ret = l + opts.context
215 if ret > len:
226 if ret > len:
216 ret = len
227 ret = len
217 return ret
228 return ret
218
229
219 def contextstart(l):
230 def contextstart(l):
220 ret = l - opts.context
231 ret = l - opts.context
221 if ret < 0:
232 if ret < 0:
222 return 0
233 return 0
223 return ret
234 return ret
224
235
225 lastfunc = [0, '']
236 lastfunc = [0, '']
226 def yieldhunk(hunk):
237 def yieldhunk(hunk):
227 (astart, a2, bstart, b2, delta) = hunk
238 (astart, a2, bstart, b2, delta) = hunk
228 aend = contextend(a2, len(l1))
239 aend = contextend(a2, len(l1))
229 alen = aend - astart
240 alen = aend - astart
230 blen = b2 - bstart + aend - a2
241 blen = b2 - bstart + aend - a2
231
242
232 func = ""
243 func = ""
233 if opts.showfunc:
244 if opts.showfunc:
234 lastpos, func = lastfunc
245 lastpos, func = lastfunc
235 # walk backwards from the start of the context up to the start of
246 # walk backwards from the start of the context up to the start of
236 # the previous hunk context until we find a line starting with an
247 # the previous hunk context until we find a line starting with an
237 # alphanumeric char.
248 # alphanumeric char.
238 for i in xrange(astart - 1, lastpos - 1, -1):
249 for i in xrange(astart - 1, lastpos - 1, -1):
239 if l1[i][0].isalnum():
250 if l1[i][0].isalnum():
240 func = ' ' + l1[i].rstrip()[:40]
251 func = ' ' + l1[i].rstrip()[:40]
241 lastfunc[1] = func
252 lastfunc[1] = func
242 break
253 break
243 # by recording this hunk's starting point as the next place to
254 # by recording this hunk's starting point as the next place to
244 # start looking for function lines, we avoid reading any line in
255 # start looking for function lines, we avoid reading any line in
245 # the file more than once.
256 # the file more than once.
246 lastfunc[0] = astart
257 lastfunc[0] = astart
247
258
248 # zero-length hunk ranges report their start line as one less
259 # zero-length hunk ranges report their start line as one less
249 if alen:
260 if alen:
250 astart += 1
261 astart += 1
251 if blen:
262 if blen:
252 bstart += 1
263 bstart += 1
253
264
254 yield "@@ -%d,%d +%d,%d @@%s\n" % (astart, alen,
265 yield "@@ -%d,%d +%d,%d @@%s\n" % (astart, alen,
255 bstart, blen, func)
266 bstart, blen, func)
256 for x in delta:
267 for x in delta:
257 yield x
268 yield x
258 for x in xrange(a2, aend):
269 for x in xrange(a2, aend):
259 yield ' ' + l1[x]
270 yield ' ' + l1[x]
260
271
261 # bdiff.blocks gives us the matching sequences in the files. The loop
272 # bdiff.blocks gives us the matching sequences in the files. The loop
262 # below finds the spaces between those matching sequences and translates
273 # below finds the spaces between those matching sequences and translates
263 # them into diff output.
274 # them into diff output.
264 #
275 #
265 hunk = None
276 hunk = None
266 ignoredlines = 0
277 ignoredlines = 0
267 for s, stype in allblocks(t1, t2, opts, l1, l2):
278 for s, stype in allblocks(t1, t2, opts, l1, l2):
268 a1, a2, b1, b2 = s
279 a1, a2, b1, b2 = s
269 if stype != '!':
280 if stype != '!':
270 if stype == '~':
281 if stype == '~':
271 # The diff context lines are based on t1 content. When
282 # The diff context lines are based on t1 content. When
272 # blank lines are ignored, the new lines offsets must
283 # blank lines are ignored, the new lines offsets must
273 # be adjusted as if equivalent blocks ('~') had the
284 # be adjusted as if equivalent blocks ('~') had the
274 # same sizes on both sides.
285 # same sizes on both sides.
275 ignoredlines += (b2 - b1) - (a2 - a1)
286 ignoredlines += (b2 - b1) - (a2 - a1)
276 continue
287 continue
277 delta = []
288 delta = []
278 old = l1[a1:a2]
289 old = l1[a1:a2]
279 new = l2[b1:b2]
290 new = l2[b1:b2]
280
291
281 b1 -= ignoredlines
292 b1 -= ignoredlines
282 b2 -= ignoredlines
293 b2 -= ignoredlines
283 astart = contextstart(a1)
294 astart = contextstart(a1)
284 bstart = contextstart(b1)
295 bstart = contextstart(b1)
285 prev = None
296 prev = None
286 if hunk:
297 if hunk:
287 # join with the previous hunk if it falls inside the context
298 # join with the previous hunk if it falls inside the context
288 if astart < hunk[1] + opts.context + 1:
299 if astart < hunk[1] + opts.context + 1:
289 prev = hunk
300 prev = hunk
290 astart = hunk[1]
301 astart = hunk[1]
291 bstart = hunk[3]
302 bstart = hunk[3]
292 else:
303 else:
293 for x in yieldhunk(hunk):
304 for x in yieldhunk(hunk):
294 yield x
305 yield x
295 if prev:
306 if prev:
296 # we've joined the previous hunk, record the new ending points.
307 # we've joined the previous hunk, record the new ending points.
297 hunk[1] = a2
308 hunk[1] = a2
298 hunk[3] = b2
309 hunk[3] = b2
299 delta = hunk[4]
310 delta = hunk[4]
300 else:
311 else:
301 # create a new hunk
312 # create a new hunk
302 hunk = [astart, a2, bstart, b2, delta]
313 hunk = [astart, a2, bstart, b2, delta]
303
314
304 delta[len(delta):] = [' ' + x for x in l1[astart:a1]]
315 delta[len(delta):] = [' ' + x for x in l1[astart:a1]]
305 delta[len(delta):] = ['-' + x for x in old]
316 delta[len(delta):] = ['-' + x for x in old]
306 delta[len(delta):] = ['+' + x for x in new]
317 delta[len(delta):] = ['+' + x for x in new]
307
318
308 if hunk:
319 if hunk:
309 for x in yieldhunk(hunk):
320 for x in yieldhunk(hunk):
310 yield x
321 yield x
311
322
312 def b85diff(to, tn):
323 def b85diff(to, tn):
313 '''print base85-encoded binary diff'''
324 '''print base85-encoded binary diff'''
314 def fmtline(line):
325 def fmtline(line):
315 l = len(line)
326 l = len(line)
316 if l <= 26:
327 if l <= 26:
317 l = chr(ord('A') + l - 1)
328 l = chr(ord('A') + l - 1)
318 else:
329 else:
319 l = chr(l - 26 + ord('a') - 1)
330 l = chr(l - 26 + ord('a') - 1)
320 return '%c%s\n' % (l, base85.b85encode(line, True))
331 return '%c%s\n' % (l, base85.b85encode(line, True))
321
332
322 def chunk(text, csize=52):
333 def chunk(text, csize=52):
323 l = len(text)
334 l = len(text)
324 i = 0
335 i = 0
325 while i < l:
336 while i < l:
326 yield text[i:i + csize]
337 yield text[i:i + csize]
327 i += csize
338 i += csize
328
339
329 if to is None:
340 if to is None:
330 to = ''
341 to = ''
331 if tn is None:
342 if tn is None:
332 tn = ''
343 tn = ''
333
344
334 if to == tn:
345 if to == tn:
335 return ''
346 return ''
336
347
337 # TODO: deltas
348 # TODO: deltas
338 ret = []
349 ret = []
339 ret.append('GIT binary patch\n')
350 ret.append('GIT binary patch\n')
340 ret.append('literal %s\n' % len(tn))
351 ret.append('literal %s\n' % len(tn))
341 for l in chunk(zlib.compress(tn)):
352 for l in chunk(zlib.compress(tn)):
342 ret.append(fmtline(l))
353 ret.append(fmtline(l))
343 ret.append('\n')
354 ret.append('\n')
344
355
345 return ''.join(ret)
356 return ''.join(ret)
346
357
347 def patchtext(bin):
358 def patchtext(bin):
348 pos = 0
359 pos = 0
349 t = []
360 t = []
350 while pos < len(bin):
361 while pos < len(bin):
351 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
362 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
352 pos += 12
363 pos += 12
353 t.append(bin[pos:pos + l])
364 t.append(bin[pos:pos + l])
354 pos += l
365 pos += l
355 return "".join(t)
366 return "".join(t)
356
367
357 def patch(a, bin):
368 def patch(a, bin):
358 if len(a) == 0:
369 if len(a) == 0:
359 # skip over trivial delta header
370 # skip over trivial delta header
360 return util.buffer(bin, 12)
371 return util.buffer(bin, 12)
361 return mpatch.patches(a, [bin])
372 return mpatch.patches(a, [bin])
362
373
363 # similar to difflib.SequenceMatcher.get_matching_blocks
374 # similar to difflib.SequenceMatcher.get_matching_blocks
364 def get_matching_blocks(a, b):
375 def get_matching_blocks(a, b):
365 return [(d[0], d[2], d[1] - d[0]) for d in bdiff.blocks(a, b)]
376 return [(d[0], d[2], d[1] - d[0]) for d in bdiff.blocks(a, b)]
366
377
367 def trivialdiffheader(length):
378 def trivialdiffheader(length):
368 return struct.pack(">lll", 0, 0, length)
379 return struct.pack(">lll", 0, 0, length)
369
380
370 def replacediffheader(oldlen, newlen):
381 def replacediffheader(oldlen, newlen):
371 return struct.pack(">lll", 0, oldlen, newlen)
382 return struct.pack(">lll", 0, oldlen, newlen)
372
383
373 patches = mpatch.patches
384 patches = mpatch.patches
374 patchedsize = mpatch.patchedsize
385 patchedsize = mpatch.patchedsize
375 textdiff = bdiff.bdiff
386 textdiff = bdiff.bdiff
@@ -1,202 +1,201
1 #require test-repo
1 #require test-repo
2
2
3 $ cd "$TESTDIR"/..
3 $ cd "$TESTDIR"/..
4
4
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 contrib/casesmash.py not using absolute_import
6 contrib/casesmash.py not using absolute_import
7 contrib/check-code.py not using absolute_import
7 contrib/check-code.py not using absolute_import
8 contrib/check-code.py requires print_function
8 contrib/check-code.py requires print_function
9 contrib/check-config.py not using absolute_import
9 contrib/check-config.py not using absolute_import
10 contrib/check-config.py requires print_function
10 contrib/check-config.py requires print_function
11 contrib/debugcmdserver.py not using absolute_import
11 contrib/debugcmdserver.py not using absolute_import
12 contrib/debugcmdserver.py requires print_function
12 contrib/debugcmdserver.py requires print_function
13 contrib/debugshell.py not using absolute_import
13 contrib/debugshell.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
14 contrib/fixpax.py not using absolute_import
15 contrib/fixpax.py requires print_function
15 contrib/fixpax.py requires print_function
16 contrib/hgclient.py not using absolute_import
16 contrib/hgclient.py not using absolute_import
17 contrib/hgclient.py requires print_function
17 contrib/hgclient.py requires print_function
18 contrib/hgfixes/fix_bytes.py not using absolute_import
18 contrib/hgfixes/fix_bytes.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
21 contrib/import-checker.py not using absolute_import
22 contrib/import-checker.py requires print_function
22 contrib/import-checker.py requires print_function
23 contrib/memory.py not using absolute_import
23 contrib/memory.py not using absolute_import
24 contrib/perf.py not using absolute_import
24 contrib/perf.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
25 contrib/python-hook-examples.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
26 contrib/revsetbenchmarks.py not using absolute_import
27 contrib/revsetbenchmarks.py requires print_function
27 contrib/revsetbenchmarks.py requires print_function
28 contrib/showstack.py not using absolute_import
28 contrib/showstack.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
29 contrib/synthrepo.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
31 doc/check-seclevel.py not using absolute_import
32 doc/gendoc.py not using absolute_import
32 doc/gendoc.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
33 doc/hgmanpage.py not using absolute_import
34 hgext/__init__.py not using absolute_import
34 hgext/__init__.py not using absolute_import
35 hgext/acl.py not using absolute_import
35 hgext/acl.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
36 hgext/blackbox.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
37 hgext/bugzilla.py not using absolute_import
38 hgext/censor.py not using absolute_import
38 hgext/censor.py not using absolute_import
39 hgext/children.py not using absolute_import
39 hgext/children.py not using absolute_import
40 hgext/churn.py not using absolute_import
40 hgext/churn.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
41 hgext/clonebundles.py not using absolute_import
42 hgext/color.py not using absolute_import
42 hgext/color.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
43 hgext/convert/__init__.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
44 hgext/convert/bzr.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
45 hgext/convert/common.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
46 hgext/convert/convcmd.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
47 hgext/convert/cvs.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
48 hgext/convert/cvsps.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
49 hgext/convert/darcs.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
50 hgext/convert/filemap.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
51 hgext/convert/git.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
52 hgext/convert/gnuarch.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
53 hgext/convert/hg.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
54 hgext/convert/monotone.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
55 hgext/convert/p4.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
56 hgext/convert/subversion.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
57 hgext/convert/transport.py not using absolute_import
58 hgext/eol.py not using absolute_import
58 hgext/eol.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
59 hgext/extdiff.py not using absolute_import
60 hgext/factotum.py not using absolute_import
60 hgext/factotum.py not using absolute_import
61 hgext/fetch.py not using absolute_import
61 hgext/fetch.py not using absolute_import
62 hgext/gpg.py not using absolute_import
62 hgext/gpg.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
63 hgext/graphlog.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
64 hgext/hgcia.py not using absolute_import
65 hgext/hgk.py not using absolute_import
65 hgext/hgk.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
66 hgext/highlight/__init__.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
67 hgext/highlight/highlight.py not using absolute_import
68 hgext/histedit.py not using absolute_import
68 hgext/histedit.py not using absolute_import
69 hgext/keyword.py not using absolute_import
69 hgext/keyword.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
70 hgext/largefiles/__init__.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
71 hgext/largefiles/basestore.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
72 hgext/largefiles/lfcommands.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
73 hgext/largefiles/lfutil.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
74 hgext/largefiles/localstore.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
75 hgext/largefiles/overrides.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
76 hgext/largefiles/proto.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
77 hgext/largefiles/remotestore.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
78 hgext/largefiles/reposetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
79 hgext/largefiles/uisetup.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
80 hgext/largefiles/wirestore.py not using absolute_import
81 hgext/mq.py not using absolute_import
81 hgext/mq.py not using absolute_import
82 hgext/notify.py not using absolute_import
82 hgext/notify.py not using absolute_import
83 hgext/pager.py not using absolute_import
83 hgext/pager.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
84 hgext/patchbomb.py not using absolute_import
85 hgext/purge.py not using absolute_import
85 hgext/purge.py not using absolute_import
86 hgext/rebase.py not using absolute_import
86 hgext/rebase.py not using absolute_import
87 hgext/record.py not using absolute_import
87 hgext/record.py not using absolute_import
88 hgext/relink.py not using absolute_import
88 hgext/relink.py not using absolute_import
89 hgext/schemes.py not using absolute_import
89 hgext/schemes.py not using absolute_import
90 hgext/share.py not using absolute_import
90 hgext/share.py not using absolute_import
91 hgext/shelve.py not using absolute_import
91 hgext/shelve.py not using absolute_import
92 hgext/strip.py not using absolute_import
92 hgext/strip.py not using absolute_import
93 hgext/transplant.py not using absolute_import
93 hgext/transplant.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
94 hgext/win32mbcs.py not using absolute_import
95 hgext/win32text.py not using absolute_import
95 hgext/win32text.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
96 hgext/zeroconf/Zeroconf.py not using absolute_import
97 hgext/zeroconf/Zeroconf.py requires print_function
97 hgext/zeroconf/Zeroconf.py requires print_function
98 hgext/zeroconf/__init__.py not using absolute_import
98 hgext/zeroconf/__init__.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
99 i18n/check-translation.py not using absolute_import
100 i18n/polib.py not using absolute_import
100 i18n/polib.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
101 mercurial/byterange.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
102 mercurial/cmdutil.py not using absolute_import
103 mercurial/commands.py not using absolute_import
103 mercurial/commands.py not using absolute_import
104 mercurial/context.py not using absolute_import
104 mercurial/context.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
105 mercurial/dirstate.py not using absolute_import
106 mercurial/dispatch.py requires print_function
106 mercurial/dispatch.py requires print_function
107 mercurial/exchange.py not using absolute_import
107 mercurial/exchange.py not using absolute_import
108 mercurial/httpclient/__init__.py not using absolute_import
108 mercurial/httpclient/__init__.py not using absolute_import
109 mercurial/httpclient/_readers.py not using absolute_import
109 mercurial/httpclient/_readers.py not using absolute_import
110 mercurial/httpclient/socketutil.py not using absolute_import
110 mercurial/httpclient/socketutil.py not using absolute_import
111 mercurial/httpconnection.py not using absolute_import
111 mercurial/httpconnection.py not using absolute_import
112 mercurial/keepalive.py not using absolute_import
112 mercurial/keepalive.py not using absolute_import
113 mercurial/keepalive.py requires print_function
113 mercurial/keepalive.py requires print_function
114 mercurial/localrepo.py not using absolute_import
114 mercurial/localrepo.py not using absolute_import
115 mercurial/lsprof.py requires print_function
115 mercurial/lsprof.py requires print_function
116 mercurial/lsprofcalltree.py not using absolute_import
116 mercurial/lsprofcalltree.py not using absolute_import
117 mercurial/lsprofcalltree.py requires print_function
117 mercurial/lsprofcalltree.py requires print_function
118 mercurial/mail.py requires print_function
118 mercurial/mail.py requires print_function
119 mercurial/manifest.py not using absolute_import
119 mercurial/manifest.py not using absolute_import
120 mercurial/mdiff.py not using absolute_import
121 mercurial/patch.py not using absolute_import
120 mercurial/patch.py not using absolute_import
122 mercurial/pvec.py not using absolute_import
121 mercurial/pvec.py not using absolute_import
123 mercurial/py3kcompat.py not using absolute_import
122 mercurial/py3kcompat.py not using absolute_import
124 setup.py not using absolute_import
123 setup.py not using absolute_import
125 tests/filterpyflakes.py requires print_function
124 tests/filterpyflakes.py requires print_function
126 tests/generate-working-copy-states.py requires print_function
125 tests/generate-working-copy-states.py requires print_function
127 tests/get-with-headers.py requires print_function
126 tests/get-with-headers.py requires print_function
128 tests/heredoctest.py requires print_function
127 tests/heredoctest.py requires print_function
129 tests/hypothesishelpers.py not using absolute_import
128 tests/hypothesishelpers.py not using absolute_import
130 tests/hypothesishelpers.py requires print_function
129 tests/hypothesishelpers.py requires print_function
131 tests/killdaemons.py not using absolute_import
130 tests/killdaemons.py not using absolute_import
132 tests/md5sum.py not using absolute_import
131 tests/md5sum.py not using absolute_import
133 tests/mockblackbox.py not using absolute_import
132 tests/mockblackbox.py not using absolute_import
134 tests/printenv.py not using absolute_import
133 tests/printenv.py not using absolute_import
135 tests/readlink.py not using absolute_import
134 tests/readlink.py not using absolute_import
136 tests/readlink.py requires print_function
135 tests/readlink.py requires print_function
137 tests/revlog-formatv0.py not using absolute_import
136 tests/revlog-formatv0.py not using absolute_import
138 tests/run-tests.py not using absolute_import
137 tests/run-tests.py not using absolute_import
139 tests/seq.py not using absolute_import
138 tests/seq.py not using absolute_import
140 tests/seq.py requires print_function
139 tests/seq.py requires print_function
141 tests/silenttestrunner.py not using absolute_import
140 tests/silenttestrunner.py not using absolute_import
142 tests/silenttestrunner.py requires print_function
141 tests/silenttestrunner.py requires print_function
143 tests/sitecustomize.py not using absolute_import
142 tests/sitecustomize.py not using absolute_import
144 tests/svn-safe-append.py not using absolute_import
143 tests/svn-safe-append.py not using absolute_import
145 tests/svnxml.py not using absolute_import
144 tests/svnxml.py not using absolute_import
146 tests/test-ancestor.py requires print_function
145 tests/test-ancestor.py requires print_function
147 tests/test-atomictempfile.py not using absolute_import
146 tests/test-atomictempfile.py not using absolute_import
148 tests/test-batching.py not using absolute_import
147 tests/test-batching.py not using absolute_import
149 tests/test-batching.py requires print_function
148 tests/test-batching.py requires print_function
150 tests/test-bdiff.py not using absolute_import
149 tests/test-bdiff.py not using absolute_import
151 tests/test-bdiff.py requires print_function
150 tests/test-bdiff.py requires print_function
152 tests/test-context.py not using absolute_import
151 tests/test-context.py not using absolute_import
153 tests/test-context.py requires print_function
152 tests/test-context.py requires print_function
154 tests/test-demandimport.py not using absolute_import
153 tests/test-demandimport.py not using absolute_import
155 tests/test-demandimport.py requires print_function
154 tests/test-demandimport.py requires print_function
156 tests/test-dispatch.py not using absolute_import
155 tests/test-dispatch.py not using absolute_import
157 tests/test-dispatch.py requires print_function
156 tests/test-dispatch.py requires print_function
158 tests/test-doctest.py not using absolute_import
157 tests/test-doctest.py not using absolute_import
159 tests/test-duplicateoptions.py not using absolute_import
158 tests/test-duplicateoptions.py not using absolute_import
160 tests/test-duplicateoptions.py requires print_function
159 tests/test-duplicateoptions.py requires print_function
161 tests/test-filecache.py not using absolute_import
160 tests/test-filecache.py not using absolute_import
162 tests/test-filecache.py requires print_function
161 tests/test-filecache.py requires print_function
163 tests/test-filelog.py not using absolute_import
162 tests/test-filelog.py not using absolute_import
164 tests/test-filelog.py requires print_function
163 tests/test-filelog.py requires print_function
165 tests/test-hg-parseurl.py not using absolute_import
164 tests/test-hg-parseurl.py not using absolute_import
166 tests/test-hg-parseurl.py requires print_function
165 tests/test-hg-parseurl.py requires print_function
167 tests/test-hgweb-auth.py not using absolute_import
166 tests/test-hgweb-auth.py not using absolute_import
168 tests/test-hgweb-auth.py requires print_function
167 tests/test-hgweb-auth.py requires print_function
169 tests/test-hgwebdir-paths.py not using absolute_import
168 tests/test-hgwebdir-paths.py not using absolute_import
170 tests/test-hybridencode.py not using absolute_import
169 tests/test-hybridencode.py not using absolute_import
171 tests/test-hybridencode.py requires print_function
170 tests/test-hybridencode.py requires print_function
172 tests/test-lrucachedict.py not using absolute_import
171 tests/test-lrucachedict.py not using absolute_import
173 tests/test-lrucachedict.py requires print_function
172 tests/test-lrucachedict.py requires print_function
174 tests/test-manifest.py not using absolute_import
173 tests/test-manifest.py not using absolute_import
175 tests/test-minirst.py not using absolute_import
174 tests/test-minirst.py not using absolute_import
176 tests/test-minirst.py requires print_function
175 tests/test-minirst.py requires print_function
177 tests/test-parseindex2.py not using absolute_import
176 tests/test-parseindex2.py not using absolute_import
178 tests/test-parseindex2.py requires print_function
177 tests/test-parseindex2.py requires print_function
179 tests/test-pathencode.py not using absolute_import
178 tests/test-pathencode.py not using absolute_import
180 tests/test-pathencode.py requires print_function
179 tests/test-pathencode.py requires print_function
181 tests/test-propertycache.py not using absolute_import
180 tests/test-propertycache.py not using absolute_import
182 tests/test-propertycache.py requires print_function
181 tests/test-propertycache.py requires print_function
183 tests/test-revlog-ancestry.py not using absolute_import
182 tests/test-revlog-ancestry.py not using absolute_import
184 tests/test-revlog-ancestry.py requires print_function
183 tests/test-revlog-ancestry.py requires print_function
185 tests/test-run-tests.py not using absolute_import
184 tests/test-run-tests.py not using absolute_import
186 tests/test-simplemerge.py not using absolute_import
185 tests/test-simplemerge.py not using absolute_import
187 tests/test-status-inprocess.py not using absolute_import
186 tests/test-status-inprocess.py not using absolute_import
188 tests/test-status-inprocess.py requires print_function
187 tests/test-status-inprocess.py requires print_function
189 tests/test-symlink-os-yes-fs-no.py not using absolute_import
188 tests/test-symlink-os-yes-fs-no.py not using absolute_import
190 tests/test-trusted.py not using absolute_import
189 tests/test-trusted.py not using absolute_import
191 tests/test-trusted.py requires print_function
190 tests/test-trusted.py requires print_function
192 tests/test-ui-color.py not using absolute_import
191 tests/test-ui-color.py not using absolute_import
193 tests/test-ui-color.py requires print_function
192 tests/test-ui-color.py requires print_function
194 tests/test-ui-config.py not using absolute_import
193 tests/test-ui-config.py not using absolute_import
195 tests/test-ui-config.py requires print_function
194 tests/test-ui-config.py requires print_function
196 tests/test-ui-verbosity.py not using absolute_import
195 tests/test-ui-verbosity.py not using absolute_import
197 tests/test-ui-verbosity.py requires print_function
196 tests/test-ui-verbosity.py requires print_function
198 tests/test-url.py not using absolute_import
197 tests/test-url.py not using absolute_import
199 tests/test-url.py requires print_function
198 tests/test-url.py requires print_function
200 tests/test-walkrepo.py requires print_function
199 tests/test-walkrepo.py requires print_function
201 tests/test-wireproto.py requires print_function
200 tests/test-wireproto.py requires print_function
202 tests/tinyproxy.py requires print_function
201 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now