# HG changeset patch # User mpm@selenic.com # Date 1115949295 28800 # Node ID b3e2ddff0159d52f30304cd4f80f87170e80e11d # Parent 1c590d34bf61e2ea12c71738e5a746cd74586157 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 diff --git a/hg b/hg --- a/hg +++ b/hg @@ -48,20 +48,25 @@ def filterfiles(list, files): return l def diff(files = None, node1 = None, node2 = None): + def date(c): + return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) if node2: change = repo.changelog.read(node2) mmap2 = repo.manifest.read(change[0]) (c, a, d) = repo.diffrevs(node1, node2) def read(f): return repo.file(f).read(mmap2[f]) + date2 = date(change) else: + date2 = time.asctime() if not node1: node1 = repo.current (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) mmap = repo.manifest.read(change[0]) + date1 = date(change) if files: (c, a, d) = map(lambda x: filterfiles(x, files), (c, a, d)) @@ -69,16 +74,15 @@ def diff(files = None, node1 = None, nod for f in c: to = repo.file(f).read(mmap[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: to = "" 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: to = repo.file(f).read(mmap[f]) tn = "" - sys.stdout.write(mdiff.unidiff(to, tn, f)) - + sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) options = {} opts = [('v', 'verbose', None, 'verbose'), @@ -178,8 +182,13 @@ elif cmd == "diff": if len(revs) > 2: print "too many revisions to diff" 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": node = repo.changelog.lookup(args[0]) diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -499,7 +499,7 @@ class localrepository: dc = dict.fromkeys(mf) def fcmp(fn): - t1 = file(fn).read() + t1 = file(os.path.join(self.root, fn)).read() t2 = self.file(fn).revision(mf[fn]) return cmp(t1, t2) @@ -509,7 +509,7 @@ class localrepository: for f in files: fn = os.path.join(d, f) - try: s = os.stat(fn) + try: s = os.stat(os.path.join(self.root, fn)) except: continue if fn in dc: c = dc[fn] diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py --- a/mercurial/mdiff.py +++ b/mercurial/mdiff.py @@ -2,11 +2,11 @@ import difflib, struct from cStringIO import StringIO -def unidiff(a, b, fn): +def unidiff(a, ad, b, bd, fn): if not a and not b: return "" a = a.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) def textdiff(a, b): @@ -29,15 +29,11 @@ def sortdiff(a, b): la += 1 lb += 1 - si = lb - while lb < len(b): - lb += 1 - yield "insert", la, la, si, lb + if lb < len(b): + yield "insert", la, la, lb, len(b) - si = la - while la < len(a): - la += 1 - yield "delete", si, la, lb, lb + if la < len(a): + yield "delete", la, len(a), lb, lb def diff(a, b, sorted=0): bin = [] @@ -60,6 +56,7 @@ def patch(a, bin): last = pos = 0 r = [] + c = 0 while pos < len(bin): p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12]) pos += 12 @@ -67,6 +64,7 @@ def patch(a, bin): r.append(bin[pos:pos + l]) pos += l last = p2 + c += 1 r.append(a[last:]) return "".join(r) diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -114,7 +114,7 @@ class revlog: last = self.length(base) text = decompress(data[:last]) - for r in range(base + 1, rev + 1): + for r in xrange(base + 1, rev + 1): s = self.length(r) b = decompress(data[last:last + s]) text = self.patch(text, b) @@ -138,14 +138,16 @@ class revlog: t = n - 1 if n: - start = self.start(self.base(t)) + base = self.base(t) + start = self.start(base) end = self.end(t) prev = self.revision(self.tip()) data = compress(self.diff(prev, text)) + dist = end - start + len(data) # full versions are inserted when the needed deltas # 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) base = n else: