Mercurial > hg > mercurial-crew-with-dirclash
view mercurial/mdiff.py @ 460:6409d9a0df43
add dirstate debugging commands
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
add dirstate debugging commands
As I've played with various different merges and more recently
rawcommit, I've found the following patch to be very very helpful in
figuring out whether the dirstate is being left in a consistent or
inconsistent state with respect to the current manifest.
I attempted to deduce the invariants that were assumed by the current
code, and then check it in this code.
I may or may not have captured the design intent in this check; if not,
I'd be very happy to hear more clearly what was intended, so that I can
write tests to that expectation.
Anyway, here's the patch. Not sure if it's a good idea to commit it to
the mainline, or just leave it as a debugging aid. I attempted to
package it so that it doesn't interfere with normal usage.
Michael Fetterman
(tweaked by mpm: remove -d magic)
manifest hash: 869f5b5f954dc0f46ba27322359e811d5e21d71c
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCvP77ywK+sNU5EO8RArmtAKCCVuI2slANzWZ26P5edtH/ixdwNwCfZLWl
5P+V+C92II3usO4YW2MULKY=
=/Pv4
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Fri, 24 Jun 2005 22:51:39 -0800 |
parents | 3b9e3d3d2810 |
children | 03f27b1381f9 |
line wrap: on
line source
# mdiff.py - diff and patch routines for mercurial # # Copyright 2005 Matt Mackall <mpm@selenic.com> # # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. import difflib, struct, bdiff from mpatch import * def unidiff(a, ad, b, bd, fn, r=None): if not a and not b: return "" if a == None: b = b.splitlines(1) l1 = "--- %s\t%s\n" % ("/dev/null", ad) l2 = "+++ %s\t%s\n" % ("b/" + fn, bd) l3 = "@@ -0,0 +1,%d @@\n" % len(b) l = [l1, l2, l3] + ["+" + e for e in b] elif b == None: a = a.splitlines(1) l1 = "--- %s\t%s\n" % ("a/" + fn, ad) l2 = "+++ %s\t%s\n" % ("/dev/null", bd) l3 = "@@ -1,%d +0,0 @@\n" % len(a) l = [l1, l2, l3] + ["-" + e for e in a] else: a = a.splitlines(1) b = b.splitlines(1) l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn)) if not l: return "" # difflib uses a space, rather than a tab l[0] = l[0][:-2] + "\t" + ad + "\n" l[1] = l[1][:-2] + "\t" + bd + "\n" for ln in xrange(len(l)): if l[ln][-1] != '\n': l[ln] += "\n\ No newline at end of file\n" if r: l.insert(0, "diff %s %s\n" % (' '.join(["-r %s" % rev for rev in r]), fn)) return "".join(l) def sortdiff(a, b): la = lb = 0 lena = len(a) lenb = len(b) while 1: am, bm, = la, lb # walk over matching lines while lb < lenb and la < lena and a[la] == b[lb] : la += 1 lb += 1 if la > am: yield (am, bm, la - am) # return a match # skip mismatched lines from b while la < lena and lb < lenb and b[lb] < a[la]: lb += 1 if lb >= lenb: break # skip mismatched lines from a while la < lena and lb < lenb and b[lb] > a[la]: la += 1 if la >= lena: break yield (lena, lenb, 0) def diff(a, b, sorted=0): if not a: s = "".join(b) return s and (struct.pack(">lll", 0, 0, len(s)) + s) bin = [] p = [0] for i in a: p.append(p[-1] + len(i)) if sorted: try: d = sortdiff(a, b) except: print a, b raise else: d = difflib.SequenceMatcher(None, a, b).get_matching_blocks() la = 0 lb = 0 for am, bm, size in d: s = "".join(b[lb:bm]) if am > la or s: bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s) la = am + size lb = bm + size return "".join(bin) def patchtext(bin): pos = 0 t = [] while pos < len(bin): p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12]) pos += 12 t.append(bin[pos:pos + l]) pos += l return "".join(t) def patch(a, bin): return patches(a, [bin]) textdiff = bdiff.bdiff