# HG changeset patch # User mason@suse.com # Date 1138421775 -46800 # Node ID e7e6504c4989a19e957b92338e2357270f5dae1d # Parent 747c8d03bd2996df76f8e562f64c6037ff8e315b Remove duplicate bunidiff code from hgdiff, importing from mdiff.py instead diff --git a/contrib/hgdiff b/contrib/hgdiff --- a/contrib/hgdiff +++ b/contrib/hgdiff @@ -5,6 +5,7 @@ import difflib 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 @@ if not args: 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):