##// END OF EJS Templates
Rewrite log command. New version is faster and more featureful....
Rewrite log command. New version is faster and more featureful. The original implementation of log walked backwards through history, which had terrible behaviour. It took several minutes to view complete kernel change history on a fast machine, for example. The rewrite uses a windowed approach to walk hunks of history forwards, while still giving results in reverse order. This reduces run time from five minutes to five seconds on my system. In addition, the rewrite uses our normal name handling mechanisms, so you can run a command like "hg log net/ipv4/**.c" and get a useful answer. It optimises for three different cases (no arguments, only files, and anything goes), so it performs well in all circumstances I've tested.

File last commit:

r1015:22571b8d default
r1031:503aaf19 default
Show More
mdiff.py
123 lines | 3.0 KiB | text/x-python | PythonLexer
mpm@selenic.com
mdiff.py: kill #! line, add copyright notice...
r239 # 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.
mpm@selenic.com
Start using bdiff for generating deltas...
r432 import difflib, struct, bdiff
from mpatch import *
mpm@selenic.com
Add automatic binary file detection to diff and export...
r1015 from util import *
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
mpm@selenic.com
Add automatic binary file detection to diff and export...
r1015 def unidiff(a, ad, b, bd, fn, r=None, text=False):
Thomas Arendsen Hein
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli....
r396
mpm@selenic.com
unidiff: punt on comparing empty files
r35 if not a and not b: return ""
mpm@selenic.com
Attempt to make diff deal with null sources properly...
r264
mpm@selenic.com
Add automatic binary file detection to diff and export...
r1015 if not text and (binary(a) or binary(b)):
l = ['Binary file %s has changed\n' % fn]
elif a == None:
mpm@selenic.com
Attempt to make diff deal with null sources properly...
r264 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)
mpm@selenic.com
diff: use tab to separate date from filename...
r272 l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn))
mpm@selenic.com
unidiff: handle empty diffs more gracefully...
r278 if not l: return ""
mpm@selenic.com
diff: use tab to separate date from filename...
r272 # difflib uses a space, rather than a tab
l[0] = l[0][:-2] + "\t" + ad + "\n"
l[1] = l[1][:-2] + "\t" + bd + "\n"
mpm@selenic.com
hg diff: fix missing final newline bug
r170
for ln in xrange(len(l)):
if l[ln][-1] != '\n':
l[ln] += "\n\ No newline at end of file\n"
Thomas Arendsen Hein
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli....
r396 if r:
l.insert(0, "diff %s %s\n" %
(' '.join(["-r %s" % rev for rev in r]), fn))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 return "".join(l)
def sortdiff(a, b):
la = lb = 0
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 lena = len(a)
lenb = len(b)
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 while 1:
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 am, bm, = la, lb
# walk over matching lines
mpm@selenic.com
mdiff: fix the fix...
r326 while lb < lenb and la < lena and a[la] == b[lb] :
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 la += 1
lb += 1
mpm@selenic.com
mdiff: revert grouping optimization for the time being...
r318
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 if la > am:
yield (am, bm, la - am) # return a match
# skip mismatched lines from b
mpm@selenic.com
Fix another sortdiff cornercase...
r361 while la < lena and lb < lenb and b[lb] < a[la]:
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 lb += 1
mpm@selenic.com
mdiff: revert grouping optimization for the time being...
r318
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 if lb >= lenb:
break
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 # skip mismatched lines from a
mpm@selenic.com
Fix another sortdiff cornercase...
r361 while la < lena and lb < lenb and b[lb] > a[la]:
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 la += 1
if la >= lena:
break
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 yield (lena, lenb, 0)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def diff(a, b, sorted=0):
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 if not a:
s = "".join(b)
return s and (struct.pack(">lll", 0, 0, len(s)) + s)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 bin = []
p = [0]
for i in a: p.append(p[-1] + len(i))
if sorted:
mpm@selenic.com
hg commit: user and date options...
r317 try:
d = sortdiff(a, b)
except:
raise
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 else:
mpm@selenic.com
mdiff: reinstate new algorithm...
r325 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
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 return "".join(bin)
mpm@selenic.com
Add a function to return the new text from a binary diff
r120 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)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def patch(a, bin):
mpm@selenic.com
Add an O(m + nlog n) patching extension
r72 return patches(a, [bin])
mpm@selenic.com
Start using bdiff for generating deltas...
r432
textdiff = bdiff.bdiff