mercurial/mdiff.py
author Bryan O'Sullivan <bos@serpentine.com>
Sat, 17 Sep 2005 00:27:27 -0700
changeset 1270 fc3b41570082
parent 1015 22571b8d35d3
child 1378 a0fcfbbf52bb
permissions -rw-r--r--
Switch to new syntax for .hgignore files. Here is the new syntax, in summary. Trailing white space is dropped. The escape character is "\". Comments start with #. Empty lines are skipped. Lines can be of the following formats: syntax: regexp # defaults following lines to non-rooted regexps syntax: glob # defaults following lines to non-rooted globs re:pattern # non-rooted regular expression glob:pattern # non-rooted glob pattern # pattern of the current default type The default pattern type is regexp, which is completely backwards compatible with the old hgignore syntax. In the dirstate class, the ignore method has been reworked to be based on the util.matcher function, by way of a new dirstate.hgignore method.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
239
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     1
# mdiff.py - diff and patch routines for mercurial
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     2
#
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     3
# Copyright 2005 Matt Mackall <mpm@selenic.com>
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     4
#
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     5
# This software may be used and distributed according to the terms
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
75840796e8e2 mdiff.py: kill #! line, add copyright notice
mpm@selenic.com
parents: 184
diff changeset
     7
432
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
     8
import difflib, struct, bdiff
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
     9
from mpatch import *
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 582
diff changeset
    10
from util import *
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    11
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 582
diff changeset
    12
def unidiff(a, ad, b, bd, fn, r=None, text=False):
396
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    13
35
9197c26a414b unidiff: punt on comparing empty files
mpm@selenic.com
parents: 0
diff changeset
    14
    if not a and not b: return ""
264
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    15
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 582
diff changeset
    16
    if not text and (binary(a) or binary(b)):
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 582
diff changeset
    17
        l = ['Binary file %s has changed\n' % fn]
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 582
diff changeset
    18
    elif a == None:
264
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    19
        b = b.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    20
        l1 = "--- %s\t%s\n" % ("/dev/null", ad)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    21
        l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    22
        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    23
        l = [l1, l2, l3] + ["+" + e for e in b]
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    24
    elif b == None:
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    25
        a = a.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    26
        l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    27
        l2 = "+++ %s\t%s\n" % ("/dev/null", bd)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    28
        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    29
        l = [l1, l2, l3] + ["-" + e for e in a]
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    30
    else:
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    31
        a = a.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    32
        b = b.splitlines(1)
272
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    33
        l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn))
278
777e388c06d6 unidiff: handle empty diffs more gracefully
mpm@selenic.com
parents: 272
diff changeset
    34
        if not l: return ""
272
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    35
        # difflib uses a space, rather than a tab
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    36
        l[0] = l[0][:-2] + "\t" + ad + "\n"
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    37
        l[1] = l[1][:-2] + "\t" + bd + "\n"
170
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    38
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    39
    for ln in xrange(len(l)):
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    40
        if l[ln][-1] != '\n':
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    41
            l[ln] += "\n\ No newline at end of file\n"
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    42
396
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    43
    if r:
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    44
        l.insert(0, "diff %s %s\n" %
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    45
                    (' '.join(["-r %s" % rev for rev in r]), fn))
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    46
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    47
    return "".join(l)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    48
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    49
def sortdiff(a, b):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    50
    la = lb = 0
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    51
    lena = len(a)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    52
    lenb = len(b)
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 432
diff changeset
    53
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    54
    while 1:
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    55
        am, bm, = la, lb
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    56
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    57
        # walk over matching lines
326
235443668bea mdiff: fix the fix
mpm@selenic.com
parents: 325
diff changeset
    58
        while lb < lenb and la < lena and a[la] == b[lb] :
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    59
            la += 1
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    60
            lb += 1
318
2819f63b16bf mdiff: revert grouping optimization for the time being
mpm@selenic.com
parents: 317
diff changeset
    61
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    62
        if la > am:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    63
            yield (am, bm, la - am) # return a match
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    64
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    65
        # skip mismatched lines from b
361
88268aa2b8d2 Fix another sortdiff cornercase
mpm@selenic.com
parents: 330
diff changeset
    66
        while la < lena and lb < lenb and b[lb] < a[la]:
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    67
            lb += 1
318
2819f63b16bf mdiff: revert grouping optimization for the time being
mpm@selenic.com
parents: 317
diff changeset
    68
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    69
        if lb >= lenb:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    70
            break
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 432
diff changeset
    71
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    72
        # skip mismatched lines from a
361
88268aa2b8d2 Fix another sortdiff cornercase
mpm@selenic.com
parents: 330
diff changeset
    73
        while la < lena and lb < lenb and b[lb] > a[la]:
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    74
            la += 1
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    75
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    76
        if la >= lena:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    77
            break
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 432
diff changeset
    78
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    79
    yield (lena, lenb, 0)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    80
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    81
def diff(a, b, sorted=0):
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    82
    if not a:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    83
        s = "".join(b)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    84
        return s and (struct.pack(">lll", 0, 0, len(s)) + s)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    85
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    86
    bin = []
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    87
    p = [0]
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    88
    for i in a: p.append(p[-1] + len(i))
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    89
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    90
    if sorted:
317
b18ce742566a hg commit: user and date options
mpm@selenic.com
parents: 278
diff changeset
    91
        try:
b18ce742566a hg commit: user and date options
mpm@selenic.com
parents: 278
diff changeset
    92
            d = sortdiff(a, b)
b18ce742566a hg commit: user and date options
mpm@selenic.com
parents: 278
diff changeset
    93
        except:
b18ce742566a hg commit: user and date options
mpm@selenic.com
parents: 278
diff changeset
    94
            raise
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    95
    else:
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    96
        d = difflib.SequenceMatcher(None, a, b).get_matching_blocks()
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    97
    la = 0
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    98
    lb = 0
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    99
    for am, bm, size in d:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   100
        s = "".join(b[lb:bm])
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   101
        if am > la or s:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   102
            bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   103
        la = am + size
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   104
        lb = bm + size
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 432
diff changeset
   105
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   106
    return "".join(bin)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   107
120
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   108
def patchtext(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   109
    pos = 0
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   110
    t = []
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   111
    while pos < len(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   112
        p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   113
        pos += 12
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   114
        t.append(bin[pos:pos + l])
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   115
        pos += l
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   116
    return "".join(t)
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   117
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   118
def patch(a, bin):
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents: 71
diff changeset
   119
    return patches(a, [bin])
432
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
   120
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
   121
textdiff = bdiff.bdiff
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
   122
3b9e3d3d2810 Start using bdiff for generating deltas
mpm@selenic.com
parents: 396
diff changeset
   123