annotate: introduce attr for storing per-line annotate data
authorSiddharth Agarwal <sid0@fb.com>
Mon, 02 Oct 2017 02:34:47 -0700
changeset 34432 2e32c6a31cc7
parent 34431 52e9310626a8
child 34433 2f5a135b2b04
annotate: introduce attr for storing per-line annotate data We're going to extend this a bit -- at first by simply adding whether this was a skipped child. We're well on our way to outgrowing tuples, though -- adding more and more fields to tuples becomes annoying very quickly. Differential Revision: https://phab.mercurial-scm.org/D898
mercurial/commands.py
mercurial/context.py
mercurial/hgweb/webcommands.py
tests/test-annotate.py
--- a/mercurial/commands.py	Mon Oct 02 02:34:47 2017 -0700
+++ b/mercurial/commands.py	Mon Oct 02 02:34:47 2017 -0700
@@ -326,12 +326,12 @@
         hexfn = rootfm.hexfunc
         formatrev = formathex = pycompat.bytestr
 
-    opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
-             ('number', ' ', lambda x: x[0].rev(), formatrev),
-             ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
-             ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
-             ('file', ' ', lambda x: x[0].path(), str),
-             ('line_number', ':', lambda x: x[1], str),
+    opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
+             ('number', ' ', lambda x: x.fctx.rev(), formatrev),
+             ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
+             ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
+             ('file', ' ', lambda x: x.fctx.path(), str),
+             ('line_number', ':', lambda x: x.lineno, str),
             ]
     fieldnamemap = {'number': 'rev', 'changeset': 'node'}
 
--- a/mercurial/context.py	Mon Oct 02 02:34:47 2017 -0700
+++ b/mercurial/context.py	Mon Oct 02 02:34:47 2017 -0700
@@ -25,6 +25,9 @@
     wdirnodes,
     wdirrev,
 )
