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
--- 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