Add basic annotation support
filelog.annotate() will get the change number on each line.
Singed-Off-by: Christopher Li<hg@chrisli.org>
--- a/hg Tue May 17 01:07:57 2005 -0800
+++ b/hg Tue May 17 01:12:30 2005 -0800
@@ -199,6 +199,21 @@
diff(args, *revs)
+elif cmd == "annotate":
+ aoptions = {}
+ opts = [('r', 'revision', '', 'revision')]
+ args = fancyopts.fancyopts(args, opts, aoptions,
+ 'hg annotate [-r id] [files]')
+ if args:
+ node = repo.current
+ if aoptions['revision']:
+ node = repo.changelog.lookup(aoptions['revision'])
+ change = repo.changelog.read(node)
+ mmap = repo.manifest.read(change[0])
+ for f in args:
+ for n, l in repo.file(f).annotate(mmap[f]):
+ sys.stdout.write("%s: %s"%(n, l))
+
elif cmd == "export":
node = repo.lookup(args[0])
prev, other = repo.changelog.parents(node)
--- a/mercurial/hg.py Tue May 17 01:07:57 2005 -0800
+++ b/mercurial/hg.py Tue May 17 01:12:30 2005 -0800
@@ -10,6 +10,7 @@
from mercurial import byterange
from mercurial.transaction import *
from mercurial.revlog import *
+from difflib import SequenceMatcher
class filelog(revlog):
def __init__(self, opener, path):
@@ -65,6 +66,32 @@
(o, n) = self.mergedag(other, transaction, linkseq)
return self.resolvedag(o, n, transaction, link)
+ def annotate(self, node):
+ revs = []
+ while node != nullid:
+ revs.append(node)
+ node = self.parents(node)[0]
+ revs.reverse()
+ prev = []
+ annotate = []
+ for node in revs:
+ curr = self.read(node).splitlines(1)
+ linkrev = self.linkrev(node)
+ sm = SequenceMatcher(None, prev, curr)
+ offset = 0
+ for o, m, n, s, t in sm.get_opcodes():
+ if o in ('insert','replace'):
+ annotate[m+offset:n+offset] = \
+ [ (linkrev, l) for l in curr[s:t]]
+ if o == 'insert':
+ offset += m-n
+ elif o == 'delete':
+ del annotate[m+offset:n+offset]
+ offset -= m-n
+ assert len(annotate) == len(curr)
+ prev = curr
+ return annotate
+
class manifest(revlog):
def __init__(self, opener):
self.mapcache = None