+from .thirdparty import (
+    attr,
+)
 from . import (
     encoding,
     error,
@@ -983,10 +986,11 @@
 
         if linenumber:
             def decorate(text, rev):
-                return ([(rev, i) for i in xrange(1, lines(text) + 1)], text)
+                return ([annotateline(fctx=rev, lineno=i)
+                         for i in xrange(1, lines(text) + 1)], text)
         else:
             def decorate(text, rev):
-                return ([(rev, False)] * lines(text), text)
+                return ([annotateline(fctx=rev)] * lines(text), text)
 
         getlog = util.lrucachefunc(lambda x: self._repo.file(x))
 
@@ -1103,6 +1107,11 @@
         """
         return self._repo.wwritedata(self.path(), self.data())
 
+@attr.s(slots=True, frozen=True)
+class annotateline(object):
+    fctx = attr.ib()
+    lineno = attr.ib(default=False)
+
 def _annotatepair(parents, childfctx, child, skipchild, diffopts):
     r'''
     Given parent and child fctxes and annotate data for parents, for all lines
@@ -1148,7 +1157,7 @@
             for (a1, a2, b1, b2), _t in blocks:
                 if a2 - a1 >= b2 - b1:
                     for bk in xrange(b1, b2):
-                        if child[0][bk][0] == childfctx:
+                        if child[0][bk].fctx == childfctx:
                             ak = min(a1 + (bk - b1), a2 - 1)
                             child[0][bk] = parent[0][ak]
                 else:
@@ -1159,7 +1168,7 @@
         for parent, blocks in remaining:
             for a1, a2, b1, b2 in blocks:
                 for bk in xrange(b1, b2):
-                    if child[0][bk][0] == childfctx:
+                    if child[0][bk].fctx == childfctx:
                         ak = min(a1 + (bk - b1), a2 - 1)
                         child[0][bk] = parent[0][ak]
     return child
--- a/mercurial/hgweb/webcommands.py	Mon Oct 02 02:34:47 2017 -0700
+++ b/mercurial/hgweb/webcommands.py	Mon Oct 02 02:34:47 2017 -0700
@@ -906,7 +906,8 @@
 
         previousrev = None
         blockparitygen = paritygen(1)
-        for lineno, ((f, targetline), l) in enumerate(lines):
+        for lineno, (aline, l) in enumerate(lines):
+            f = aline.fctx
             rev = f.rev()
             if rev != previousrev:
                 blockhead = True
@@ -924,7 +925,7 @@
                    "file": f.path(),
                    "blockhead": blockhead,
                    "blockparity": blockparity,
-                   "targetline": targetline,
+                   "targetline": aline.lineno,
                    "line": l,
                    "lineno": lineno + 1,
                    "lineid": "l%d" % (lineno + 1),
--- a/tests/test-annotate.py	Mon Oct 02 02:34:47 2017 -0700
+++ b/tests/test-annotate.py	Mon Oct 02 02:34:47 2017 -0700
@@ -7,6 +7,7 @@
     mdiff,
 )
 from mercurial.context import (
+    annotateline,
     _annotatepair,
 )
 
@@ -25,50 +26,76 @@
         diffopts = mdiff.diffopts()
 
         def decorate(text, rev):
-            return ([(rev, i) for i in xrange(1, text.count(b'\n') + 1)], text)
+            return ([annotateline(fctx=rev, lineno=i)
+                     for i in xrange(1, text.count(b'\n') + 1)],
+                    text)
 
         # Basic usage
 
         oldann = decorate(olddata, oldfctx)
         p1ann = decorate(p1data, p1fctx)
         p1ann = _annotatepair([oldann], p1fctx, p1ann, False, diffopts)
-        self.assertEqual(p1ann[0], [('old', 1), ('old', 2), ('p1', 3)])
+        self.assertEqual(p1ann[0], [
+            annotateline('old', 1),
+            annotateline('old', 2),
+            annotateline('p1', 3),
+        ])
 
         p2ann = decorate(p2data, p2fctx)
         p2ann = _annotatepair([oldann], p2fctx, p2ann, False, diffopts)
-        self.assertEqual(p2ann[0], [('old', 1), ('p2', 2), ('p2', 3)])
+        self.assertEqual(p2ann[0], [
+            annotateline('old', 1),
+            annotateline('p2', 2),
+            annotateline('p2', 3),
+        ])
 
         # Test with multiple parents (note the difference caused by ordering)
 
         childann = decorate(childdata, childfctx)
         childann = _annotatepair([p1ann, p2ann], childfctx, childann, False,
                                  diffopts)
-        self.assertEqual(childann[0],
-            [('old', 1), ('c', 2), ('p2', 2), ('c', 4), ('p2', 3)]
-        )
+        self.assertEqual(childann[0], [
+            annotateline('old', 1),
+            annotateline('c', 2),
+            annotateline('p2', 2),
+            annotateline('c', 4),
+            annotateline('p2', 3),
+        ])
 
         childann = decorate(childdata, childfctx)
         childann = _annotatepair([p2ann, p1ann], childfctx, childann, False,
                                  diffopts)
-        self.assertEqual(childann[0],
-            [('old', 1), ('c', 2), ('p1', 3), ('c', 4), ('p2', 3)]
-        )
+        self.assertEqual(childann[0], [
+            annotateline('old', 1),
+            annotateline('c', 2),
+            annotateline('p1', 3),
+            annotateline('c', 4),
+            annotateline('p2', 3),
+        ])
 
         # Test with skipchild (note the difference caused by ordering)
 
         childann = decorate(childdata, childfctx)
         childann = _annotatepair([p1ann, p2ann], childfctx, childann, True,
                                  diffopts)
-        self.assertEqual(childann[0],
-            [('old', 1), ('old', 2), ('p2', 2), ('p2', 2), ('p2', 3)]
-        )
+        self.assertEqual(childann[0], [
+            annotateline('old', 1),
+            annotateline('old', 2),
+            annotateline('p2', 2),
+            annotateline('p2', 2),
+            annotateline('p2', 3),
+        ])
 
         childann = decorate(childdata, childfctx)
         childann = _annotatepair([p2ann, p1ann], childfctx, childann, True,
                                  diffopts)
-        self.assertEqual(childann[0],
-            [('old', 1), ('old', 2), ('p1', 3), ('p1', 3), ('p2', 3)]
-        )
+        self.assertEqual(childann[0], [
+            annotateline('old', 1),
+            annotateline('old', 2),
+            annotateline('p1', 3),
+            annotateline('p1', 3),
+            annotateline('p2', 3),
+        ])
 
 if __name__ == '__main__':
     import silenttestrunner