contrib/hgdiff
author Thomas Arendsen Hein <thomas@intevation.de>
Mon, 13 Mar 2006 13:05:41 +0100
changeset 1933 7544700fd931
parent 1644 e7e6504c4989
child 3398 0f308690bda8
permissions -rwxr-xr-x
Use 'hg ci -d "1000000 0"' in tests to circumvent problem with leading zero. Some systems show "Thu Jan 01" instead of "Thu Jan 1", which breaks tests. Using "1000000" yields "Mon Jan 12 13:46:40 1970", which looks the same on all systems.

#!/usr/bin/env python

import os, sys, struct, stat
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"
parser = OptionParser(usage=usage)

parser.add_option("-d", "--difflib", action="store_true", default=False)
parser.add_option('-x', '--count', default=1)
parser.add_option('-c', '--context', type="int", default=3)
parser.add_option('-p', '--show-c-function', action="store_true", default=False)
parser.add_option('-w', '--ignore-all-space', action="store_true", 
                  default=False)

(options, args) = parser.parse_args()

if not args:
    parser.print_help()
    sys.exit(1)

# simple utility function to put all the
# files from a directory tree into a dict
def buildlist(names, top):
    tlen = len(top)
    for root, dirs, files in os.walk(top):
        l = root[tlen + 1:]
        for x in files:
            p = os.path.join(root, x)
            st = os.lstat(p)
            if stat.S_ISREG(st.st_mode):
                names[os.path.join(l, x)] = (st.st_dev, st.st_ino)

def diff_files(file1, file2):
    if file1 == None:
        b = file(file2).read().splitlines(1)
        l1 = "--- %s\n" % (file2)
        l2 = "+++ %s\n" % (file2)
        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
        l = [l1, l2, l3] + ["+" + e for e in b]
    elif file2 == None:
        a = file(file1).read().splitlines(1)
        l1 = "--- %s\n" % (file1)
        l2 = "+++ %s\n" % (file1)
        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
        l = [l1, l2, l3] + ["-" + e for e in a]
    else:
        t1 = file(file1).read()
        t2 = file(file2).read()
        l1 = t1.splitlines(1)
        l2 = t2.splitlines(1)
        if options.difflib:
            l = difflib.unified_diff(l1, l2, file1, file2)
        else:
            l = bunidiff(t1, t2, l1, l2, file1, file2, context=options.context,
                     showfunc=options.show_c_function,
                     ignorews=options.ignore_all_space)
    for x in l:
        if x[-1] != '\n':
            x += "\n\ No newline at end of file\n"
        print x,

file1 = args[0]
file2 = args[1]

if os.path.isfile(file1) and os.path.isfile(file2):
    diff_files(file1, file2)
elif os.path.isdir(file1):
    if not os.path.isdir(file2):
        sys.stderr.write("file types don't match\n")
        sys.exit(1)

    d1 = {}
    d2 = {}

    buildlist(d1, file1)
    buildlist(d2, file2)
    keys = d1.keys()
    keys.sort()
    for x in keys:
        if x not in d2:
            f2 = None
        else:
            f2 = os.path.join(file2, x)
            st1 = d1[x]
            st2 = d2[x]
            del d2[x]
            if st1[0] == st2[0] and st1[1] == st2[1]:
                sys.stderr.write("%s is a hard link\n" % x)
                continue
        x = os.path.join(file1, x)
        diff_files(x, f2)
    keys = d2.keys()
    keys.sort()
    for x in keys:
        f1 = None
        x = os.path.join(file2, x)
        diff_files(f1, x)