contrib/hgdiff
author Matt Mackall <mpm@selenic.com>
Tue, 24 Jan 2006 14:49:19 +1300
changeset 1636 7da32bb3d1d3
child 1644 e7e6504c4989
permissions -rwxr-xr-x
contrib: add Chris Mason's stand-alone diff tool This uses Mercurial's diff algorithm to generate unidiffs like the traditional diff tool.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1636
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
#!/usr/bin/env python
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
import os, sys, struct, stat
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
import difflib
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
import re
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
from optparse import OptionParser
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
from mercurial.bdiff import bdiff, blocks
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
VERSION="0.2"
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
usage = "usage: %prog [options] file1 file2"
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
parser = OptionParser(usage=usage)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
parser.add_option("-d", "--difflib", action="store_true", default=False)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
parser.add_option('-x', '--count', default=1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
parser.add_option('-c', '--context', type="int", default=3)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
parser.add_option('-p', '--show-c-function', action="store_true", default=False)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
parser.add_option('-w', '--ignore-all-space', action="store_true", 
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
                  default=False)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
(options, args) = parser.parse_args()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
if not args:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
    parser.print_help()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
    sys.exit(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
# somewhat self contained replacement for difflib.unified_diff
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
# t1 and t2 are the text to be diffed
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
# l1 and l2 are the text broken up into lines
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
# header1 and header2 are the filenames for the diff output
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
# context is the number of context lines
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
# showfunc enables diff -p output
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
# ignorews ignores all whitespace changes in the diff
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
def bunidiff(t1, t2, l1, l2, header1, header2, context=3, showfunc=False, 
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
             ignorews=False):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
    def contextend(l, len):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
        ret = l + context
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
        if ret > len:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
            ret = len
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
        return ret
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
    def contextstart(l):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
        ret = l - context
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
        if ret < 0:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
            return 0
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
        return ret
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
    def yieldhunk(hunk, header):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
        if header:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
            for x in header:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
                yield x
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
        (astart, a2, bstart, b2, delta) = hunk
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
        aend = contextend(a2, len(l1))
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
        alen = aend - astart
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
        blen = b2 - bstart + aend - a2
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
        func = ""
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
        if showfunc:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
            # walk backwards from the start of the context
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
            # to find a line starting with an alphanumeric char.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
            for x in xrange(astart, -1, -1):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
                t = l1[x]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
                if funcre.match(t):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                    func = ' ' + t[:40]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
                    break
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
            
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
        yield "@@ -%d,%d +%d,%d @@%s\n" % (astart + 1, alen, 
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
                                           bstart + 1, blen, func)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
        for x in delta:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
            yield x
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
        for x in xrange(a2, aend):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
            yield ' ' + l1[x]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
    header = [ "--- %s\t\n" % header1, "+++ %s\t\n" % header2 ]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
    if showfunc:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
        funcre = re.compile('\w')
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
    if ignorews:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
        wsre = re.compile('[ \t]')
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
    # bdiff.blocks gives us the matching sequences in the files.  The loop
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
    # below finds the spaces between those matching sequences and translates
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    # them into diff output.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    #
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
    diff = blocks(t1, t2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    hunk = None
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
    for i in xrange(len(diff)):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
        # The first match is special.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
        # we've either found a match starting at line 0 or a match later
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        # in the file.  If it starts later, old and new below will both be
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
        # empty and we'll continue to the next match.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
        if i > 0:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
            s = diff[i-1]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
        else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
            s = [0, 0, 0, 0]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
        delta = []
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
        s1 = diff[i]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
        a1 = s[1]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
        a2 = s1[0]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
        b1 = s[3]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
        b2 = s1[2]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
        old = l1[a1:a2]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
        new = l2[b1:b2]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
        # bdiff sometimes gives huge matches past eof, this check eats them,
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        # and deals with the special first match case described above
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
        if not old and not new:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
            continue
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
        if ignorews:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
            wsold = wsre.sub('', "".join(old))
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
            wsnew = wsre.sub('', "".join(new))
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
            if wsold == wsnew:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
                continue
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
        astart = contextstart(a1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   116
        bstart = contextstart(b1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
        prev = None
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
        if hunk:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
            # join with the previous hunk if it falls inside the context
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
            if astart < hunk[1] + context + 1:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
                prev = hunk
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
                astart = hunk[1]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
                bstart = hunk[3]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
            else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
                for x in yieldhunk(hunk, header):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
                    yield x
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
                # we only want to yield the header if the files differ, and
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   128
                # we only want to yield it once.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
                header = None
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
        if prev:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131
            # we've joined the previous hunk, record the new ending points.
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   132
            hunk[1] = a2
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   133
            hunk[3] = b2
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   134
            delta = hunk[4]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
        else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   136
            # create a new hunk
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   137
            hunk = [ astart, a2, bstart, b2, delta ]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   138
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   139
        delta[len(delta):] = [ ' ' + x for x in l1[astart:a1] ]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   140
        delta[len(delta):] = [ '-' + x for x in old ]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   141
        delta[len(delta):] = [ '+' + x for x in new ]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   142
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   143
    if hunk:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
        for x in yieldhunk(hunk, header):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   145
            yield x
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   146
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   147
# simple utility function to put all the
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   148
# files from a directory tree into a dict
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   149
def buildlist(names, top):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   150
    tlen = len(top)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   151
    for root, dirs, files in os.walk(top):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   152
        l = root[tlen + 1:]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
        for x in files:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
            p = os.path.join(root, x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   155
            st = os.lstat(p)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
            if stat.S_ISREG(st.st_mode):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   157
                names[os.path.join(l, x)] = (st.st_dev, st.st_ino)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   158
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   159
def diff_files(file1, file2):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   160
    if file1 == None:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
        b = file(file2).read().splitlines(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   162
        l1 = "--- %s\n" % (file2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   163
        l2 = "+++ %s\n" % (file2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   164
        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   165
        l = [l1, l2, l3] + ["+" + e for e in b]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   166
    elif file2 == None:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   167
        a = file(file1).read().splitlines(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   168
        l1 = "--- %s\n" % (file1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
        l2 = "+++ %s\n" % (file1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   171
        l = [l1, l2, l3] + ["-" + e for e in a]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   172
    else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   173
        t1 = file(file1).read()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   174
        t2 = file(file2).read()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
        l1 = t1.splitlines(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   176
        l2 = t2.splitlines(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   177
        if options.difflib:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   178
            l = difflib.unified_diff(l1, l2, file1, file2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   179
        else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   180
            l = bunidiff(t1, t2, l1, l2, file1, file2, context=options.context,
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
                     showfunc=options.show_c_function,
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   182
                     ignorews=options.ignore_all_space)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   183
    for x in l:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   184
        if x[-1] != '\n':
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   185
            x += "\n\ No newline at end of file\n"
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   186
        print x,
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   187
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   188
file1 = args[0]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   189
file2 = args[1]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   190
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   191
if os.path.isfile(file1) and os.path.isfile(file2):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   192
    diff_files(file1, file2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
elif os.path.isdir(file1):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   194
    if not os.path.isdir(file2):
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   195
        sys.stderr.write("file types don't match\n")
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   196
        sys.exit(1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   197
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   198
    d1 = {}
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   199
    d2 = {}
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   200
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   201
    buildlist(d1, file1)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   202
    buildlist(d2, file2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   203
    keys = d1.keys()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   204
    keys.sort()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   205
    for x in keys:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   206
        if x not in d2:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
            f2 = None
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
        else:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   209
            f2 = os.path.join(file2, x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
            st1 = d1[x]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   211
            st2 = d2[x]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   212
            del d2[x]
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   213
            if st1[0] == st2[0] and st1[1] == st2[1]:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
                sys.stderr.write("%s is a hard link\n" % x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   215
                continue
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   216
        x = os.path.join(file1, x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
        diff_files(x, f2)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
    keys = d2.keys()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
    keys.sort()
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   220
    for x in keys:
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   221
        f1 = None
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   222
        x = os.path.join(file2, x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   223
        diff_files(f1, x)
7da32bb3d1d3 contrib: add Chris Mason's stand-alone diff tool
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   224