templates: add 'bisect' keyword to return a cset's bisect status
This new 'bisect' template expands to a cset's bisection status (good,
bad and so on...). There is also a new 'shortbisect' filter that yields
a single char representing the cset's bisection status.
It uses the two recently-added hbisect.label() and .shortlabel() functions.
Example output using the repository in test-bisect2.t, and some made-up
state of the 'end at merge' test (with graphlog, it's so explicit):
$ hg glog --template '{rev}:{node|short} {bisect}\n' \
-r 'bisect(range)|bisect(ignored)'
o 17:
228c06deef46: bad
|
o 16:
609d82a7ebae: bad (implicit)
|
o 15:
857b178a7cf3: bad
|\
| o 13:
b0a32c86eb31: good
| |
| o 12:
9f259202bbe7: good (implicit)
| |
| o 11:
82ca6f06eccd: good
| |
@ | 10:
429fcd26f52d: untested
|\ \
| o | 9:
3c77083deb4a: skipped
| |/
| o 8:
dab8161ac8fc: good
| |
o | 6:
a214d5d3811a: ignored
|\ \
| o | 5:
385a529b6670: ignored
| | |
o | | 4:
5c668c22234f: ignored
| | |
o | | 3:
0950834f0a9c: ignored
|/ /
o / 2:
051e12f87bf1: ignored
|/
And now the same with the short label:
$ hg log --template '{bisect|shortbisect} {rev}:{node|short}\n'
18:
d42e18c7bc9b
B 17:
228c06deef46
B 16:
609d82a7ebae
B 15:
857b178a7cf3
14:
faa450606157
G 13:
b0a32c86eb31
G 12:
9f259202bbe7
G 11:
82ca6f06eccd
U 10:
429fcd26f52d
S 9:
3c77083deb4a
G 8:
dab8161ac8fc
7:
50c76098bbf2
I 6:
a214d5d3811a
I 5:
385a529b6670
I 4:
5c668c22234f
I 3:
0950834f0a9c
I 2:
051e12f87bf1
1:
4ca5088da217
0:
33b1f9bc8bc5
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
# ignore.py - ignored file handling for mercurial
#
# Copyright 2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from i18n import _
import util, match
import re
_commentre = None
def ignorepats(lines):
'''parse lines (iterable) of .hgignore text, returning a tuple of
(patterns, parse errors). These patterns should be given to compile()
to be validated and converted into a match function.'''
syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
syntax = 'relre:'
patterns = []
warnings = []
for line in lines:
if "#" in line:
global _commentre
if not _commentre:
_commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
# remove comments prefixed by an even number of escapes
line = _commentre.sub(r'\1', line)
# fixup properly escaped comments that survived the above
line = line.replace("\\#", "#")
line = line.rstrip()
if not line:
continue
if line.startswith('syntax:'):
s = line[7:].strip()
try:
syntax = syntaxes[s]
except KeyError:
warnings.append(_("ignoring invalid syntax '%s'") % s)
continue
pat = syntax + line
for s, rels in syntaxes.iteritems():
if line.startswith(rels):
pat = line
break
elif line.startswith(s+':'):
pat = rels + line[len(s)+1:]
break
patterns.append(pat)
return patterns, warnings
def ignore(root, files, warn):
'''return matcher covering patterns in 'files'.
the files parsed for patterns include:
.hgignore in the repository root
any additional files specified in the [ui] section of ~/.hgrc
trailing white space is dropped.
the escape character is backslash.
comments start with #.
empty lines are skipped.
lines can be of the following formats:
syntax: regexp # defaults following lines to non-rooted regexps
syntax: glob # defaults following lines to non-rooted globs
re:pattern # non-rooted regular expression
glob:pattern # non-rooted glob
pattern # pattern of the current default type'''
pats = {}
for f in files:
try:
pats[f] = []
fp = open(f)
pats[f], warnings = ignorepats(fp)
for warning in warnings:
warn("%s: %s\n" % (f, warning))
except IOError, inst:
if f != files[0]:
warn(_("skipping unreadable ignore file '%s': %s\n") %
(f, inst.strerror))
allpats = []
for patlist in pats.values():
allpats.extend(patlist)
if not allpats:
return util.never
try:
ignorefunc = match.match(root, '', [], allpats)
except util.Abort:
# Re-raise an exception where the src is the right file
for f, patlist in pats.iteritems():
try:
match.match(root, '', [], patlist)
except util.Abort, inst:
raise util.Abort('%s: %s' % (f, inst[0]))
return ignorefunc