##// END OF EJS Templates
log: add support for bookmarks...
log: add support for bookmarks A bookmark can already be pushed with 'hg push origin -B topic-foo'. The pull command also supports bookmarks. This patch adds support for bookmarks using the '_opt2logrevset' code path. The list of changesets for a bookmark can now be obtained simply with: 'hg log -B topic-foo'. Reviewed-by: Elenie Godzaridis <arangradient@gmail.com> Differential Revision: https://phab.mercurial-scm.org/D8973

File last commit:

r43347:687b865b default
r46123:2517df77 default
Show More
formatter.py
174 lines | 5.8 KiB | text/x-python | PythonLexer
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 # Copyright 2016-present Facebook. All Rights Reserved.
#
# format: defines the format used to output annotate result
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from mercurial import (
encoding,
node,
pycompat,
templatefilters,
util,
)
Augie Fackler
formatting: blacken the codebase...
r43346 from mercurial.utils import dateutil
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
# imitating mercurial.commands.annotate, not using the vanilla formatter since
# the data structures are a bit different, and we have some fast paths.
class defaultformatter(object):
"""the default formatter that does leftpad and support some common flags"""
def __init__(self, ui, repo, opts):
self.ui = ui
self.opts = opts
if ui.quiet:
datefunc = dateutil.shortdate
else:
datefunc = dateutil.datestr
datefunc = util.cachefunc(datefunc)
getctx = util.cachefunc(lambda x: repo[x[0]])
hexfunc = self._hexfunc
# special handling working copy "changeset" and "rev" functions
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.opts.get(b'rev') == b'wdir()':
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 orig = hexfunc
hexfunc = lambda x: None if x is None else orig(x)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 wnode = hexfunc(repo[b'.'].node()) + b'+'
wrev = b'%d' % repo[b'.'].rev()
wrevpad = b''
if not opts.get(b'changeset'): # only show + if changeset is hidden
wrev += b'+'
wrevpad = b' '
revenc = lambda x: wrev if x is None else (b'%d' % x) + wrevpad
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
py3: replace str() with pycompat.bytestr() or ('%d' % int)...
r40763 def csetenc(x):
if x is None:
return wnode
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return pycompat.bytestr(x) + b' '
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 else:
Pulkit Goyal
py3: replace str() with pycompat.bytestr() or ('%d' % int)...
r40763 revenc = csetenc = pycompat.bytestr
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
# opt name, separator, raw value (for json/plain), encoder (for plain)
Augie Fackler
formatting: blacken the codebase...
r43346 opmap = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'user', b' ', lambda x: getctx(x).user(), ui.shortuser),
(b'number', b' ', lambda x: getctx(x).rev(), revenc),
(b'changeset', b' ', lambda x: hexfunc(x[0]), csetenc),
(b'date', b' ', lambda x: getctx(x).date(), datefunc),
(b'file', b' ', lambda x: x[2], pycompat.bytestr),
(b'line_number', b':', lambda x: x[1] + 1, pycompat.bytestr),
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fieldnamemap = {b'number': b'rev', b'changeset': b'node'}
Augie Fackler
formatting: blacken the codebase...
r43346 funcmap = [
(get, sep, fieldnamemap.get(op, op), enc)
for op, sep, get, enc in opmap
if opts.get(op)
]
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 # no separator for first column
funcmap[0] = list(funcmap[0])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 funcmap[0][1] = b''
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 self.funcmap = funcmap
def write(self, annotatedresult, lines=None, existinglines=None):
"""(annotateresult, [str], set([rev, linenum])) -> None. write output.
annotateresult can be [(node, linenum, path)], or [(node, linenum)]
"""
Augie Fackler
formatting: blacken the codebase...
r43346 pieces = [] # [[str]]
maxwidths = [] # [int]
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
# calculate padding
for f, sep, name, enc in self.funcmap:
l = [enc(f(x)) for x in annotatedresult]
pieces.append(l)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if name in [b'node', b'date']: # node and date has fixed size
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 l = l[:1]
Pulkit Goyal
py3: use pycompat.maplist instead of map...
r39762 widths = pycompat.maplist(encoding.colwidth, set(l))
Augie Fackler
formatting: blacken the codebase...
r43346 maxwidth = max(widths) if widths else 0
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 maxwidths.append(maxwidth)
# buffered output
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result = b''
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 for i in pycompat.xrange(len(annotatedresult)):
for j, p in enumerate(pieces):
sep = self.funcmap[j][1]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 padding = b' ' * (maxwidths[j] - len(p[i]))
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 result += sep + padding + p[i]
if lines:
if existinglines is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b': ' + lines[i]
Augie Fackler
formatting: blacken the codebase...
r43346 else: # extra formatting showing whether a line exists
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 key = (annotatedresult[i][0], annotatedresult[i][1])
if key in existinglines:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b': ' + lines[i]
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b': ' + self.ui.label(
b'-' + lines[i], b'diff.deleted'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if result[-1:] != b'\n':
result += b'\n'
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
self.ui.write(result)
@util.propertycache
def _hexfunc(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.ui.debugflag or self.opts.get(b'long_hash'):
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 return node.hex
else:
return node.short
def end(self):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 class jsonformatter(defaultformatter):
def __init__(self, ui, repo, opts):
super(jsonformatter, self).__init__(ui, repo, opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b'[')
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 self.needcomma = False
def write(self, annotatedresult, lines=None, existinglines=None):
if annotatedresult:
self._writecomma()
Augie Fackler
formatting: blacken the codebase...
r43346 pieces = [
(name, pycompat.maplist(f, annotatedresult))
for f, sep, name, enc in self.funcmap
]
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 if lines is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pieces.append((b'line', lines))
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 pieces.sort()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 seps = [b','] * len(pieces[:-1]) + [b'']
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result = b''
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 lasti = len(annotatedresult) - 1
for i in pycompat.xrange(len(annotatedresult)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b'\n {\n'
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 for j, p in enumerate(pieces):
k, vs = p
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b' "%s": %s%s\n' % (
Augie Fackler
formatting: blacken the codebase...
r43346 k,
templatefilters.json(vs[i], paranoid=False),
seps[j],
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b' }%s' % (b'' if i == lasti else b',')
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 if lasti >= 0:
self.needcomma = True
self.ui.write(result)
def _writecomma(self):
if self.needcomma:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b',')
Augie Fackler
fastannotate: initial import from Facebook's hg-experimental...
r39243 self.needcomma = False
@util.propertycache
def _hexfunc(self):
return node.hex
def end(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write(b'\n]\n')