annotate hgext/fastannotate/formatter.py @ 39772:ae531f5e583c

testing: add interface unit tests for file storage Our strategy for supporting alternate storage backends is to define interfaces for everything then "code to the interface." We already have interfaces for various primitives, including file and manifest storage. What we don't have is generic unit tests for those interfaces. Up to this point we've been relying on high-level integration tests (mainly in the form of existing .t tests) to test alternate storage backends. And my experience with developing the "simple store" test extension is that such testing is very tedious: it takes several minutes to run all tests and when you find a failure, it is often non-trivial to debug. This commit starts to change that. This commit introduces the mercurial.testing.storage module. It contains testing code for storage. Currently, it defines some unittest.TestCase classes for testing the file storage interfaces. It also defines some factory functions that allow a caller to easily spawn a custom TestCase "bound" to a specific file storage backend implementation. A new .py test has been added. It simply defines a callable to produce filelog and transaction instances on demand and then "registers" the various test classes so the filelog class can be tested with the storage interface unit tests. As part of writing the tests, I identified a couple of apparent bugs in revlog.py and filelog.py! These are tracked with inline TODO comments. Writing the tests makes it more obvious where the storage interface is lacking. For example, we raise either IndexError or error.LookupError for missing revisions depending on whether we use an integer revision or a node. Also, we raise error.RevlogError in various places when we should be raising a storage-agnostic error type. The storage interfaces are currently far from perfect and there is much work to be done to improve them. But at least with this commit we finally have the start of unit tests that can be used to "qualify" the behavior of a storage backend. And when implementing and debugging new storage backends, we now have an obvious place to define new tests and have obvious places to insert breakpoints to facilitate debugging. This should be invaluable when implementing new storage backends. I added the mercurial.testing package because these interface conformance tests are generic and need to be usable by all storage backends. Having the code live in tests/ would make it difficult for storage backends implemented in extensions to test their interface conformance. First, it would require obtaining a copy of Mercurial's storage test code in order to test. Second, it would make testing against multiple Mercurial versions difficult, as you would need to import N copies of the storage testing code in order to achieve test coverage. By making the test code part of the Mercurial distribution itself, extensions can `import mercurial.testing.*` to access and run the test code. The test will run against whatever Mercurial version is active. FWIW I've always wanted to move parts of run-tests.py into the mercurial.* package to make the testing story simpler (e.g. imagine an `hg debugruntests` command that could invoke the test harness). While I have no plans to do that in the near future, establishing the mercurial.testing package does provide a natural home for that code should someone do this in the future. Differential Revision: https://phab.mercurial-scm.org/D4650
author Gregory Szorc <gregory.szorc@gmail.com>
date Tue, 18 Sep 2018 16:52:11 -0700
parents 7e3ce2131882
children 001f27970b60
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
39210
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
1 # Copyright 2016-present Facebook. All Rights Reserved.
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
2 #
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
3 # format: defines the format used to output annotate result
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
4 #
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
7 from __future__ import absolute_import
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
8
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
9 from mercurial import (
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
10 encoding,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
11 node,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
12 pycompat,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
13 templatefilters,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
14 util,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
15 )
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
16 from mercurial.utils import (
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
17 dateutil,
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
18 )
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
19
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
20 # imitating mercurial.commands.annotate, not using the vanilla formatter since
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
21 # the data structures are a bit different, and we have some fast paths.
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
22 class defaultformatter(object):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
23 """the default formatter that does leftpad and support some common flags"""
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
24
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
25 def __init__(self, ui, repo, opts):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
26 self.ui = ui
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
27 self.opts = opts
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
28
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
29 if ui.quiet:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
30 datefunc = dateutil.shortdate
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
31 else:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
32 datefunc = dateutil.datestr
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
33 datefunc = util.cachefunc(datefunc)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
34 getctx = util.cachefunc(lambda x: repo[x[0]])
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
35 hexfunc = self._hexfunc
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
36
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
37 # special handling working copy "changeset" and "rev" functions
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
38 if self.opts.get('rev') == 'wdir()':
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
39 orig = hexfunc
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
40 hexfunc = lambda x: None if x is None else orig(x)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
41 wnode = hexfunc(repo[None].p1().node()) + '+'
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
42 wrev = str(repo[None].p1().rev())
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
43 wrevpad = ''
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
44 if not opts.get('changeset'): # only show + if changeset is hidden
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
45 wrev += '+'
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
46 wrevpad = ' '
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
47 revenc = lambda x: wrev if x is None else str(x) + wrevpad
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
48 csetenc = lambda x: wnode if x is None else str(x) + ' '
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
49 else:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
50 revenc = csetenc = str
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
51
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
52 # opt name, separator, raw value (for json/plain), encoder (for plain)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
53 opmap = [('user', ' ', lambda x: getctx(x).user(), ui.shortuser),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
54 ('number', ' ', lambda x: getctx(x).rev(), revenc),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
55 ('changeset', ' ', lambda x: hexfunc(x[0]), csetenc),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
56 ('date', ' ', lambda x: getctx(x).date(), datefunc),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
57 ('file', ' ', lambda x: x[2], str),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
58 ('line_number', ':', lambda x: x[1] + 1, str)]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
59 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
60 funcmap = [(get, sep, fieldnamemap.get(op, op), enc)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
61 for op, sep, get, enc in opmap
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
62 if opts.get(op)]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
63 # no separator for first column
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
64 funcmap[0] = list(funcmap[0])
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
65 funcmap[0][1] = ''
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
66 self.funcmap = funcmap
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
67
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
68 def write(self, annotatedresult, lines=None, existinglines=None):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
69 """(annotateresult, [str], set([rev, linenum])) -> None. write output.
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
70 annotateresult can be [(node, linenum, path)], or [(node, linenum)]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
71 """
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
72 pieces = [] # [[str]]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
73 maxwidths = [] # [int]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
74
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
75 # calculate padding
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
76 for f, sep, name, enc in self.funcmap:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
77 l = [enc(f(x)) for x in annotatedresult]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
78 pieces.append(l)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
79 if name in ['node', 'date']: # node and date has fixed size
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
80 l = l[:1]
39726
7e3ce2131882 py3: use pycompat.maplist instead of map
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 39210
diff changeset
81 widths = pycompat.maplist(encoding.colwidth, set(l))
39210
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
82 maxwidth = (max(widths) if widths else 0)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
83 maxwidths.append(maxwidth)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
84
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
85 # buffered output
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
86 result = ''
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
87 for i in pycompat.xrange(len(annotatedresult)):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
88 for j, p in enumerate(pieces):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
89 sep = self.funcmap[j][1]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
90 padding = ' ' * (maxwidths[j] - len(p[i]))
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
91 result += sep + padding + p[i]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
92 if lines:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
93 if existinglines is None:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
94 result += ': ' + lines[i]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
95 else: # extra formatting showing whether a line exists
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
96 key = (annotatedresult[i][0], annotatedresult[i][1])
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
97 if key in existinglines:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
98 result += ': ' + lines[i]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
99 else:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
100 result += ': ' + self.ui.label('-' + lines[i],
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
101 'diff.deleted')
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
102
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
103 if result[-1] != '\n':
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
104 result += '\n'
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
105
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
106 self.ui.write(result)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
107
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
108 @util.propertycache
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
109 def _hexfunc(self):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
110 if self.ui.debugflag or self.opts.get('long_hash'):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
111 return node.hex
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
112 else:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
113 return node.short
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
114
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
115 def end(self):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
116 pass
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
117
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
118 class jsonformatter(defaultformatter):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
119 def __init__(self, ui, repo, opts):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
120 super(jsonformatter, self).__init__(ui, repo, opts)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
121 self.ui.write('[')
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
122 self.needcomma = False
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
123
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
124 def write(self, annotatedresult, lines=None, existinglines=None):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
125 if annotatedresult:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
126 self._writecomma()
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
127
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
128 pieces = [(name, map(f, annotatedresult))
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
129 for f, sep, name, enc in self.funcmap]
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
130 if lines is not None:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
131 pieces.append(('line', lines))
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
132 pieces.sort()
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
133
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
134 seps = [','] * len(pieces[:-1]) + ['']
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
135
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
136 result = ''
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
137 lasti = len(annotatedresult) - 1
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
138 for i in pycompat.xrange(len(annotatedresult)):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
139 result += '\n {\n'
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
140 for j, p in enumerate(pieces):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
141 k, vs = p
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
142 result += (' "%s": %s%s\n'
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
143 % (k, templatefilters.json(vs[i], paranoid=False),
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
144 seps[j]))
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
145 result += ' }%s' % ('' if i == lasti else ',')
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
146 if lasti >= 0:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
147 self.needcomma = True
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
148
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
149 self.ui.write(result)
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
150
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
151 def _writecomma(self):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
152 if self.needcomma:
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
153 self.ui.write(',')
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
154 self.needcomma = False
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
155
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
156 @util.propertycache
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
157 def _hexfunc(self):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
158 return node.hex
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
159
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
160 def end(self):
1ddb296e0dee fastannotate: initial import from Facebook's hg-experimental
Augie Fackler <augie@google.com>
parents:
diff changeset
161 self.ui.write('\n]\n')