comparison mercurial/mdiff.py @ 9827:4fe9ca519637

mdiff: fix diff -b/B/w on mixed whitespace hunks (issue127) Previous code was computing hunks then checking if these hunks could be ignored when taking whitespace/blank-lines options in accounts. This approach is simple but fails with hunks containing both whitespace and non-whitespace changes, the whole hunk is emitted while it can be mostly made of whitespace. The new version normalize the whitespaces before hunk generation, and test for blank-lines afterwards.
author Patrick Mezard <pmezard@gmail.com>
date Wed, 11 Nov 2009 18:31:42 +0100
parents 9e055cfdd620
children 7637fe4f525d
comparison
equal deleted inserted replaced
9826:d768614578dd 9827:4fe9ca519637
55 raise util.Abort(_('diff context lines count must be ' 55 raise util.Abort(_('diff context lines count must be '
56 'an integer, not %r') % self.context) 56 'an integer, not %r') % self.context)
57 57
58 defaultopts = diffopts() 58 defaultopts = diffopts()
59 59
60 def wsclean(opts, text): 60 def wsclean(opts, text, blank=True):
61 if opts.ignorews: 61 if opts.ignorews:
62 text = re.sub('[ \t]+', '', text) 62 text = re.sub('[ \t]+', '', text)
63 elif opts.ignorewsamount: 63 elif opts.ignorewsamount:
64 text = re.sub('[ \t]+', ' ', text) 64 text = re.sub('[ \t]+', ' ', text)
65 text = re.sub('[ \t]+\n', '\n', text) 65 text = re.sub('[ \t]+\n', '\n', text)
66 if opts.ignoreblanklines: 66 if blank and opts.ignoreblanklines:
67 text = re.sub('\n+', '', text) 67 text = re.sub('\n+', '', text)
68 return text 68 return text
69 69
70 def diffline(revs, a, b, opts): 70 def diffline(revs, a, b, opts):
71 parts = ['diff'] 71 parts = ['diff']
181 181
182 # bdiff.blocks gives us the matching sequences in the files. The loop 182 # bdiff.blocks gives us the matching sequences in the files. The loop
183 # below finds the spaces between those matching sequences and translates 183 # below finds the spaces between those matching sequences and translates
184 # them into diff output. 184 # them into diff output.
185 # 185 #
186 if opts.ignorews or opts.ignorewsamount:
187 t1 = wsclean(opts, t1, False)
188 t2 = wsclean(opts, t2, False)
189
186 diff = bdiff.blocks(t1, t2) 190 diff = bdiff.blocks(t1, t2)
187 hunk = None 191 hunk = None
188 for i, s1 in enumerate(diff): 192 for i, s1 in enumerate(diff):
189 # The first match is special. 193 # The first match is special.
190 # we've either found a match starting at line 0 or a match later 194 # we've either found a match starting at line 0 or a match later
206 # bdiff sometimes gives huge matches past eof, this check eats them, 210 # bdiff sometimes gives huge matches past eof, this check eats them,
207 # and deals with the special first match case described above 211 # and deals with the special first match case described above
208 if not old and not new: 212 if not old and not new:
209 continue 213 continue
210 214
211 if opts.ignorews or opts.ignorewsamount or opts.ignoreblanklines: 215 if opts.ignoreblanklines:
212 if wsclean(opts, "".join(old)) == wsclean(opts, "".join(new)): 216 if wsclean(opts, "".join(old)) == wsclean(opts, "".join(new)):
213 continue 217 continue
214 218
215 astart = contextstart(a1) 219 astart = contextstart(a1)
216 bstart = contextstart(b1) 220 bstart = contextstart(b1)