--- a/contrib/hgdiff Fri Jan 27 12:15:39 2006 +0100
+++ b/contrib/hgdiff Sat Jan 28 17:16:15 2006 +1300
@@ -5,6 +5,7 @@
import re
from optparse import OptionParser
from mercurial.bdiff import bdiff, blocks
+from mercurial.mdiff import bunidiff
VERSION="0.2"
usage = "usage: %prog [options] file1 file2"
@@ -23,127 +24,6 @@
parser.print_help()
sys.exit(1)
-# somewhat self contained replacement for difflib.unified_diff
-# t1 and t2 are the text to be diffed
-# l1 and l2 are the text broken up into lines
-# header1 and header2 are the filenames for the diff output
-# context is the number of context lines
-# showfunc enables diff -p output
-# ignorews ignores all whitespace changes in the diff
-def bunidiff(t1, t2, l1, l2, header1, header2, context=3, showfunc=False,
- ignorews=False):
- def contextend(l, len):
- ret = l + context
- if ret > len:
- ret = len
- return ret
-
- def contextstart(l):
- ret = l - context
- if ret < 0:
- return 0
- return ret
-
- def yieldhunk(hunk, header):
- if header:
- for x in header:
- yield x
- (astart, a2, bstart, b2, delta) = hunk
- aend = contextend(a2, len(l1))
- alen = aend - astart
- blen = b2 - bstart + aend - a2
-
- func = ""
- if showfunc:
- # walk backwards from the start of the context
- # to find a line starting with an alphanumeric char.
- for x in xrange(astart, -1, -1):
- t = l1[x]
- if funcre.match(t):
- func = ' ' + t[:40]
- break
-
- yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen,
- bstart + 1, blen, func)
- for x in delta:
- yield x
- for x in xrange(a2, aend):
- yield ' ' + l1[x]
-
- header = [ "--- %s\t\n" % header1, "+++ %s\t\n" % header2 ]
-
- if showfunc:
- funcre = re.compile('\w')
- if ignorews:
- wsre = re.compile('[ \t]')
-
- # bdiff.blocks gives us the matching sequences in the files. The loop
- # below finds the spaces between those matching sequences and translates
- # them into diff output.
- #
- diff = blocks(t1, t2)
- hunk = None
- for i in xrange(len(diff)):
- # The first match is special.
- # we've either found a match starting at line 0 or a match later
- # in the file. If it starts later, old and new below will both be
- # empty and we'll continue to the next match.
- if i > 0:
- s = diff[i-1]
- else:
- s = [0, 0, 0, 0]
- delta = []
- s1 = diff[i]
- a1 = s[1]
- a2 = s1[0]
- b1 = s[3]
- b2 = s1[2]
- old = l1[a1:a2]
- new = l2[b1:b2]
-
- # bdiff sometimes gives huge matches past eof, this check eats them,
- # and deals with the special first match case described above
- if not old and not new:
- continue
-
- if ignorews:
- wsold = wsre.sub('', "".join(old))
- wsnew = wsre.sub('', "".join(new))
- if wsold == wsnew:
- continue
-
- astart = contextstart(a1)
- bstart = contextstart(b1)
- prev = None
- if hunk:
- # join with the previous hunk if it falls inside the context
- if astart < hunk[1] + context + 1:
- prev = hunk
- astart = hunk[1]
- bstart = hunk[3]
- else:
- for x in yieldhunk(hunk, header):
- yield x
- # we only want to yield the header if the files differ, and
- # we only want to yield it once.
- header = None
- if prev:
- # we've joined the previous hunk, record the new ending points.
- hunk[1] = a2
- hunk[3] = b2
- delta = hunk[4]
- else:
- # create a new hunk
- hunk = [ astart, a2, bstart, b2, delta ]
-
- delta[len(delta):] = [ ' ' + x for x in l1[astart:a1] ]
- delta[len(delta):] = [ '-' + x for x in old ]
- delta[len(delta):] = [ '+' + x for x in new ]
-
- if hunk:
- for x in yieldhunk(hunk, header):
- yield x
-
# simple utility function to put all the
# files from a directory tree into a dict
def buildlist(names, top):