Diff in subdirectories from Jake Edge

Dates in diff
Fix O(n^2) behaviour of manifest diff
Add a/ and b/ to work with patch -p1
This commit is contained in:
mpm@selenic.com 2005-05-12 17:54:55 -08:00
parent b3f6fa6d57
commit 264f689db9
4 changed files with 31 additions and 22 deletions

23
hg
View File

@ -48,20 +48,25 @@ def filterfiles(list, files):
return l return l
def diff(files = None, node1 = None, node2 = None): def diff(files = None, node1 = None, node2 = None):
def date(c):
return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
if node2: if node2:
change = repo.changelog.read(node2) change = repo.changelog.read(node2)
mmap2 = repo.manifest.read(change[0]) mmap2 = repo.manifest.read(change[0])
(c, a, d) = repo.diffrevs(node1, node2) (c, a, d) = repo.diffrevs(node1, node2)
def read(f): return repo.file(f).read(mmap2[f]) def read(f): return repo.file(f).read(mmap2[f])
date2 = date(change)
else: else:
date2 = time.asctime()
if not node1: if not node1:
node1 = repo.current node1 = repo.current
(c, a, d) = repo.diffdir(repo.root, node1) (c, a, d) = repo.diffdir(repo.root, node1)
def read(f): return file(f).read() def read(f): return file(os.path.join(repo.root, f)).read()
change = repo.changelog.read(node1) change = repo.changelog.read(node1)
mmap = repo.manifest.read(change[0]) mmap = repo.manifest.read(change[0])
date1 = date(change)
if files: if files:
(c, a, d) = map(lambda x: filterfiles(x, files), (c, a, d)) (c, a, d) = map(lambda x: filterfiles(x, files), (c, a, d))
@ -69,16 +74,15 @@ def diff(files = None, node1 = None, node2 = None):
for f in c: for f in c:
to = repo.file(f).read(mmap[f]) to = repo.file(f).read(mmap[f])
tn = read(f) tn = read(f)
sys.stdout.write(mdiff.unidiff(to, tn, f)) sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
for f in a: for f in a:
to = "" to = ""
tn = read(f) tn = read(f)
sys.stdout.write(mdiff.unidiff(to, tn, f)) sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
for f in d: for f in d:
to = repo.file(f).read(mmap[f]) to = repo.file(f).read(mmap[f])
tn = "" tn = ""
sys.stdout.write(mdiff.unidiff(to, tn, f)) sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
options = {} options = {}
opts = [('v', 'verbose', None, 'verbose'), opts = [('v', 'verbose', None, 'verbose'),
@ -178,8 +182,13 @@ elif cmd == "diff":
if len(revs) > 2: if len(revs) > 2:
print "too many revisions to diff" print "too many revisions to diff"
sys.exit(1) sys.exit(1)
else:
diff(args, *revs) if os.getcwd() != repo.root:
relpath = os.getcwd()[len(repo.root) + 1: ]
if not args: args = [ relpath ]
else: args = [ os.path.join(relpath, x) for x in args ]
diff(args, *revs)
elif cmd == "export": elif cmd == "export":
node = repo.changelog.lookup(args[0]) node = repo.changelog.lookup(args[0])

View File

@ -499,7 +499,7 @@ class localrepository:
dc = dict.fromkeys(mf) dc = dict.fromkeys(mf)
def fcmp(fn): def fcmp(fn):
t1 = file(fn).read() t1 = file(os.path.join(self.root, fn)).read()
t2 = self.file(fn).revision(mf[fn]) t2 = self.file(fn).revision(mf[fn])
return cmp(t1, t2) return cmp(t1, t2)
@ -509,7 +509,7 @@ class localrepository:
for f in files: for f in files:
fn = os.path.join(d, f) fn = os.path.join(d, f)
try: s = os.stat(fn) try: s = os.stat(os.path.join(self.root, fn))
except: continue except: continue
if fn in dc: if fn in dc:
c = dc[fn] c = dc[fn]

View File

@ -2,11 +2,11 @@
import difflib, struct import difflib, struct
from cStringIO import StringIO from cStringIO import StringIO
def unidiff(a, b, fn): def unidiff(a, ad, b, bd, fn):
if not a and not b: return "" if not a and not b: return ""
a = a.splitlines(1) a = a.splitlines(1)
b = b.splitlines(1) b = b.splitlines(1)
l = list(difflib.unified_diff(a, b, fn, fn)) l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn, ad, bd))
return "".join(l) return "".join(l)
def textdiff(a, b): def textdiff(a, b):
@ -29,15 +29,11 @@ def sortdiff(a, b):
la += 1 la += 1
lb += 1 lb += 1
si = lb if lb < len(b):
while lb < len(b): yield "insert", la, la, lb, len(b)
lb += 1
yield "insert", la, la, si, lb
si = la if la < len(a):
while la < len(a): yield "delete", la, len(a), lb, lb
la += 1
yield "delete", si, la, lb, lb
def diff(a, b, sorted=0): def diff(a, b, sorted=0):
bin = [] bin = []
@ -60,6 +56,7 @@ def patch(a, bin):
last = pos = 0 last = pos = 0
r = [] r = []
c = 0
while pos < len(bin): while pos < len(bin):
p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12]) p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
pos += 12 pos += 12
@ -67,6 +64,7 @@ def patch(a, bin):
r.append(bin[pos:pos + l]) r.append(bin[pos:pos + l])
pos += l pos += l
last = p2 last = p2
c += 1
r.append(a[last:]) r.append(a[last:])
return "".join(r) return "".join(r)

View File

@ -114,7 +114,7 @@ class revlog:
last = self.length(base) last = self.length(base)
text = decompress(data[:last]) text = decompress(data[:last])
for r in range(base + 1, rev + 1): for r in xrange(base + 1, rev + 1):
s = self.length(r) s = self.length(r)
b = decompress(data[last:last + s]) b = decompress(data[last:last + s])
text = self.patch(text, b) text = self.patch(text, b)
@ -138,14 +138,16 @@ class revlog:
t = n - 1 t = n - 1
if n: if n:
start = self.start(self.base(t)) base = self.base(t)
start = self.start(base)
end = self.end(t) end = self.end(t)
prev = self.revision(self.tip()) prev = self.revision(self.tip())
data = compress(self.diff(prev, text)) data = compress(self.diff(prev, text))
dist = end - start + len(data)
# full versions are inserted when the needed deltas # full versions are inserted when the needed deltas
# become comparable to the uncompressed text # become comparable to the uncompressed text
if not n or (end + len(data) - start) > len(text) * 2: if not n or dist > len(text) * 2:
data = compress(text) data = compress(text)
base = n base = n
else: else: