mercurial/mdiff.py
author mpm@selenic.com
Tue, 21 Jun 2005 19:31:13 -0800
changeset 419 28511fc21073
parent 396 8f8bb77d560e
child 432 3b9e3d3d2810
permissions -rw-r--r--
[PATCH] file seperator handling for the other 'OS' -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 [PATCH] file seperator handling for the other 'OS' From: K Thananchayan <thananck@yahoo.com> The following patch maintains repo root relative source file names in canonical form (with '/' as file seperator). Mercurial calls os.path.join, os.path.normpath, os.path.walk that use platform's file seperator. This patch does not change seperator in these circumstances (except when the result refer to source files). manifest hash: 2fbb4cb0d3d0bc4f4de5c7c8803fb738072ec6c5 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCuNuBywK+sNU5EO8RAhAZAKCV8cz11+rdof9n1tHb0uDScF34GgCeITNi 4aVikToPXqXyReN9kFP5pnY= =xcV5 -----END PGP SIGNATURE-----
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
249
619e775aa7f9 import and startup cleanups
mpm@selenic.com
parents: 241
diff changeset
     8
import difflib, struct
127
44538462d3c8 Fix braindamaged import in mdiff.
mpm@selenic.com
parents: 125
diff changeset
     9
from mercurial.mpatch import *
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    10
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
    11
def unidiff(a, ad, b, bd, fn, r=None):
8f8bb77d560e Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 361
diff changeset
    12
35
9197c26a414b unidiff: punt on comparing empty files
mpm@selenic.com
parents: 0
diff changeset
    13
    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
    14
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    15
    if a == None:
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    16
        b = b.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    17
        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
    18
        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
    19
        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
    20
        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
    21
    elif b == None:
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    22
        a = a.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    23
        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
    24
        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
    25
        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
    26
        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
    27
    else:
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    28
        a = a.splitlines(1)
4c1d7072d5cd Attempt to make diff deal with null sources properly
mpm@selenic.com
parents: 249
diff changeset
    29
        b = b.splitlines(1)
272
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    30
        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
    31
        if not l: return ""
272
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    32
        # difflib uses a space, rather than a tab
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    33
        l[0] = l[0][:-2] + "\t" + ad + "\n"
467cea2bf2d8 diff: use tab to separate date from filename
mpm@selenic.com
parents: 264
diff changeset
    34
        l[1] = l[1][:-2] + "\t" + bd + "\n"
170
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    35
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    36
    for ln in xrange(len(l)):
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    37
        if l[ln][-1] != '\n':
e6c621a825f2 hg diff: fix missing final newline bug
mpm@selenic.com
parents: 127
diff changeset
    38
            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
    39
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
    40
    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
    41
        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
    42
                    (' '.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
    43
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    44
    return "".join(l)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    45
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    46
def textdiff(a, b):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    47
    return diff(a.splitlines(1), b.splitlines(1))
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)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
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
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    71
        
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
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    78
        
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
            print a, b
b18ce742566a hg commit: user and date options
mpm@selenic.com
parents: 278
diff changeset
    95
            raise
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    96
    else:
325
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    97
        d = difflib.SequenceMatcher(None, a, b).get_matching_blocks()
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    98
    la = 0
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
    99
    lb = 0
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   100
    for am, bm, size in d:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   101
        s = "".join(b[lb:bm])
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   102
        if am > la or s:
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   103
            bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s)
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   104
        la = am + size
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   105
        lb = bm + size
ad87e19854a6 mdiff: reinstate new algorithm
mpm@selenic.com
parents: 318
diff changeset
   106
    
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   107
    return "".join(bin)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   108
120
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   109
def patchtext(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   110
    pos = 0
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   111
    t = []
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   112
    while pos < len(bin):
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   113
        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
   114
        pos += 12
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   115
        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
   116
        pos += l
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   117
    return "".join(t)
bae6f0328f63 Add a function to return the new text from a binary diff
mpm@selenic.com
parents: 75
diff changeset
   118
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   119
def patch(a, bin):
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents: 71
diff changeset
   120
    return patches(a, [bin])