31 datefunc = util.cachefunc(datefunc) |
31 datefunc = util.cachefunc(datefunc) |
32 getctx = util.cachefunc(lambda x: repo[x[0]]) |
32 getctx = util.cachefunc(lambda x: repo[x[0]]) |
33 hexfunc = self._hexfunc |
33 hexfunc = self._hexfunc |
34 |
34 |
35 # special handling working copy "changeset" and "rev" functions |
35 # special handling working copy "changeset" and "rev" functions |
36 if self.opts.get('rev') == 'wdir()': |
36 if self.opts.get(b'rev') == b'wdir()': |
37 orig = hexfunc |
37 orig = hexfunc |
38 hexfunc = lambda x: None if x is None else orig(x) |
38 hexfunc = lambda x: None if x is None else orig(x) |
39 wnode = hexfunc(repo['.'].node()) + '+' |
39 wnode = hexfunc(repo[b'.'].node()) + b'+' |
40 wrev = '%d' % repo['.'].rev() |
40 wrev = b'%d' % repo[b'.'].rev() |
41 wrevpad = '' |
41 wrevpad = b'' |
42 if not opts.get('changeset'): # only show + if changeset is hidden |
42 if not opts.get(b'changeset'): # only show + if changeset is hidden |
43 wrev += '+' |
43 wrev += b'+' |
44 wrevpad = ' ' |
44 wrevpad = b' ' |
45 revenc = lambda x: wrev if x is None else ('%d' % x) + wrevpad |
45 revenc = lambda x: wrev if x is None else (b'%d' % x) + wrevpad |
46 |
46 |
47 def csetenc(x): |
47 def csetenc(x): |
48 if x is None: |
48 if x is None: |
49 return wnode |
49 return wnode |
50 return pycompat.bytestr(x) + ' ' |
50 return pycompat.bytestr(x) + b' ' |
51 |
51 |
52 else: |
52 else: |
53 revenc = csetenc = pycompat.bytestr |
53 revenc = csetenc = pycompat.bytestr |
54 |
54 |
55 # opt name, separator, raw value (for json/plain), encoder (for plain) |
55 # opt name, separator, raw value (for json/plain), encoder (for plain) |
56 opmap = [ |
56 opmap = [ |
57 ('user', ' ', lambda x: getctx(x).user(), ui.shortuser), |
57 (b'user', b' ', lambda x: getctx(x).user(), ui.shortuser), |
58 ('number', ' ', lambda x: getctx(x).rev(), revenc), |
58 (b'number', b' ', lambda x: getctx(x).rev(), revenc), |
59 ('changeset', ' ', lambda x: hexfunc(x[0]), csetenc), |
59 (b'changeset', b' ', lambda x: hexfunc(x[0]), csetenc), |
60 ('date', ' ', lambda x: getctx(x).date(), datefunc), |
60 (b'date', b' ', lambda x: getctx(x).date(), datefunc), |
61 ('file', ' ', lambda x: x[2], pycompat.bytestr), |
61 (b'file', b' ', lambda x: x[2], pycompat.bytestr), |
62 ('line_number', ':', lambda x: x[1] + 1, pycompat.bytestr), |
62 (b'line_number', b':', lambda x: x[1] + 1, pycompat.bytestr), |
63 ] |
63 ] |
64 fieldnamemap = {'number': 'rev', 'changeset': 'node'} |
64 fieldnamemap = {b'number': b'rev', b'changeset': b'node'} |
65 funcmap = [ |
65 funcmap = [ |
66 (get, sep, fieldnamemap.get(op, op), enc) |
66 (get, sep, fieldnamemap.get(op, op), enc) |
67 for op, sep, get, enc in opmap |
67 for op, sep, get, enc in opmap |
68 if opts.get(op) |
68 if opts.get(op) |
69 ] |
69 ] |
70 # no separator for first column |
70 # no separator for first column |
71 funcmap[0] = list(funcmap[0]) |
71 funcmap[0] = list(funcmap[0]) |
72 funcmap[0][1] = '' |
72 funcmap[0][1] = b'' |
73 self.funcmap = funcmap |
73 self.funcmap = funcmap |
74 |
74 |
75 def write(self, annotatedresult, lines=None, existinglines=None): |
75 def write(self, annotatedresult, lines=None, existinglines=None): |
76 """(annotateresult, [str], set([rev, linenum])) -> None. write output. |
76 """(annotateresult, [str], set([rev, linenum])) -> None. write output. |
77 annotateresult can be [(node, linenum, path)], or [(node, linenum)] |
77 annotateresult can be [(node, linenum, path)], or [(node, linenum)] |
81 |
81 |
82 # calculate padding |
82 # calculate padding |
83 for f, sep, name, enc in self.funcmap: |
83 for f, sep, name, enc in self.funcmap: |
84 l = [enc(f(x)) for x in annotatedresult] |
84 l = [enc(f(x)) for x in annotatedresult] |
85 pieces.append(l) |
85 pieces.append(l) |
86 if name in ['node', 'date']: # node and date has fixed size |
86 if name in [b'node', b'date']: # node and date has fixed size |
87 l = l[:1] |
87 l = l[:1] |
88 widths = pycompat.maplist(encoding.colwidth, set(l)) |
88 widths = pycompat.maplist(encoding.colwidth, set(l)) |
89 maxwidth = max(widths) if widths else 0 |
89 maxwidth = max(widths) if widths else 0 |
90 maxwidths.append(maxwidth) |
90 maxwidths.append(maxwidth) |
91 |
91 |
92 # buffered output |
92 # buffered output |
93 result = '' |
93 result = b'' |
94 for i in pycompat.xrange(len(annotatedresult)): |
94 for i in pycompat.xrange(len(annotatedresult)): |
95 for j, p in enumerate(pieces): |
95 for j, p in enumerate(pieces): |
96 sep = self.funcmap[j][1] |
96 sep = self.funcmap[j][1] |
97 padding = ' ' * (maxwidths[j] - len(p[i])) |
97 padding = b' ' * (maxwidths[j] - len(p[i])) |
98 result += sep + padding + p[i] |
98 result += sep + padding + p[i] |
99 if lines: |
99 if lines: |
100 if existinglines is None: |
100 if existinglines is None: |
101 result += ': ' + lines[i] |
101 result += b': ' + lines[i] |
102 else: # extra formatting showing whether a line exists |
102 else: # extra formatting showing whether a line exists |
103 key = (annotatedresult[i][0], annotatedresult[i][1]) |
103 key = (annotatedresult[i][0], annotatedresult[i][1]) |
104 if key in existinglines: |
104 if key in existinglines: |
105 result += ': ' + lines[i] |
105 result += b': ' + lines[i] |
106 else: |
106 else: |
107 result += ': ' + self.ui.label( |
107 result += b': ' + self.ui.label( |
108 '-' + lines[i], 'diff.deleted' |
108 b'-' + lines[i], b'diff.deleted' |
109 ) |
109 ) |
110 |
110 |
111 if result[-1:] != '\n': |
111 if result[-1:] != b'\n': |
112 result += '\n' |
112 result += b'\n' |
113 |
113 |
114 self.ui.write(result) |
114 self.ui.write(result) |
115 |
115 |
116 @util.propertycache |
116 @util.propertycache |
117 def _hexfunc(self): |
117 def _hexfunc(self): |
118 if self.ui.debugflag or self.opts.get('long_hash'): |
118 if self.ui.debugflag or self.opts.get(b'long_hash'): |
119 return node.hex |
119 return node.hex |
120 else: |
120 else: |
121 return node.short |
121 return node.short |
122 |
122 |
123 def end(self): |
123 def end(self): |
137 pieces = [ |
137 pieces = [ |
138 (name, pycompat.maplist(f, annotatedresult)) |
138 (name, pycompat.maplist(f, annotatedresult)) |
139 for f, sep, name, enc in self.funcmap |
139 for f, sep, name, enc in self.funcmap |
140 ] |
140 ] |
141 if lines is not None: |
141 if lines is not None: |
142 pieces.append(('line', lines)) |
142 pieces.append((b'line', lines)) |
143 pieces.sort() |
143 pieces.sort() |
144 |
144 |
145 seps = [','] * len(pieces[:-1]) + [''] |
145 seps = [b','] * len(pieces[:-1]) + [b''] |
146 |
146 |
147 result = '' |
147 result = b'' |
148 lasti = len(annotatedresult) - 1 |
148 lasti = len(annotatedresult) - 1 |
149 for i in pycompat.xrange(len(annotatedresult)): |
149 for i in pycompat.xrange(len(annotatedresult)): |
150 result += '\n {\n' |
150 result += b'\n {\n' |
151 for j, p in enumerate(pieces): |
151 for j, p in enumerate(pieces): |
152 k, vs = p |
152 k, vs = p |
153 result += ' "%s": %s%s\n' % ( |
153 result += b' "%s": %s%s\n' % ( |
154 k, |
154 k, |
155 templatefilters.json(vs[i], paranoid=False), |
155 templatefilters.json(vs[i], paranoid=False), |
156 seps[j], |
156 seps[j], |
157 ) |
157 ) |
158 result += ' }%s' % ('' if i == lasti else ',') |
158 result += b' }%s' % (b'' if i == lasti else b',') |
159 if lasti >= 0: |
159 if lasti >= 0: |
160 self.needcomma = True |
160 self.needcomma = True |
161 |
161 |
162 self.ui.write(result) |
162 self.ui.write(result) |
163 |
163 |
164 def _writecomma(self): |
164 def _writecomma(self): |
165 if self.needcomma: |
165 if self.needcomma: |
166 self.ui.write(',') |
166 self.ui.write(b',') |
167 self.needcomma = False |
167 self.needcomma = False |
168 |
168 |
169 @util.propertycache |
169 @util.propertycache |
170 def _hexfunc(self): |
170 def _hexfunc(self): |
171 return node.hex |
171 return node.hex |
172 |
172 |
173 def end(self): |
173 def end(self): |
174 self.ui.write('\n]\n') |
174 self.ui.write(b'\n]\n') |