##// END OF EJS Templates
merge with stable
Matt Mackall -
r25662:ff5172c8 merge default
parent child Browse files
Show More
@@ -1,669 +1,671
1 # match.py - filename matching
1 # match.py - filename matching
2 #
2 #
3 # Copyright 2008, 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2008, 2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import copy, re
8 import copy, re
9 import util, pathutil
9 import util, pathutil
10 from i18n import _
10 from i18n import _
11
11
12 propertycache = util.propertycache
12 propertycache = util.propertycache
13
13
14 def _rematcher(regex):
14 def _rematcher(regex):
15 '''compile the regexp with the best available regexp engine and return a
15 '''compile the regexp with the best available regexp engine and return a
16 matcher function'''
16 matcher function'''
17 m = util.re.compile(regex)
17 m = util.re.compile(regex)
18 try:
18 try:
19 # slightly faster, provided by facebook's re2 bindings
19 # slightly faster, provided by facebook's re2 bindings
20 return m.test_match
20 return m.test_match
21 except AttributeError:
21 except AttributeError:
22 return m.match
22 return m.match
23
23
24 def _expandsets(kindpats, ctx, listsubrepos):
24 def _expandsets(kindpats, ctx, listsubrepos):
25 '''Returns the kindpats list with the 'set' patterns expanded.'''
25 '''Returns the kindpats list with the 'set' patterns expanded.'''
26 fset = set()
26 fset = set()
27 other = []
27 other = []
28
28
29 for kind, pat, source in kindpats:
29 for kind, pat, source in kindpats:
30 if kind == 'set':
30 if kind == 'set':
31 if not ctx:
31 if not ctx:
32 raise util.Abort("fileset expression with no context")
32 raise util.Abort("fileset expression with no context")
33 s = ctx.getfileset(pat)
33 s = ctx.getfileset(pat)
34 fset.update(s)
34 fset.update(s)
35
35
36 if listsubrepos:
36 if listsubrepos:
37 for subpath in ctx.substate:
37 for subpath in ctx.substate:
38 s = ctx.sub(subpath).getfileset(pat)
38 s = ctx.sub(subpath).getfileset(pat)
39 fset.update(subpath + '/' + f for f in s)
39 fset.update(subpath + '/' + f for f in s)
40
40
41 continue
41 continue
42 other.append((kind, pat, source))
42 other.append((kind, pat, source))
43 return fset, other
43 return fset, other
44
44
45 def _expandsubinclude(kindpats, root):
45 def _expandsubinclude(kindpats, root):
46 '''Returns the list of subinclude matchers and the kindpats without the
46 '''Returns the list of subinclude matchers and the kindpats without the
47 subincludes in it.'''
47 subincludes in it.'''
48 relmatchers = []
48 relmatchers = []
49 other = []
49 other = []
50
50
51 for kind, pat, source in kindpats:
51 for kind, pat, source in kindpats:
52 if kind == 'subinclude':
52 if kind == 'subinclude':
53 sourceroot = pathutil.dirname(util.normpath(source))
53 sourceroot = pathutil.dirname(util.normpath(source))
54 pat = util.pconvert(pat)
54 pat = util.pconvert(pat)
55 path = pathutil.join(sourceroot, pat)
55 path = pathutil.join(sourceroot, pat)
56
56
57 newroot = pathutil.dirname(path)
57 newroot = pathutil.dirname(path)
58 relmatcher = match(newroot, '', [], ['include:%s' % path])
58 relmatcher = match(newroot, '', [], ['include:%s' % path])
59
59
60 prefix = pathutil.canonpath(root, root, newroot)
60 prefix = pathutil.canonpath(root, root, newroot)
61 if prefix:
61 if prefix:
62 prefix += '/'
62 prefix += '/'
63 relmatchers.append((prefix, relmatcher))
63 relmatchers.append((prefix, relmatcher))
64 else:
64 else:
65 other.append((kind, pat, source))
65 other.append((kind, pat, source))
66
66
67 return relmatchers, other
67 return relmatchers, other
68
68
69 def _kindpatsalwaysmatch(kindpats):
69 def _kindpatsalwaysmatch(kindpats):
70 """"Checks whether the kindspats match everything, as e.g.
70 """"Checks whether the kindspats match everything, as e.g.
71 'relpath:.' does.
71 'relpath:.' does.
72 """
72 """
73 for kind, pat, source in kindpats:
73 for kind, pat, source in kindpats:
74 if pat != '' or kind not in ['relpath', 'glob']:
74 if pat != '' or kind not in ['relpath', 'glob']:
75 return False
75 return False
76 return True
76 return True
77
77
78 class match(object):
78 class match(object):
79 def __init__(self, root, cwd, patterns, include=[], exclude=[],
79 def __init__(self, root, cwd, patterns, include=[], exclude=[],
80 default='glob', exact=False, auditor=None, ctx=None,
80 default='glob', exact=False, auditor=None, ctx=None,
81 listsubrepos=False, warn=None, badfn=None):
81 listsubrepos=False, warn=None, badfn=None):
82 """build an object to match a set of file patterns
82 """build an object to match a set of file patterns
83
83
84 arguments:
84 arguments:
85 root - the canonical root of the tree you're matching against
85 root - the canonical root of the tree you're matching against
86 cwd - the current working directory, if relevant
86 cwd - the current working directory, if relevant
87 patterns - patterns to find
87 patterns - patterns to find
88 include - patterns to include (unless they are excluded)
88 include - patterns to include (unless they are excluded)
89 exclude - patterns to exclude (even if they are included)
89 exclude - patterns to exclude (even if they are included)
90 default - if a pattern in patterns has no explicit type, assume this one
90 default - if a pattern in patterns has no explicit type, assume this one
91 exact - patterns are actually filenames (include/exclude still apply)
91 exact - patterns are actually filenames (include/exclude still apply)
92 warn - optional function used for printing warnings
92 warn - optional function used for printing warnings
93 badfn - optional bad() callback for this matcher instead of the default
93 badfn - optional bad() callback for this matcher instead of the default
94
94
95 a pattern is one of:
95 a pattern is one of:
96 'glob:<glob>' - a glob relative to cwd
96 'glob:<glob>' - a glob relative to cwd
97 're:<regexp>' - a regular expression
97 're:<regexp>' - a regular expression
98 'path:<path>' - a path relative to repository root
98 'path:<path>' - a path relative to repository root
99 'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
99 'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
100 'relpath:<path>' - a path relative to cwd
100 'relpath:<path>' - a path relative to cwd
101 'relre:<regexp>' - a regexp that needn't match the start of a name
101 'relre:<regexp>' - a regexp that needn't match the start of a name
102 'set:<fileset>' - a fileset expression
102 'set:<fileset>' - a fileset expression
103 'include:<path>' - a file of patterns to read and include
103 'include:<path>' - a file of patterns to read and include
104 'subinclude:<path>' - a file of patterns to match against files under
104 'subinclude:<path>' - a file of patterns to match against files under
105 the same directory
105 the same directory
106 '<something>' - a pattern of the specified default type
106 '<something>' - a pattern of the specified default type
107 """
107 """
108
108
109 self._root = root
109 self._root = root
110 self._cwd = cwd
110 self._cwd = cwd
111 self._files = [] # exact files and roots of patterns
111 self._files = [] # exact files and roots of patterns
112 self._anypats = bool(include or exclude)
112 self._anypats = bool(include or exclude)
113 self._always = False
113 self._always = False
114 self._pathrestricted = bool(include or exclude or patterns)
114 self._pathrestricted = bool(include or exclude or patterns)
115 self._warn = warn
115 self._warn = warn
116 self._includeroots = set()
116 self._includeroots = set()
117 self._includedirs = set(['.'])
117 self._includedirs = set(['.'])
118 self._excluderoots = set()
118 self._excluderoots = set()
119
119
120 if badfn is not None:
120 if badfn is not None:
121 self.bad = badfn
121 self.bad = badfn
122
122
123 matchfns = []
123 matchfns = []
124 if include:
124 if include:
125 kindpats = self._normalize(include, 'glob', root, cwd, auditor)
125 kindpats = self._normalize(include, 'glob', root, cwd, auditor)
126 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)',
126 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)',
127 listsubrepos, root)
127 listsubrepos, root)
128 self._includeroots.update(_roots(kindpats))
128 self._includeroots.update(_roots(kindpats))
129 self._includedirs.update(util.dirs(self._includeroots))
129 self._includedirs.update(util.dirs(self._includeroots))
130 matchfns.append(im)
130 matchfns.append(im)
131 if exclude:
131 if exclude:
132 kindpats = self._normalize(exclude, 'glob', root, cwd, auditor)
132 kindpats = self._normalize(exclude, 'glob', root, cwd, auditor)
133 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)',
133 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)',
134 listsubrepos, root)
134 listsubrepos, root)
135 if not _anypats(kindpats):
135 if not _anypats(kindpats):
136 self._excluderoots.update(_roots(kindpats))
136 self._excluderoots.update(_roots(kindpats))
137 matchfns.append(lambda f: not em(f))
137 matchfns.append(lambda f: not em(f))
138 if exact:
138 if exact:
139 if isinstance(patterns, list):
139 if isinstance(patterns, list):
140 self._files = patterns
140 self._files = patterns
141 else:
141 else:
142 self._files = list(patterns)
142 self._files = list(patterns)
143 matchfns.append(self.exact)
143 matchfns.append(self.exact)
144 elif patterns:
144 elif patterns:
145 kindpats = self._normalize(patterns, default, root, cwd, auditor)
145 kindpats = self._normalize(patterns, default, root, cwd, auditor)
146 if not _kindpatsalwaysmatch(kindpats):
146 if not _kindpatsalwaysmatch(kindpats):
147 self._files = _roots(kindpats)
147 self._files = _roots(kindpats)
148 self._anypats = self._anypats or _anypats(kindpats)
148 self._anypats = self._anypats or _anypats(kindpats)
149 self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
149 self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
150 listsubrepos, root)
150 listsubrepos, root)
151 matchfns.append(pm)
151 matchfns.append(pm)
152
152
153 if not matchfns:
153 if not matchfns:
154 m = util.always
154 m = util.always
155 self._always = True
155 self._always = True
156 elif len(matchfns) == 1:
156 elif len(matchfns) == 1:
157 m = matchfns[0]
157 m = matchfns[0]
158 else:
158 else:
159 def m(f):
159 def m(f):
160 for matchfn in matchfns:
160 for matchfn in matchfns:
161 if not matchfn(f):
161 if not matchfn(f):
162 return False
162 return False
163 return True
163 return True
164
164
165 self.matchfn = m
165 self.matchfn = m
166 self._fileroots = set(self._files)
166 self._fileroots = set(self._files)
167
167
168 def __call__(self, fn):
168 def __call__(self, fn):
169 return self.matchfn(fn)
169 return self.matchfn(fn)
170 def __iter__(self):
170 def __iter__(self):
171 for f in self._files:
171 for f in self._files:
172 yield f
172 yield f
173
173
174 # Callbacks related to how the matcher is used by dirstate.walk.
174 # Callbacks related to how the matcher is used by dirstate.walk.
175 # Subscribers to these events must monkeypatch the matcher object.
175 # Subscribers to these events must monkeypatch the matcher object.
176 def bad(self, f, msg):
176 def bad(self, f, msg):
177 '''Callback from dirstate.walk for each explicit file that can't be
177 '''Callback from dirstate.walk for each explicit file that can't be
178 found/accessed, with an error message.'''
178 found/accessed, with an error message.'''
179 pass
179 pass
180
180
181 # If an explicitdir is set, it will be called when an explicitly listed
181 # If an explicitdir is set, it will be called when an explicitly listed
182 # directory is visited.
182 # directory is visited.
183 explicitdir = None
183 explicitdir = None
184
184
185 # If an traversedir is set, it will be called when a directory discovered
185 # If an traversedir is set, it will be called when a directory discovered
186 # by recursive traversal is visited.
186 # by recursive traversal is visited.
187 traversedir = None
187 traversedir = None
188
188
189 def abs(self, f):
189 def abs(self, f):
190 '''Convert a repo path back to path that is relative to the root of the
190 '''Convert a repo path back to path that is relative to the root of the
191 matcher.'''
191 matcher.'''
192 return f
192 return f
193
193
194 def rel(self, f):
194 def rel(self, f):
195 '''Convert repo path back to path that is relative to cwd of matcher.'''
195 '''Convert repo path back to path that is relative to cwd of matcher.'''
196 return util.pathto(self._root, self._cwd, f)
196 return util.pathto(self._root, self._cwd, f)
197
197
198 def uipath(self, f):
198 def uipath(self, f):
199 '''Convert repo path to a display path. If patterns or -I/-X were used
199 '''Convert repo path to a display path. If patterns or -I/-X were used
200 to create this matcher, the display path will be relative to cwd.
200 to create this matcher, the display path will be relative to cwd.
201 Otherwise it is relative to the root of the repo.'''
201 Otherwise it is relative to the root of the repo.'''
202 return (self._pathrestricted and self.rel(f)) or self.abs(f)
202 return (self._pathrestricted and self.rel(f)) or self.abs(f)
203
203
204 def files(self):
204 def files(self):
205 '''Explicitly listed files or patterns or roots:
205 '''Explicitly listed files or patterns or roots:
206 if no patterns or .always(): empty list,
206 if no patterns or .always(): empty list,
207 if exact: list exact files,
207 if exact: list exact files,
208 if not .anypats(): list all files and dirs,
208 if not .anypats(): list all files and dirs,
209 else: optimal roots'''
209 else: optimal roots'''
210 return self._files
210 return self._files
211
211
212 @propertycache
212 @propertycache
213 def _dirs(self):
213 def _dirs(self):
214 return set(util.dirs(self._fileroots)) | set(['.'])
214 return set(util.dirs(self._fileroots)) | set(['.'])
215
215
216 def visitdir(self, dir):
216 def visitdir(self, dir):
217 '''Decides whether a directory should be visited based on whether it
217 '''Decides whether a directory should be visited based on whether it
218 has potential matches in it or one of its subdirectories. This is
218 has potential matches in it or one of its subdirectories. This is
219 based on the match's primary, included, and excluded patterns.
219 based on the match's primary, included, and excluded patterns.
220
220
221 This function's behavior is undefined if it has returned False for
221 This function's behavior is undefined if it has returned False for
222 one of the dir's parent directories.
222 one of the dir's parent directories.
223 '''
223 '''
224 if dir in self._excluderoots:
224 if dir in self._excluderoots:
225 return False
225 return False
226 if (self._includeroots and
226 if (self._includeroots and
227 '.' not in self._includeroots and
227 '.' not in self._includeroots and
228 dir not in self._includeroots and
228 dir not in self._includeroots and
229 dir not in self._includedirs and
229 dir not in self._includedirs and
230 not any(parent in self._includeroots
230 not any(parent in self._includeroots
231 for parent in util.finddirs(dir))):
231 for parent in util.finddirs(dir))):
232 return False
232 return False
233 return (not self._fileroots or
233 return (not self._fileroots or
234 '.' in self._fileroots or
234 '.' in self._fileroots or
235 dir in self._fileroots or
235 dir in self._fileroots or
236 dir in self._dirs or
236 dir in self._dirs or
237 any(parentdir in self._fileroots
237 any(parentdir in self._fileroots
238 for parentdir in util.finddirs(dir)))
238 for parentdir in util.finddirs(dir)))
239
239
240 def exact(self, f):
240 def exact(self, f):
241 '''Returns True if f is in .files().'''
241 '''Returns True if f is in .files().'''
242 return f in self._fileroots
242 return f in self._fileroots
243
243
244 def anypats(self):
244 def anypats(self):
245 '''Matcher uses patterns or include/exclude.'''
245 '''Matcher uses patterns or include/exclude.'''
246 return self._anypats
246 return self._anypats
247
247
248 def always(self):
248 def always(self):
249 '''Matcher will match everything and .files() will be empty
249 '''Matcher will match everything and .files() will be empty
250 - optimization might be possible and necessary.'''
250 - optimization might be possible and necessary.'''
251 return self._always
251 return self._always
252
252
253 def ispartial(self):
253 def ispartial(self):
254 '''True if the matcher won't always match.
254 '''True if the matcher won't always match.
255
255
256 Although it's just the inverse of _always in this implementation,
256 Although it's just the inverse of _always in this implementation,
257 an extenion such as narrowhg might make it return something
257 an extenion such as narrowhg might make it return something
258 slightly different.'''
258 slightly different.'''
259 return not self._always
259 return not self._always
260
260
261 def isexact(self):
261 def isexact(self):
262 return self.matchfn == self.exact
262 return self.matchfn == self.exact
263
263
264 def prefix(self):
264 def prefix(self):
265 return not self.always() and not self.isexact() and not self.anypats()
265 return not self.always() and not self.isexact() and not self.anypats()
266
266
267 def _normalize(self, patterns, default, root, cwd, auditor):
267 def _normalize(self, patterns, default, root, cwd, auditor):
268 '''Convert 'kind:pat' from the patterns list to tuples with kind and
268 '''Convert 'kind:pat' from the patterns list to tuples with kind and
269 normalized and rooted patterns and with listfiles expanded.'''
269 normalized and rooted patterns and with listfiles expanded.'''
270 kindpats = []
270 kindpats = []
271 for kind, pat in [_patsplit(p, default) for p in patterns]:
271 for kind, pat in [_patsplit(p, default) for p in patterns]:
272 if kind in ('glob', 'relpath'):
272 if kind in ('glob', 'relpath'):
273 pat = pathutil.canonpath(root, cwd, pat, auditor)
273 pat = pathutil.canonpath(root, cwd, pat, auditor)
274 elif kind in ('relglob', 'path'):
274 elif kind in ('relglob', 'path'):
275 pat = util.normpath(pat)
275 pat = util.normpath(pat)
276 elif kind in ('listfile', 'listfile0'):
276 elif kind in ('listfile', 'listfile0'):
277 try:
277 try:
278 files = util.readfile(pat)
278 files = util.readfile(pat)
279 if kind == 'listfile0':
279 if kind == 'listfile0':
280 files = files.split('\0')
280 files = files.split('\0')
281 else:
281 else:
282 files = files.splitlines()
282 files = files.splitlines()
283 files = [f for f in files if f]
283 files = [f for f in files if f]
284 except EnvironmentError:
284 except EnvironmentError:
285 raise util.Abort(_("unable to read file list (%s)") % pat)
285 raise util.Abort(_("unable to read file list (%s)") % pat)
286 for k, p, source in self._normalize(files, default, root, cwd,
286 for k, p, source in self._normalize(files, default, root, cwd,
287 auditor):
287 auditor):
288 kindpats.append((k, p, pat))
288 kindpats.append((k, p, pat))
289 continue
289 continue
290 elif kind == 'include':
290 elif kind == 'include':
291 try:
291 try:
292 includepats = readpatternfile(pat, self._warn)
292 includepats = readpatternfile(pat, self._warn)
293 for k, p, source in self._normalize(includepats, default,
293 for k, p, source in self._normalize(includepats, default,
294 root, cwd, auditor):
294 root, cwd, auditor):
295 kindpats.append((k, p, source or pat))
295 kindpats.append((k, p, source or pat))
296 except util.Abort as inst:
296 except util.Abort as inst:
297 raise util.Abort('%s: %s' % (pat, inst[0]))
297 raise util.Abort('%s: %s' % (pat, inst[0]))
298 except IOError as inst:
298 except IOError as inst:
299 if self._warn:
299 if self._warn:
300 self._warn(_("skipping unreadable pattern file "
300 self._warn(_("skipping unreadable pattern file "
301 "'%s': %s\n") % (pat, inst.strerror))
301 "'%s': %s\n") % (pat, inst.strerror))
302 continue
302 continue
303 # else: re or relre - which cannot be normalized
303 # else: re or relre - which cannot be normalized
304 kindpats.append((kind, pat, ''))
304 kindpats.append((kind, pat, ''))
305 return kindpats
305 return kindpats
306
306
307 def exact(root, cwd, files, badfn=None):
307 def exact(root, cwd, files, badfn=None):
308 return match(root, cwd, files, exact=True, badfn=badfn)
308 return match(root, cwd, files, exact=True, badfn=badfn)
309
309
310 def always(root, cwd):
310 def always(root, cwd):
311 return match(root, cwd, [])
311 return match(root, cwd, [])
312
312
313 def badmatch(match, badfn):
313 def badmatch(match, badfn):
314 """Make a copy of the given matcher, replacing its bad method with the given
314 """Make a copy of the given matcher, replacing its bad method with the given
315 one.
315 one.
316 """
316 """
317 m = copy.copy(match)
317 m = copy.copy(match)
318 m.bad = badfn
318 m.bad = badfn
319 return m
319 return m
320
320
321 class narrowmatcher(match):
321 class narrowmatcher(match):
322 """Adapt a matcher to work on a subdirectory only.
322 """Adapt a matcher to work on a subdirectory only.
323
323
324 The paths are remapped to remove/insert the path as needed:
324 The paths are remapped to remove/insert the path as needed:
325
325
326 >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
326 >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
327 >>> m2 = narrowmatcher('sub', m1)
327 >>> m2 = narrowmatcher('sub', m1)
328 >>> bool(m2('a.txt'))
328 >>> bool(m2('a.txt'))
329 False
329 False
330 >>> bool(m2('b.txt'))
330 >>> bool(m2('b.txt'))
331 True
331 True
332 >>> bool(m2.matchfn('a.txt'))
332 >>> bool(m2.matchfn('a.txt'))
333 False
333 False
334 >>> bool(m2.matchfn('b.txt'))
334 >>> bool(m2.matchfn('b.txt'))
335 True
335 True
336 >>> m2.files()
336 >>> m2.files()
337 ['b.txt']
337 ['b.txt']
338 >>> m2.exact('b.txt')
338 >>> m2.exact('b.txt')
339 True
339 True
340 >>> util.pconvert(m2.rel('b.txt'))
340 >>> util.pconvert(m2.rel('b.txt'))
341 'sub/b.txt'
341 'sub/b.txt'
342 >>> def bad(f, msg):
342 >>> def bad(f, msg):
343 ... print "%s: %s" % (f, msg)
343 ... print "%s: %s" % (f, msg)
344 >>> m1.bad = bad
344 >>> m1.bad = bad
345 >>> m2.bad('x.txt', 'No such file')
345 >>> m2.bad('x.txt', 'No such file')
346 sub/x.txt: No such file
346 sub/x.txt: No such file
347 >>> m2.abs('c.txt')
347 >>> m2.abs('c.txt')
348 'sub/c.txt'
348 'sub/c.txt'
349 """
349 """
350
350
351 def __init__(self, path, matcher):
351 def __init__(self, path, matcher):
352 self._root = matcher._root
352 self._root = matcher._root
353 self._cwd = matcher._cwd
353 self._cwd = matcher._cwd
354 self._path = path
354 self._path = path
355 self._matcher = matcher
355 self._matcher = matcher
356 self._always = matcher._always
356 self._always = matcher._always
357 self._pathrestricted = matcher._pathrestricted
357 self._pathrestricted = matcher._pathrestricted
358
358
359 self._files = [f[len(path) + 1:] for f in matcher._files
359 self._files = [f[len(path) + 1:] for f in matcher._files
360 if f.startswith(path + "/")]
360 if f.startswith(path + "/")]
361
361
362 # If the parent repo had a path to this subrepo and no patterns are
362 # If the parent repo had a path to this subrepo and no patterns are
363 # specified, this submatcher always matches.
363 # specified, this submatcher always matches.
364 if not self._always and not matcher._anypats:
364 if not self._always and not matcher._anypats:
365 self._always = any(f == path for f in matcher._files)
365 self._always = any(f == path for f in matcher._files)
366
366
367 self._anypats = matcher._anypats
367 self._anypats = matcher._anypats
368 self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
368 self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
369 self._fileroots = set(self._files)
369 self._fileroots = set(self._files)
370
370
371 def abs(self, f):
371 def abs(self, f):
372 return self._matcher.abs(self._path + "/" + f)
372 return self._matcher.abs(self._path + "/" + f)
373
373
374 def bad(self, f, msg):
374 def bad(self, f, msg):
375 self._matcher.bad(self._path + "/" + f, msg)
375 self._matcher.bad(self._path + "/" + f, msg)
376
376
377 def rel(self, f):
377 def rel(self, f):
378 return self._matcher.rel(self._path + "/" + f)
378 return self._matcher.rel(self._path + "/" + f)
379
379
380 class icasefsmatcher(match):
380 class icasefsmatcher(match):
381 """A matcher for wdir on case insensitive filesystems, which normalizes the
381 """A matcher for wdir on case insensitive filesystems, which normalizes the
382 given patterns to the case in the filesystem.
382 given patterns to the case in the filesystem.
383 """
383 """
384
384
385 def __init__(self, root, cwd, patterns, include, exclude, default, auditor,
385 def __init__(self, root, cwd, patterns, include, exclude, default, auditor,
386 ctx, listsubrepos=False, badfn=None):
386 ctx, listsubrepos=False, badfn=None):
387 init = super(icasefsmatcher, self).__init__
387 init = super(icasefsmatcher, self).__init__
388 self._dsnormalize = ctx.repo().dirstate.normalize
388 self._dsnormalize = ctx.repo().dirstate.normalize
389
389
390 init(root, cwd, patterns, include, exclude, default, auditor=auditor,
390 init(root, cwd, patterns, include, exclude, default, auditor=auditor,
391 ctx=ctx, listsubrepos=listsubrepos, badfn=badfn)
391 ctx=ctx, listsubrepos=listsubrepos, badfn=badfn)
392
392
393 # m.exact(file) must be based off of the actual user input, otherwise
393 # m.exact(file) must be based off of the actual user input, otherwise
394 # inexact case matches are treated as exact, and not noted without -v.
394 # inexact case matches are treated as exact, and not noted without -v.
395 if self._files:
395 if self._files:
396 self._fileroots = set(_roots(self._kp))
396 self._fileroots = set(_roots(self._kp))
397
397
398 def _normalize(self, patterns, default, root, cwd, auditor):
398 def _normalize(self, patterns, default, root, cwd, auditor):
399 self._kp = super(icasefsmatcher, self)._normalize(patterns, default,
399 self._kp = super(icasefsmatcher, self)._normalize(patterns, default,
400 root, cwd, auditor)
400 root, cwd, auditor)
401 kindpats = []
401 kindpats = []
402 for kind, pats, source in self._kp:
402 for kind, pats, source in self._kp:
403 if kind not in ('re', 'relre'): # regex can't be normalized
403 if kind not in ('re', 'relre'): # regex can't be normalized
404 pats = self._dsnormalize(pats)
404 pats = self._dsnormalize(pats)
405 kindpats.append((kind, pats, source))
405 kindpats.append((kind, pats, source))
406 return kindpats
406 return kindpats
407
407
408 def patkind(pattern, default=None):
408 def patkind(pattern, default=None):
409 '''If pattern is 'kind:pat' with a known kind, return kind.'''
409 '''If pattern is 'kind:pat' with a known kind, return kind.'''
410 return _patsplit(pattern, default)[0]
410 return _patsplit(pattern, default)[0]
411
411
412 def _patsplit(pattern, default):
412 def _patsplit(pattern, default):
413 """Split a string into the optional pattern kind prefix and the actual
413 """Split a string into the optional pattern kind prefix and the actual
414 pattern."""
414 pattern."""
415 if ':' in pattern:
415 if ':' in pattern:
416 kind, pat = pattern.split(':', 1)
416 kind, pat = pattern.split(':', 1)
417 if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
417 if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
418 'listfile', 'listfile0', 'set', 'include', 'subinclude'):
418 'listfile', 'listfile0', 'set', 'include', 'subinclude'):
419 return kind, pat
419 return kind, pat
420 return default, pattern
420 return default, pattern
421
421
422 def _globre(pat):
422 def _globre(pat):
423 r'''Convert an extended glob string to a regexp string.
423 r'''Convert an extended glob string to a regexp string.
424
424
425 >>> print _globre(r'?')
425 >>> print _globre(r'?')
426 .
426 .
427 >>> print _globre(r'*')
427 >>> print _globre(r'*')
428 [^/]*
428 [^/]*
429 >>> print _globre(r'**')
429 >>> print _globre(r'**')
430 .*
430 .*
431 >>> print _globre(r'**/a')
431 >>> print _globre(r'**/a')
432 (?:.*/)?a
432 (?:.*/)?a
433 >>> print _globre(r'a/**/b')
433 >>> print _globre(r'a/**/b')
434 a\/(?:.*/)?b
434 a\/(?:.*/)?b
435 >>> print _globre(r'[a*?!^][^b][!c]')
435 >>> print _globre(r'[a*?!^][^b][!c]')
436 [a*?!^][\^b][^c]
436 [a*?!^][\^b][^c]
437 >>> print _globre(r'{a,b}')
437 >>> print _globre(r'{a,b}')
438 (?:a|b)
438 (?:a|b)
439 >>> print _globre(r'.\*\?')
439 >>> print _globre(r'.\*\?')
440 \.\*\?
440 \.\*\?
441 '''
441 '''
442 i, n = 0, len(pat)
442 i, n = 0, len(pat)
443 res = ''
443 res = ''
444 group = 0
444 group = 0
445 escape = util.re.escape
445 escape = util.re.escape
446 def peek():
446 def peek():
447 return i < n and pat[i]
447 return i < n and pat[i]
448 while i < n:
448 while i < n:
449 c = pat[i]
449 c = pat[i]
450 i += 1
450 i += 1
451 if c not in '*?[{},\\':
451 if c not in '*?[{},\\':
452 res += escape(c)
452 res += escape(c)
453 elif c == '*':
453 elif c == '*':
454 if peek() == '*':
454 if peek() == '*':
455 i += 1
455 i += 1
456 if peek() == '/':
456 if peek() == '/':
457 i += 1
457 i += 1
458 res += '(?:.*/)?'
458 res += '(?:.*/)?'
459 else:
459 else:
460 res += '.*'
460 res += '.*'
461 else:
461 else:
462 res += '[^/]*'
462 res += '[^/]*'
463 elif c == '?':
463 elif c == '?':
464 res += '.'
464 res += '.'
465 elif c == '[':
465 elif c == '[':
466 j = i
466 j = i
467 if j < n and pat[j] in '!]':
467 if j < n and pat[j] in '!]':
468 j += 1
468 j += 1
469 while j < n and pat[j] != ']':
469 while j < n and pat[j] != ']':
470 j += 1
470 j += 1
471 if j >= n:
471 if j >= n:
472 res += '\\['
472 res += '\\['
473 else:
473 else:
474 stuff = pat[i:j].replace('\\','\\\\')
474 stuff = pat[i:j].replace('\\','\\\\')
475 i = j + 1
475 i = j + 1
476 if stuff[0] == '!':
476 if stuff[0] == '!':
477 stuff = '^' + stuff[1:]
477 stuff = '^' + stuff[1:]
478 elif stuff[0] == '^':
478 elif stuff[0] == '^':
479 stuff = '\\' + stuff
479 stuff = '\\' + stuff
480 res = '%s[%s]' % (res, stuff)
480 res = '%s[%s]' % (res, stuff)
481 elif c == '{':
481 elif c == '{':
482 group += 1
482 group += 1
483 res += '(?:'
483 res += '(?:'
484 elif c == '}' and group:
484 elif c == '}' and group:
485 res += ')'
485 res += ')'
486 group -= 1
486 group -= 1
487 elif c == ',' and group:
487 elif c == ',' and group:
488 res += '|'
488 res += '|'
489 elif c == '\\':
489 elif c == '\\':
490 p = peek()
490 p = peek()
491 if p:
491 if p:
492 i += 1
492 i += 1
493 res += escape(p)
493 res += escape(p)
494 else:
494 else:
495 res += escape(c)
495 res += escape(c)
496 else:
496 else:
497 res += escape(c)
497 res += escape(c)
498 return res
498 return res
499
499
500 def _regex(kind, pat, globsuffix):
500 def _regex(kind, pat, globsuffix):
501 '''Convert a (normalized) pattern of any kind into a regular expression.
501 '''Convert a (normalized) pattern of any kind into a regular expression.
502 globsuffix is appended to the regexp of globs.'''
502 globsuffix is appended to the regexp of globs.'''
503 if not pat:
503 if not pat:
504 return ''
504 return ''
505 if kind == 're':
505 if kind == 're':
506 return pat
506 return pat
507 if kind == 'path':
507 if kind == 'path':
508 if pat == '.':
509 return ''
508 return '^' + util.re.escape(pat) + '(?:/|$)'
510 return '^' + util.re.escape(pat) + '(?:/|$)'
509 if kind == 'relglob':
511 if kind == 'relglob':
510 return '(?:|.*/)' + _globre(pat) + globsuffix
512 return '(?:|.*/)' + _globre(pat) + globsuffix
511 if kind == 'relpath':
513 if kind == 'relpath':
512 return util.re.escape(pat) + '(?:/|$)'
514 return util.re.escape(pat) + '(?:/|$)'
513 if kind == 'relre':
515 if kind == 'relre':
514 if pat.startswith('^'):
516 if pat.startswith('^'):
515 return pat
517 return pat
516 return '.*' + pat
518 return '.*' + pat
517 return _globre(pat) + globsuffix
519 return _globre(pat) + globsuffix
518
520
519 def _buildmatch(ctx, kindpats, globsuffix, listsubrepos, root):
521 def _buildmatch(ctx, kindpats, globsuffix, listsubrepos, root):
520 '''Return regexp string and a matcher function for kindpats.
522 '''Return regexp string and a matcher function for kindpats.
521 globsuffix is appended to the regexp of globs.'''
523 globsuffix is appended to the regexp of globs.'''
522 matchfuncs = []
524 matchfuncs = []
523
525
524 subincludes, kindpats = _expandsubinclude(kindpats, root)
526 subincludes, kindpats = _expandsubinclude(kindpats, root)
525 if subincludes:
527 if subincludes:
526 def matchsubinclude(f):
528 def matchsubinclude(f):
527 for prefix, mf in subincludes:
529 for prefix, mf in subincludes:
528 if f.startswith(prefix) and mf(f[len(prefix):]):
530 if f.startswith(prefix) and mf(f[len(prefix):]):
529 return True
531 return True
530 return False
532 return False
531 matchfuncs.append(matchsubinclude)
533 matchfuncs.append(matchsubinclude)
532
534
533 fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
535 fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
534 if fset:
536 if fset:
535 matchfuncs.append(fset.__contains__)
537 matchfuncs.append(fset.__contains__)
536
538
537 regex = ''
539 regex = ''
538 if kindpats:
540 if kindpats:
539 regex, mf = _buildregexmatch(kindpats, globsuffix)
541 regex, mf = _buildregexmatch(kindpats, globsuffix)
540 matchfuncs.append(mf)
542 matchfuncs.append(mf)
541
543
542 if len(matchfuncs) == 1:
544 if len(matchfuncs) == 1:
543 return regex, matchfuncs[0]
545 return regex, matchfuncs[0]
544 else:
546 else:
545 return regex, lambda f: any(mf(f) for mf in matchfuncs)
547 return regex, lambda f: any(mf(f) for mf in matchfuncs)
546
548
547 def _buildregexmatch(kindpats, globsuffix):
549 def _buildregexmatch(kindpats, globsuffix):
548 """Build a match function from a list of kinds and kindpats,
550 """Build a match function from a list of kinds and kindpats,
549 return regexp string and a matcher function."""
551 return regexp string and a matcher function."""
550 try:
552 try:
551 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
553 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
552 for (k, p, s) in kindpats])
554 for (k, p, s) in kindpats])
553 if len(regex) > 20000:
555 if len(regex) > 20000:
554 raise OverflowError
556 raise OverflowError
555 return regex, _rematcher(regex)
557 return regex, _rematcher(regex)
556 except OverflowError:
558 except OverflowError:
557 # We're using a Python with a tiny regex engine and we
559 # We're using a Python with a tiny regex engine and we
558 # made it explode, so we'll divide the pattern list in two
560 # made it explode, so we'll divide the pattern list in two
559 # until it works
561 # until it works
560 l = len(kindpats)
562 l = len(kindpats)
561 if l < 2:
563 if l < 2:
562 raise
564 raise
563 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
565 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
564 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
566 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
565 return regex, lambda s: a(s) or b(s)
567 return regex, lambda s: a(s) or b(s)
566 except re.error:
568 except re.error:
567 for k, p, s in kindpats:
569 for k, p, s in kindpats:
568 try:
570 try:
569 _rematcher('(?:%s)' % _regex(k, p, globsuffix))
571 _rematcher('(?:%s)' % _regex(k, p, globsuffix))
570 except re.error:
572 except re.error:
571 if s:
573 if s:
572 raise util.Abort(_("%s: invalid pattern (%s): %s") %
574 raise util.Abort(_("%s: invalid pattern (%s): %s") %
573 (s, k, p))
575 (s, k, p))
574 else:
576 else:
575 raise util.Abort(_("invalid pattern (%s): %s") % (k, p))
577 raise util.Abort(_("invalid pattern (%s): %s") % (k, p))
576 raise util.Abort(_("invalid pattern"))
578 raise util.Abort(_("invalid pattern"))
577
579
578 def _roots(kindpats):
580 def _roots(kindpats):
579 '''return roots and exact explicitly listed files from patterns
581 '''return roots and exact explicitly listed files from patterns
580
582
581 >>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')])
583 >>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')])
582 ['g', 'g', '.']
584 ['g', 'g', '.']
583 >>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
585 >>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
584 ['r', 'p/p', '.']
586 ['r', 'p/p', '.']
585 >>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
587 >>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
586 ['.', '.', '.']
588 ['.', '.', '.']
587 '''
589 '''
588 r = []
590 r = []
589 for kind, pat, source in kindpats:
591 for kind, pat, source in kindpats:
590 if kind == 'glob': # find the non-glob prefix
592 if kind == 'glob': # find the non-glob prefix
591 root = []
593 root = []
592 for p in pat.split('/'):
594 for p in pat.split('/'):
593 if '[' in p or '{' in p or '*' in p or '?' in p:
595 if '[' in p or '{' in p or '*' in p or '?' in p:
594 break
596 break
595 root.append(p)
597 root.append(p)
596 r.append('/'.join(root) or '.')
598 r.append('/'.join(root) or '.')
597 elif kind in ('relpath', 'path'):
599 elif kind in ('relpath', 'path'):
598 r.append(pat or '.')
600 r.append(pat or '.')
599 else: # relglob, re, relre
601 else: # relglob, re, relre
600 r.append('.')
602 r.append('.')
601 return r
603 return r
602
604
603 def _anypats(kindpats):
605 def _anypats(kindpats):
604 for kind, pat, source in kindpats:
606 for kind, pat, source in kindpats:
605 if kind in ('glob', 're', 'relglob', 'relre', 'set'):
607 if kind in ('glob', 're', 'relglob', 'relre', 'set'):
606 return True
608 return True
607
609
608 _commentre = None
610 _commentre = None
609
611
610 def readpatternfile(filepath, warn):
612 def readpatternfile(filepath, warn):
611 '''parse a pattern file, returning a list of
613 '''parse a pattern file, returning a list of
612 patterns. These patterns should be given to compile()
614 patterns. These patterns should be given to compile()
613 to be validated and converted into a match function.
615 to be validated and converted into a match function.
614
616
615 trailing white space is dropped.
617 trailing white space is dropped.
616 the escape character is backslash.
618 the escape character is backslash.
617 comments start with #.
619 comments start with #.
618 empty lines are skipped.
620 empty lines are skipped.
619
621
620 lines can be of the following formats:
622 lines can be of the following formats:
621
623
622 syntax: regexp # defaults following lines to non-rooted regexps
624 syntax: regexp # defaults following lines to non-rooted regexps
623 syntax: glob # defaults following lines to non-rooted globs
625 syntax: glob # defaults following lines to non-rooted globs
624 re:pattern # non-rooted regular expression
626 re:pattern # non-rooted regular expression
625 glob:pattern # non-rooted glob
627 glob:pattern # non-rooted glob
626 pattern # pattern of the current default type'''
628 pattern # pattern of the current default type'''
627
629
628 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
630 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
629 'include': 'include', 'subinclude': 'subinclude'}
631 'include': 'include', 'subinclude': 'subinclude'}
630 syntax = 'relre:'
632 syntax = 'relre:'
631 patterns = []
633 patterns = []
632
634
633 fp = open(filepath)
635 fp = open(filepath)
634 for line in fp:
636 for line in fp:
635 if "#" in line:
637 if "#" in line:
636 global _commentre
638 global _commentre
637 if not _commentre:
639 if not _commentre:
638 _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
640 _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
639 # remove comments prefixed by an even number of escapes
641 # remove comments prefixed by an even number of escapes
640 line = _commentre.sub(r'\1', line)
642 line = _commentre.sub(r'\1', line)
641 # fixup properly escaped comments that survived the above
643 # fixup properly escaped comments that survived the above
642 line = line.replace("\\#", "#")
644 line = line.replace("\\#", "#")
643 line = line.rstrip()
645 line = line.rstrip()
644 if not line:
646 if not line:
645 continue
647 continue
646
648
647 if line.startswith('syntax:'):
649 if line.startswith('syntax:'):
648 s = line[7:].strip()
650 s = line[7:].strip()
649 try:
651 try:
650 syntax = syntaxes[s]
652 syntax = syntaxes[s]
651 except KeyError:
653 except KeyError:
652 if warn:
654 if warn:
653 warn(_("%s: ignoring invalid syntax '%s'\n") %
655 warn(_("%s: ignoring invalid syntax '%s'\n") %
654 (filepath, s))
656 (filepath, s))
655 continue
657 continue
656
658
657 linesyntax = syntax
659 linesyntax = syntax
658 for s, rels in syntaxes.iteritems():
660 for s, rels in syntaxes.iteritems():
659 if line.startswith(rels):
661 if line.startswith(rels):
660 linesyntax = rels
662 linesyntax = rels
661 line = line[len(rels):]
663 line = line[len(rels):]
662 break
664 break
663 elif line.startswith(s+':'):
665 elif line.startswith(s+':'):
664 linesyntax = rels
666 linesyntax = rels
665 line = line[len(s) + 1:]
667 line = line[len(s) + 1:]
666 break
668 break
667 patterns.append(linesyntax + line)
669 patterns.append(linesyntax + line)
668 fp.close()
670 fp.close()
669 return patterns
671 return patterns
@@ -1,862 +1,862
1 # templater.py - template expansion for output
1 # templater.py - template expansion for output
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import os, re
9 import os, re
10 import util, config, templatefilters, templatekw, parser, error
10 import util, config, templatefilters, templatekw, parser, error
11 import revset as revsetmod
11 import revset as revsetmod
12 import types
12 import types
13 import minirst
13 import minirst
14
14
15 # template parsing
15 # template parsing
16
16
17 elements = {
17 elements = {
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
19 ",": (2, None, ("list", 2)),
19 ",": (2, None, ("list", 2)),
20 "|": (5, None, ("|", 5)),
20 "|": (5, None, ("|", 5)),
21 "%": (6, None, ("%", 6)),
21 "%": (6, None, ("%", 6)),
22 ")": (0, None, None),
22 ")": (0, None, None),
23 "integer": (0, ("integer",), None),
23 "integer": (0, ("integer",), None),
24 "symbol": (0, ("symbol",), None),
24 "symbol": (0, ("symbol",), None),
25 "string": (0, ("template",), None),
25 "string": (0, ("template",), None),
26 "rawstring": (0, ("rawstring",), None),
26 "rawstring": (0, ("rawstring",), None),
27 "end": (0, None, None),
27 "end": (0, None, None),
28 }
28 }
29
29
30 def tokenize(program, start, end):
30 def tokenize(program, start, end):
31 pos = start
31 pos = start
32 while pos < end:
32 while pos < end:
33 c = program[pos]
33 c = program[pos]
34 if c.isspace(): # skip inter-token whitespace
34 if c.isspace(): # skip inter-token whitespace
35 pass
35 pass
36 elif c in "(,)%|": # handle simple operators
36 elif c in "(,)%|": # handle simple operators
37 yield (c, None, pos)
37 yield (c, None, pos)
38 elif (c in '"\'' or c == 'r' and
38 elif (c in '"\'' or c == 'r' and
39 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
39 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
40 if c == 'r':
40 if c == 'r':
41 pos += 1
41 pos += 1
42 c = program[pos]
42 c = program[pos]
43 decode = False
43 decode = False
44 else:
44 else:
45 decode = True
45 decode = True
46 pos += 1
46 pos += 1
47 s = pos
47 s = pos
48 while pos < end: # find closing quote
48 while pos < end: # find closing quote
49 d = program[pos]
49 d = program[pos]
50 if decode and d == '\\': # skip over escaped characters
50 if d == '\\': # skip over escaped characters
51 pos += 2
51 pos += 2
52 continue
52 continue
53 if d == c:
53 if d == c:
54 if not decode:
54 if not decode:
55 yield ('rawstring', program[s:pos], s)
55 yield ('rawstring', program[s:pos], s)
56 break
56 break
57 yield ('string', program[s:pos], s)
57 yield ('string', program[s:pos], s)
58 break
58 break
59 pos += 1
59 pos += 1
60 else:
60 else:
61 raise error.ParseError(_("unterminated string"), s)
61 raise error.ParseError(_("unterminated string"), s)
62 elif c.isdigit() or c == '-':
62 elif c.isdigit() or c == '-':
63 s = pos
63 s = pos
64 if c == '-': # simply take negate operator as part of integer
64 if c == '-': # simply take negate operator as part of integer
65 pos += 1
65 pos += 1
66 if pos >= end or not program[pos].isdigit():
66 if pos >= end or not program[pos].isdigit():
67 raise error.ParseError(_("integer literal without digits"), s)
67 raise error.ParseError(_("integer literal without digits"), s)
68 pos += 1
68 pos += 1
69 while pos < end:
69 while pos < end:
70 d = program[pos]
70 d = program[pos]
71 if not d.isdigit():
71 if not d.isdigit():
72 break
72 break
73 pos += 1
73 pos += 1
74 yield ('integer', program[s:pos], s)
74 yield ('integer', program[s:pos], s)
75 pos -= 1
75 pos -= 1
76 elif c.isalnum() or c in '_':
76 elif c.isalnum() or c in '_':
77 s = pos
77 s = pos
78 pos += 1
78 pos += 1
79 while pos < end: # find end of symbol
79 while pos < end: # find end of symbol
80 d = program[pos]
80 d = program[pos]
81 if not (d.isalnum() or d == "_"):
81 if not (d.isalnum() or d == "_"):
82 break
82 break
83 pos += 1
83 pos += 1
84 sym = program[s:pos]
84 sym = program[s:pos]
85 yield ('symbol', sym, s)
85 yield ('symbol', sym, s)
86 pos -= 1
86 pos -= 1
87 elif c == '}':
87 elif c == '}':
88 pos += 1
88 pos += 1
89 break
89 break
90 else:
90 else:
91 raise error.ParseError(_("syntax error"), pos)
91 raise error.ParseError(_("syntax error"), pos)
92 pos += 1
92 pos += 1
93 yield ('end', None, pos)
93 yield ('end', None, pos)
94
94
95 def compiletemplate(tmpl, context):
95 def compiletemplate(tmpl, context):
96 parsed = []
96 parsed = []
97 pos, stop = 0, len(tmpl)
97 pos, stop = 0, len(tmpl)
98 p = parser.parser(elements)
98 p = parser.parser(elements)
99 while pos < stop:
99 while pos < stop:
100 n = tmpl.find('{', pos)
100 n = tmpl.find('{', pos)
101 if n < 0:
101 if n < 0:
102 parsed.append(('string', tmpl[pos:]))
102 parsed.append(('string', tmpl[pos:]))
103 break
103 break
104 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
104 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
105 if bs % 2 == 1:
105 if bs % 2 == 1:
106 # escaped (e.g. '\{', '\\\{', but not '\\{')
106 # escaped (e.g. '\{', '\\\{', but not '\\{')
107 parsed.append(('string', (tmpl[pos:n - 1] + "{")))
107 parsed.append(('string', (tmpl[pos:n - 1] + "{")))
108 pos = n + 1
108 pos = n + 1
109 continue
109 continue
110 if n > pos:
110 if n > pos:
111 parsed.append(('string', tmpl[pos:n]))
111 parsed.append(('string', tmpl[pos:n]))
112
112
113 parseres, pos = p.parse(tokenize(tmpl, n + 1, stop))
113 parseres, pos = p.parse(tokenize(tmpl, n + 1, stop))
114 parsed.append(parseres)
114 parsed.append(parseres)
115
115
116 return [compileexp(e, context, methods) for e in parsed]
116 return [compileexp(e, context, methods) for e in parsed]
117
117
118 def compileexp(exp, context, curmethods):
118 def compileexp(exp, context, curmethods):
119 t = exp[0]
119 t = exp[0]
120 if t in curmethods:
120 if t in curmethods:
121 return curmethods[t](exp, context)
121 return curmethods[t](exp, context)
122 raise error.ParseError(_("unknown method '%s'") % t)
122 raise error.ParseError(_("unknown method '%s'") % t)
123
123
124 # template evaluation
124 # template evaluation
125
125
126 def getsymbol(exp):
126 def getsymbol(exp):
127 if exp[0] == 'symbol':
127 if exp[0] == 'symbol':
128 return exp[1]
128 return exp[1]
129 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
129 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
130
130
131 def getlist(x):
131 def getlist(x):
132 if not x:
132 if not x:
133 return []
133 return []
134 if x[0] == 'list':
134 if x[0] == 'list':
135 return getlist(x[1]) + [x[2]]
135 return getlist(x[1]) + [x[2]]
136 return [x]
136 return [x]
137
137
138 def getfilter(exp, context):
138 def getfilter(exp, context):
139 f = getsymbol(exp)
139 f = getsymbol(exp)
140 if f not in context._filters:
140 if f not in context._filters:
141 raise error.ParseError(_("unknown function '%s'") % f)
141 raise error.ParseError(_("unknown function '%s'") % f)
142 return context._filters[f]
142 return context._filters[f]
143
143
144 def gettemplate(exp, context):
144 def gettemplate(exp, context):
145 if exp[0] == 'template':
145 if exp[0] == 'template':
146 return compiletemplate(exp[1], context)
146 return compiletemplate(exp[1], context)
147 if exp[0] == 'symbol':
147 if exp[0] == 'symbol':
148 # unlike runsymbol(), here 'symbol' is always taken as template name
148 # unlike runsymbol(), here 'symbol' is always taken as template name
149 # even if it exists in mapping. this allows us to override mapping
149 # even if it exists in mapping. this allows us to override mapping
150 # by web templates, e.g. 'changelogtag' is redefined in map file.
150 # by web templates, e.g. 'changelogtag' is redefined in map file.
151 return context._load(exp[1])
151 return context._load(exp[1])
152 raise error.ParseError(_("expected template specifier"))
152 raise error.ParseError(_("expected template specifier"))
153
153
154 def runinteger(context, mapping, data):
154 def runinteger(context, mapping, data):
155 return int(data)
155 return int(data)
156
156
157 def runstring(context, mapping, data):
157 def runstring(context, mapping, data):
158 return data.decode("string-escape")
158 return data.decode("string-escape")
159
159
160 def runrawstring(context, mapping, data):
160 def runrawstring(context, mapping, data):
161 return data
161 return data
162
162
163 def runsymbol(context, mapping, key):
163 def runsymbol(context, mapping, key):
164 v = mapping.get(key)
164 v = mapping.get(key)
165 if v is None:
165 if v is None:
166 v = context._defaults.get(key)
166 v = context._defaults.get(key)
167 if v is None:
167 if v is None:
168 try:
168 try:
169 v = context.process(key, mapping)
169 v = context.process(key, mapping)
170 except TemplateNotFound:
170 except TemplateNotFound:
171 v = ''
171 v = ''
172 if callable(v):
172 if callable(v):
173 return v(**mapping)
173 return v(**mapping)
174 if isinstance(v, types.GeneratorType):
174 if isinstance(v, types.GeneratorType):
175 v = list(v)
175 v = list(v)
176 return v
176 return v
177
177
178 def buildtemplate(exp, context):
178 def buildtemplate(exp, context):
179 ctmpl = compiletemplate(exp[1], context)
179 ctmpl = compiletemplate(exp[1], context)
180 if len(ctmpl) == 1:
180 if len(ctmpl) == 1:
181 return ctmpl[0] # fast path for string with no template fragment
181 return ctmpl[0] # fast path for string with no template fragment
182 return (runtemplate, ctmpl)
182 return (runtemplate, ctmpl)
183
183
184 def runtemplate(context, mapping, template):
184 def runtemplate(context, mapping, template):
185 for func, data in template:
185 for func, data in template:
186 yield func(context, mapping, data)
186 yield func(context, mapping, data)
187
187
188 def buildfilter(exp, context):
188 def buildfilter(exp, context):
189 func, data = compileexp(exp[1], context, methods)
189 func, data = compileexp(exp[1], context, methods)
190 filt = getfilter(exp[2], context)
190 filt = getfilter(exp[2], context)
191 return (runfilter, (func, data, filt))
191 return (runfilter, (func, data, filt))
192
192
193 def runfilter(context, mapping, data):
193 def runfilter(context, mapping, data):
194 func, data, filt = data
194 func, data, filt = data
195 # func() may return string, generator of strings or arbitrary object such
195 # func() may return string, generator of strings or arbitrary object such
196 # as date tuple, but filter does not want generator.
196 # as date tuple, but filter does not want generator.
197 thing = func(context, mapping, data)
197 thing = func(context, mapping, data)
198 if isinstance(thing, types.GeneratorType):
198 if isinstance(thing, types.GeneratorType):
199 thing = stringify(thing)
199 thing = stringify(thing)
200 try:
200 try:
201 return filt(thing)
201 return filt(thing)
202 except (ValueError, AttributeError, TypeError):
202 except (ValueError, AttributeError, TypeError):
203 if isinstance(data, tuple):
203 if isinstance(data, tuple):
204 dt = data[1]
204 dt = data[1]
205 else:
205 else:
206 dt = data
206 dt = data
207 raise util.Abort(_("template filter '%s' is not compatible with "
207 raise util.Abort(_("template filter '%s' is not compatible with "
208 "keyword '%s'") % (filt.func_name, dt))
208 "keyword '%s'") % (filt.func_name, dt))
209
209
210 def buildmap(exp, context):
210 def buildmap(exp, context):
211 func, data = compileexp(exp[1], context, methods)
211 func, data = compileexp(exp[1], context, methods)
212 ctmpl = gettemplate(exp[2], context)
212 ctmpl = gettemplate(exp[2], context)
213 return (runmap, (func, data, ctmpl))
213 return (runmap, (func, data, ctmpl))
214
214
215 def runmap(context, mapping, data):
215 def runmap(context, mapping, data):
216 func, data, ctmpl = data
216 func, data, ctmpl = data
217 d = func(context, mapping, data)
217 d = func(context, mapping, data)
218 if callable(d):
218 if callable(d):
219 d = d()
219 d = d()
220
220
221 lm = mapping.copy()
221 lm = mapping.copy()
222
222
223 for i in d:
223 for i in d:
224 if isinstance(i, dict):
224 if isinstance(i, dict):
225 lm.update(i)
225 lm.update(i)
226 lm['originalnode'] = mapping.get('node')
226 lm['originalnode'] = mapping.get('node')
227 yield runtemplate(context, lm, ctmpl)
227 yield runtemplate(context, lm, ctmpl)
228 else:
228 else:
229 # v is not an iterable of dicts, this happen when 'key'
229 # v is not an iterable of dicts, this happen when 'key'
230 # has been fully expanded already and format is useless.
230 # has been fully expanded already and format is useless.
231 # If so, return the expanded value.
231 # If so, return the expanded value.
232 yield i
232 yield i
233
233
234 def buildfunc(exp, context):
234 def buildfunc(exp, context):
235 n = getsymbol(exp[1])
235 n = getsymbol(exp[1])
236 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
236 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
237 if n in funcs:
237 if n in funcs:
238 f = funcs[n]
238 f = funcs[n]
239 return (f, args)
239 return (f, args)
240 if n in context._filters:
240 if n in context._filters:
241 if len(args) != 1:
241 if len(args) != 1:
242 raise error.ParseError(_("filter %s expects one argument") % n)
242 raise error.ParseError(_("filter %s expects one argument") % n)
243 f = context._filters[n]
243 f = context._filters[n]
244 return (runfilter, (args[0][0], args[0][1], f))
244 return (runfilter, (args[0][0], args[0][1], f))
245 raise error.ParseError(_("unknown function '%s'") % n)
245 raise error.ParseError(_("unknown function '%s'") % n)
246
246
247 def date(context, mapping, args):
247 def date(context, mapping, args):
248 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
248 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
249 strings."""
249 strings."""
250 if not (1 <= len(args) <= 2):
250 if not (1 <= len(args) <= 2):
251 # i18n: "date" is a keyword
251 # i18n: "date" is a keyword
252 raise error.ParseError(_("date expects one or two arguments"))
252 raise error.ParseError(_("date expects one or two arguments"))
253
253
254 date = args[0][0](context, mapping, args[0][1])
254 date = args[0][0](context, mapping, args[0][1])
255 fmt = None
255 fmt = None
256 if len(args) == 2:
256 if len(args) == 2:
257 fmt = stringify(args[1][0](context, mapping, args[1][1]))
257 fmt = stringify(args[1][0](context, mapping, args[1][1]))
258 try:
258 try:
259 if fmt is None:
259 if fmt is None:
260 return util.datestr(date)
260 return util.datestr(date)
261 else:
261 else:
262 return util.datestr(date, fmt)
262 return util.datestr(date, fmt)
263 except (TypeError, ValueError):
263 except (TypeError, ValueError):
264 # i18n: "date" is a keyword
264 # i18n: "date" is a keyword
265 raise error.ParseError(_("date expects a date information"))
265 raise error.ParseError(_("date expects a date information"))
266
266
267 def diff(context, mapping, args):
267 def diff(context, mapping, args):
268 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
268 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
269 specifying files to include or exclude."""
269 specifying files to include or exclude."""
270 if len(args) > 2:
270 if len(args) > 2:
271 # i18n: "diff" is a keyword
271 # i18n: "diff" is a keyword
272 raise error.ParseError(_("diff expects one, two or no arguments"))
272 raise error.ParseError(_("diff expects one, two or no arguments"))
273
273
274 def getpatterns(i):
274 def getpatterns(i):
275 if i < len(args):
275 if i < len(args):
276 s = stringify(args[i][0](context, mapping, args[i][1])).strip()
276 s = stringify(args[i][0](context, mapping, args[i][1])).strip()
277 if s:
277 if s:
278 return [s]
278 return [s]
279 return []
279 return []
280
280
281 ctx = mapping['ctx']
281 ctx = mapping['ctx']
282 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
282 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
283
283
284 return ''.join(chunks)
284 return ''.join(chunks)
285
285
286 def fill(context, mapping, args):
286 def fill(context, mapping, args):
287 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
287 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
288 paragraphs with optional indentation. See the "fill" filter."""
288 paragraphs with optional indentation. See the "fill" filter."""
289 if not (1 <= len(args) <= 4):
289 if not (1 <= len(args) <= 4):
290 # i18n: "fill" is a keyword
290 # i18n: "fill" is a keyword
291 raise error.ParseError(_("fill expects one to four arguments"))
291 raise error.ParseError(_("fill expects one to four arguments"))
292
292
293 text = stringify(args[0][0](context, mapping, args[0][1]))
293 text = stringify(args[0][0](context, mapping, args[0][1]))
294 width = 76
294 width = 76
295 initindent = ''
295 initindent = ''
296 hangindent = ''
296 hangindent = ''
297 if 2 <= len(args) <= 4:
297 if 2 <= len(args) <= 4:
298 try:
298 try:
299 width = int(stringify(args[1][0](context, mapping, args[1][1])))
299 width = int(stringify(args[1][0](context, mapping, args[1][1])))
300 except ValueError:
300 except ValueError:
301 # i18n: "fill" is a keyword
301 # i18n: "fill" is a keyword
302 raise error.ParseError(_("fill expects an integer width"))
302 raise error.ParseError(_("fill expects an integer width"))
303 try:
303 try:
304 initindent = stringify(args[2][0](context, mapping, args[2][1]))
304 initindent = stringify(args[2][0](context, mapping, args[2][1]))
305 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
305 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
306 except IndexError:
306 except IndexError:
307 pass
307 pass
308
308
309 return templatefilters.fill(text, width, initindent, hangindent)
309 return templatefilters.fill(text, width, initindent, hangindent)
310
310
311 def pad(context, mapping, args):
311 def pad(context, mapping, args):
312 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
312 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
313 fill character."""
313 fill character."""
314 if not (2 <= len(args) <= 4):
314 if not (2 <= len(args) <= 4):
315 # i18n: "pad" is a keyword
315 # i18n: "pad" is a keyword
316 raise error.ParseError(_("pad() expects two to four arguments"))
316 raise error.ParseError(_("pad() expects two to four arguments"))
317
317
318 width = int(args[1][1])
318 width = int(args[1][1])
319
319
320 text = stringify(args[0][0](context, mapping, args[0][1]))
320 text = stringify(args[0][0](context, mapping, args[0][1]))
321
321
322 right = False
322 right = False
323 fillchar = ' '
323 fillchar = ' '
324 if len(args) > 2:
324 if len(args) > 2:
325 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
325 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
326 if len(args) > 3:
326 if len(args) > 3:
327 right = util.parsebool(args[3][1])
327 right = util.parsebool(args[3][1])
328
328
329 if right:
329 if right:
330 return text.rjust(width, fillchar)
330 return text.rjust(width, fillchar)
331 else:
331 else:
332 return text.ljust(width, fillchar)
332 return text.ljust(width, fillchar)
333
333
334 def indent(context, mapping, args):
334 def indent(context, mapping, args):
335 """:indent(text, indentchars[, firstline]): Indents all non-empty lines
335 """:indent(text, indentchars[, firstline]): Indents all non-empty lines
336 with the characters given in the indentchars string. An optional
336 with the characters given in the indentchars string. An optional
337 third parameter will override the indent for the first line only
337 third parameter will override the indent for the first line only
338 if present."""
338 if present."""
339 if not (2 <= len(args) <= 3):
339 if not (2 <= len(args) <= 3):
340 # i18n: "indent" is a keyword
340 # i18n: "indent" is a keyword
341 raise error.ParseError(_("indent() expects two or three arguments"))
341 raise error.ParseError(_("indent() expects two or three arguments"))
342
342
343 text = stringify(args[0][0](context, mapping, args[0][1]))
343 text = stringify(args[0][0](context, mapping, args[0][1]))
344 indent = stringify(args[1][0](context, mapping, args[1][1]))
344 indent = stringify(args[1][0](context, mapping, args[1][1]))
345
345
346 if len(args) == 3:
346 if len(args) == 3:
347 firstline = stringify(args[2][0](context, mapping, args[2][1]))
347 firstline = stringify(args[2][0](context, mapping, args[2][1]))
348 else:
348 else:
349 firstline = indent
349 firstline = indent
350
350
351 # the indent function doesn't indent the first line, so we do it here
351 # the indent function doesn't indent the first line, so we do it here
352 return templatefilters.indent(firstline + text, indent)
352 return templatefilters.indent(firstline + text, indent)
353
353
354 def get(context, mapping, args):
354 def get(context, mapping, args):
355 """:get(dict, key): Get an attribute/key from an object. Some keywords
355 """:get(dict, key): Get an attribute/key from an object. Some keywords
356 are complex types. This function allows you to obtain the value of an
356 are complex types. This function allows you to obtain the value of an
357 attribute on these type."""
357 attribute on these type."""
358 if len(args) != 2:
358 if len(args) != 2:
359 # i18n: "get" is a keyword
359 # i18n: "get" is a keyword
360 raise error.ParseError(_("get() expects two arguments"))
360 raise error.ParseError(_("get() expects two arguments"))
361
361
362 dictarg = args[0][0](context, mapping, args[0][1])
362 dictarg = args[0][0](context, mapping, args[0][1])
363 if not util.safehasattr(dictarg, 'get'):
363 if not util.safehasattr(dictarg, 'get'):
364 # i18n: "get" is a keyword
364 # i18n: "get" is a keyword
365 raise error.ParseError(_("get() expects a dict as first argument"))
365 raise error.ParseError(_("get() expects a dict as first argument"))
366
366
367 key = args[1][0](context, mapping, args[1][1])
367 key = args[1][0](context, mapping, args[1][1])
368 yield dictarg.get(key)
368 yield dictarg.get(key)
369
369
370 def if_(context, mapping, args):
370 def if_(context, mapping, args):
371 """:if(expr, then[, else]): Conditionally execute based on the result of
371 """:if(expr, then[, else]): Conditionally execute based on the result of
372 an expression."""
372 an expression."""
373 if not (2 <= len(args) <= 3):
373 if not (2 <= len(args) <= 3):
374 # i18n: "if" is a keyword
374 # i18n: "if" is a keyword
375 raise error.ParseError(_("if expects two or three arguments"))
375 raise error.ParseError(_("if expects two or three arguments"))
376
376
377 test = stringify(args[0][0](context, mapping, args[0][1]))
377 test = stringify(args[0][0](context, mapping, args[0][1]))
378 if test:
378 if test:
379 yield args[1][0](context, mapping, args[1][1])
379 yield args[1][0](context, mapping, args[1][1])
380 elif len(args) == 3:
380 elif len(args) == 3:
381 yield args[2][0](context, mapping, args[2][1])
381 yield args[2][0](context, mapping, args[2][1])
382
382
383 def ifcontains(context, mapping, args):
383 def ifcontains(context, mapping, args):
384 """:ifcontains(search, thing, then[, else]): Conditionally execute based
384 """:ifcontains(search, thing, then[, else]): Conditionally execute based
385 on whether the item "search" is in "thing"."""
385 on whether the item "search" is in "thing"."""
386 if not (3 <= len(args) <= 4):
386 if not (3 <= len(args) <= 4):
387 # i18n: "ifcontains" is a keyword
387 # i18n: "ifcontains" is a keyword
388 raise error.ParseError(_("ifcontains expects three or four arguments"))
388 raise error.ParseError(_("ifcontains expects three or four arguments"))
389
389
390 item = stringify(args[0][0](context, mapping, args[0][1]))
390 item = stringify(args[0][0](context, mapping, args[0][1]))
391 items = args[1][0](context, mapping, args[1][1])
391 items = args[1][0](context, mapping, args[1][1])
392
392
393 if item in items:
393 if item in items:
394 yield args[2][0](context, mapping, args[2][1])
394 yield args[2][0](context, mapping, args[2][1])
395 elif len(args) == 4:
395 elif len(args) == 4:
396 yield args[3][0](context, mapping, args[3][1])
396 yield args[3][0](context, mapping, args[3][1])
397
397
398 def ifeq(context, mapping, args):
398 def ifeq(context, mapping, args):
399 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
399 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
400 whether 2 items are equivalent."""
400 whether 2 items are equivalent."""
401 if not (3 <= len(args) <= 4):
401 if not (3 <= len(args) <= 4):
402 # i18n: "ifeq" is a keyword
402 # i18n: "ifeq" is a keyword
403 raise error.ParseError(_("ifeq expects three or four arguments"))
403 raise error.ParseError(_("ifeq expects three or four arguments"))
404
404
405 test = stringify(args[0][0](context, mapping, args[0][1]))
405 test = stringify(args[0][0](context, mapping, args[0][1]))
406 match = stringify(args[1][0](context, mapping, args[1][1]))
406 match = stringify(args[1][0](context, mapping, args[1][1]))
407 if test == match:
407 if test == match:
408 yield args[2][0](context, mapping, args[2][1])
408 yield args[2][0](context, mapping, args[2][1])
409 elif len(args) == 4:
409 elif len(args) == 4:
410 yield args[3][0](context, mapping, args[3][1])
410 yield args[3][0](context, mapping, args[3][1])
411
411
412 def join(context, mapping, args):
412 def join(context, mapping, args):
413 """:join(list, sep): Join items in a list with a delimiter."""
413 """:join(list, sep): Join items in a list with a delimiter."""
414 if not (1 <= len(args) <= 2):
414 if not (1 <= len(args) <= 2):
415 # i18n: "join" is a keyword
415 # i18n: "join" is a keyword
416 raise error.ParseError(_("join expects one or two arguments"))
416 raise error.ParseError(_("join expects one or two arguments"))
417
417
418 joinset = args[0][0](context, mapping, args[0][1])
418 joinset = args[0][0](context, mapping, args[0][1])
419 if callable(joinset):
419 if callable(joinset):
420 jf = joinset.joinfmt
420 jf = joinset.joinfmt
421 joinset = [jf(x) for x in joinset()]
421 joinset = [jf(x) for x in joinset()]
422
422
423 joiner = " "
423 joiner = " "
424 if len(args) > 1:
424 if len(args) > 1:
425 joiner = stringify(args[1][0](context, mapping, args[1][1]))
425 joiner = stringify(args[1][0](context, mapping, args[1][1]))
426
426
427 first = True
427 first = True
428 for x in joinset:
428 for x in joinset:
429 if first:
429 if first:
430 first = False
430 first = False
431 else:
431 else:
432 yield joiner
432 yield joiner
433 yield x
433 yield x
434
434
435 def label(context, mapping, args):
435 def label(context, mapping, args):
436 """:label(label, expr): Apply a label to generated content. Content with
436 """:label(label, expr): Apply a label to generated content. Content with
437 a label applied can result in additional post-processing, such as
437 a label applied can result in additional post-processing, such as
438 automatic colorization."""
438 automatic colorization."""
439 if len(args) != 2:
439 if len(args) != 2:
440 # i18n: "label" is a keyword
440 # i18n: "label" is a keyword
441 raise error.ParseError(_("label expects two arguments"))
441 raise error.ParseError(_("label expects two arguments"))
442
442
443 # ignore args[0] (the label string) since this is supposed to be a a no-op
443 # ignore args[0] (the label string) since this is supposed to be a a no-op
444 yield args[1][0](context, mapping, args[1][1])
444 yield args[1][0](context, mapping, args[1][1])
445
445
446 def revset(context, mapping, args):
446 def revset(context, mapping, args):
447 """:revset(query[, formatargs...]): Execute a revision set query. See
447 """:revset(query[, formatargs...]): Execute a revision set query. See
448 :hg:`help revset`."""
448 :hg:`help revset`."""
449 if not len(args) > 0:
449 if not len(args) > 0:
450 # i18n: "revset" is a keyword
450 # i18n: "revset" is a keyword
451 raise error.ParseError(_("revset expects one or more arguments"))
451 raise error.ParseError(_("revset expects one or more arguments"))
452
452
453 raw = args[0][1]
453 raw = stringify(args[0][0](context, mapping, args[0][1]))
454 ctx = mapping['ctx']
454 ctx = mapping['ctx']
455 repo = ctx.repo()
455 repo = ctx.repo()
456
456
457 def query(expr):
457 def query(expr):
458 m = revsetmod.match(repo.ui, expr)
458 m = revsetmod.match(repo.ui, expr)
459 return m(repo)
459 return m(repo)
460
460
461 if len(args) > 1:
461 if len(args) > 1:
462 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
462 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
463 revs = query(revsetmod.formatspec(raw, *formatargs))
463 revs = query(revsetmod.formatspec(raw, *formatargs))
464 revs = list([str(r) for r in revs])
464 revs = list([str(r) for r in revs])
465 else:
465 else:
466 revsetcache = mapping['cache'].setdefault("revsetcache", {})
466 revsetcache = mapping['cache'].setdefault("revsetcache", {})
467 if raw in revsetcache:
467 if raw in revsetcache:
468 revs = revsetcache[raw]
468 revs = revsetcache[raw]
469 else:
469 else:
470 revs = query(raw)
470 revs = query(raw)
471 revs = list([str(r) for r in revs])
471 revs = list([str(r) for r in revs])
472 revsetcache[raw] = revs
472 revsetcache[raw] = revs
473
473
474 return templatekw.showlist("revision", revs, **mapping)
474 return templatekw.showlist("revision", revs, **mapping)
475
475
476 def rstdoc(context, mapping, args):
476 def rstdoc(context, mapping, args):
477 """:rstdoc(text, style): Format ReStructuredText."""
477 """:rstdoc(text, style): Format ReStructuredText."""
478 if len(args) != 2:
478 if len(args) != 2:
479 # i18n: "rstdoc" is a keyword
479 # i18n: "rstdoc" is a keyword
480 raise error.ParseError(_("rstdoc expects two arguments"))
480 raise error.ParseError(_("rstdoc expects two arguments"))
481
481
482 text = stringify(args[0][0](context, mapping, args[0][1]))
482 text = stringify(args[0][0](context, mapping, args[0][1]))
483 style = stringify(args[1][0](context, mapping, args[1][1]))
483 style = stringify(args[1][0](context, mapping, args[1][1]))
484
484
485 return minirst.format(text, style=style, keep=['verbose'])
485 return minirst.format(text, style=style, keep=['verbose'])
486
486
487 def shortest(context, mapping, args):
487 def shortest(context, mapping, args):
488 """:shortest(node, minlength=4): Obtain the shortest representation of
488 """:shortest(node, minlength=4): Obtain the shortest representation of
489 a node."""
489 a node."""
490 if not (1 <= len(args) <= 2):
490 if not (1 <= len(args) <= 2):
491 # i18n: "shortest" is a keyword
491 # i18n: "shortest" is a keyword
492 raise error.ParseError(_("shortest() expects one or two arguments"))
492 raise error.ParseError(_("shortest() expects one or two arguments"))
493
493
494 node = stringify(args[0][0](context, mapping, args[0][1]))
494 node = stringify(args[0][0](context, mapping, args[0][1]))
495
495
496 minlength = 4
496 minlength = 4
497 if len(args) > 1:
497 if len(args) > 1:
498 minlength = int(args[1][1])
498 minlength = int(args[1][1])
499
499
500 cl = mapping['ctx']._repo.changelog
500 cl = mapping['ctx']._repo.changelog
501 def isvalid(test):
501 def isvalid(test):
502 try:
502 try:
503 try:
503 try:
504 cl.index.partialmatch(test)
504 cl.index.partialmatch(test)
505 except AttributeError:
505 except AttributeError:
506 # Pure mercurial doesn't support partialmatch on the index.
506 # Pure mercurial doesn't support partialmatch on the index.
507 # Fallback to the slow way.
507 # Fallback to the slow way.
508 if cl._partialmatch(test) is None:
508 if cl._partialmatch(test) is None:
509 return False
509 return False
510
510
511 try:
511 try:
512 i = int(test)
512 i = int(test)
513 # if we are a pure int, then starting with zero will not be
513 # if we are a pure int, then starting with zero will not be
514 # confused as a rev; or, obviously, if the int is larger than
514 # confused as a rev; or, obviously, if the int is larger than
515 # the value of the tip rev
515 # the value of the tip rev
516 if test[0] == '0' or i > len(cl):
516 if test[0] == '0' or i > len(cl):
517 return True
517 return True
518 return False
518 return False
519 except ValueError:
519 except ValueError:
520 return True
520 return True
521 except error.RevlogError:
521 except error.RevlogError:
522 return False
522 return False
523
523
524 shortest = node
524 shortest = node
525 startlength = max(6, minlength)
525 startlength = max(6, minlength)
526 length = startlength
526 length = startlength
527 while True:
527 while True:
528 test = node[:length]
528 test = node[:length]
529 if isvalid(test):
529 if isvalid(test):
530 shortest = test
530 shortest = test
531 if length == minlength or length > startlength:
531 if length == minlength or length > startlength:
532 return shortest
532 return shortest
533 length -= 1
533 length -= 1
534 else:
534 else:
535 length += 1
535 length += 1
536 if len(shortest) <= length:
536 if len(shortest) <= length:
537 return shortest
537 return shortest
538
538
539 def strip(context, mapping, args):
539 def strip(context, mapping, args):
540 """:strip(text[, chars]): Strip characters from a string."""
540 """:strip(text[, chars]): Strip characters from a string."""
541 if not (1 <= len(args) <= 2):
541 if not (1 <= len(args) <= 2):
542 # i18n: "strip" is a keyword
542 # i18n: "strip" is a keyword
543 raise error.ParseError(_("strip expects one or two arguments"))
543 raise error.ParseError(_("strip expects one or two arguments"))
544
544
545 text = stringify(args[0][0](context, mapping, args[0][1]))
545 text = stringify(args[0][0](context, mapping, args[0][1]))
546 if len(args) == 2:
546 if len(args) == 2:
547 chars = stringify(args[1][0](context, mapping, args[1][1]))
547 chars = stringify(args[1][0](context, mapping, args[1][1]))
548 return text.strip(chars)
548 return text.strip(chars)
549 return text.strip()
549 return text.strip()
550
550
551 def sub(context, mapping, args):
551 def sub(context, mapping, args):
552 """:sub(pattern, replacement, expression): Perform text substitution
552 """:sub(pattern, replacement, expression): Perform text substitution
553 using regular expressions."""
553 using regular expressions."""
554 if len(args) != 3:
554 if len(args) != 3:
555 # i18n: "sub" is a keyword
555 # i18n: "sub" is a keyword
556 raise error.ParseError(_("sub expects three arguments"))
556 raise error.ParseError(_("sub expects three arguments"))
557
557
558 pat = stringify(args[0][0](context, mapping, args[0][1]))
558 pat = stringify(args[0][0](context, mapping, args[0][1]))
559 rpl = stringify(args[1][0](context, mapping, args[1][1]))
559 rpl = stringify(args[1][0](context, mapping, args[1][1]))
560 src = stringify(args[2][0](context, mapping, args[2][1]))
560 src = stringify(args[2][0](context, mapping, args[2][1]))
561 yield re.sub(pat, rpl, src)
561 yield re.sub(pat, rpl, src)
562
562
563 def startswith(context, mapping, args):
563 def startswith(context, mapping, args):
564 """:startswith(pattern, text): Returns the value from the "text" argument
564 """:startswith(pattern, text): Returns the value from the "text" argument
565 if it begins with the content from the "pattern" argument."""
565 if it begins with the content from the "pattern" argument."""
566 if len(args) != 2:
566 if len(args) != 2:
567 # i18n: "startswith" is a keyword
567 # i18n: "startswith" is a keyword
568 raise error.ParseError(_("startswith expects two arguments"))
568 raise error.ParseError(_("startswith expects two arguments"))
569
569
570 patn = stringify(args[0][0](context, mapping, args[0][1]))
570 patn = stringify(args[0][0](context, mapping, args[0][1]))
571 text = stringify(args[1][0](context, mapping, args[1][1]))
571 text = stringify(args[1][0](context, mapping, args[1][1]))
572 if text.startswith(patn):
572 if text.startswith(patn):
573 return text
573 return text
574 return ''
574 return ''
575
575
576
576
577 def word(context, mapping, args):
577 def word(context, mapping, args):
578 """:word(number, text[, separator]): Return the nth word from a string."""
578 """:word(number, text[, separator]): Return the nth word from a string."""
579 if not (2 <= len(args) <= 3):
579 if not (2 <= len(args) <= 3):
580 # i18n: "word" is a keyword
580 # i18n: "word" is a keyword
581 raise error.ParseError(_("word expects two or three arguments, got %d")
581 raise error.ParseError(_("word expects two or three arguments, got %d")
582 % len(args))
582 % len(args))
583
583
584 try:
584 try:
585 num = int(stringify(args[0][0](context, mapping, args[0][1])))
585 num = int(stringify(args[0][0](context, mapping, args[0][1])))
586 except ValueError:
586 except ValueError:
587 # i18n: "word" is a keyword
587 # i18n: "word" is a keyword
588 raise error.ParseError(_("word expects an integer index"))
588 raise error.ParseError(_("word expects an integer index"))
589 text = stringify(args[1][0](context, mapping, args[1][1]))
589 text = stringify(args[1][0](context, mapping, args[1][1]))
590 if len(args) == 3:
590 if len(args) == 3:
591 splitter = stringify(args[2][0](context, mapping, args[2][1]))
591 splitter = stringify(args[2][0](context, mapping, args[2][1]))
592 else:
592 else:
593 splitter = None
593 splitter = None
594
594
595 tokens = text.split(splitter)
595 tokens = text.split(splitter)
596 if num >= len(tokens):
596 if num >= len(tokens):
597 return ''
597 return ''
598 else:
598 else:
599 return tokens[num]
599 return tokens[num]
600
600
601 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
601 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
602 exprmethods = {
602 exprmethods = {
603 "integer": lambda e, c: (runinteger, e[1]),
603 "integer": lambda e, c: (runinteger, e[1]),
604 "string": lambda e, c: (runstring, e[1]),
604 "string": lambda e, c: (runstring, e[1]),
605 "rawstring": lambda e, c: (runrawstring, e[1]),
605 "rawstring": lambda e, c: (runrawstring, e[1]),
606 "symbol": lambda e, c: (runsymbol, e[1]),
606 "symbol": lambda e, c: (runsymbol, e[1]),
607 "template": buildtemplate,
607 "template": buildtemplate,
608 "group": lambda e, c: compileexp(e[1], c, exprmethods),
608 "group": lambda e, c: compileexp(e[1], c, exprmethods),
609 # ".": buildmember,
609 # ".": buildmember,
610 "|": buildfilter,
610 "|": buildfilter,
611 "%": buildmap,
611 "%": buildmap,
612 "func": buildfunc,
612 "func": buildfunc,
613 }
613 }
614
614
615 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
615 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
616 methods = exprmethods.copy()
616 methods = exprmethods.copy()
617 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
617 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
618
618
619 funcs = {
619 funcs = {
620 "date": date,
620 "date": date,
621 "diff": diff,
621 "diff": diff,
622 "fill": fill,
622 "fill": fill,
623 "get": get,
623 "get": get,
624 "if": if_,
624 "if": if_,
625 "ifcontains": ifcontains,
625 "ifcontains": ifcontains,
626 "ifeq": ifeq,
626 "ifeq": ifeq,
627 "indent": indent,
627 "indent": indent,
628 "join": join,
628 "join": join,
629 "label": label,
629 "label": label,
630 "pad": pad,
630 "pad": pad,
631 "revset": revset,
631 "revset": revset,
632 "rstdoc": rstdoc,
632 "rstdoc": rstdoc,
633 "shortest": shortest,
633 "shortest": shortest,
634 "startswith": startswith,
634 "startswith": startswith,
635 "strip": strip,
635 "strip": strip,
636 "sub": sub,
636 "sub": sub,
637 "word": word,
637 "word": word,
638 }
638 }
639
639
640 # template engine
640 # template engine
641
641
642 stringify = templatefilters.stringify
642 stringify = templatefilters.stringify
643
643
644 def _flatten(thing):
644 def _flatten(thing):
645 '''yield a single stream from a possibly nested set of iterators'''
645 '''yield a single stream from a possibly nested set of iterators'''
646 if isinstance(thing, str):
646 if isinstance(thing, str):
647 yield thing
647 yield thing
648 elif not util.safehasattr(thing, '__iter__'):
648 elif not util.safehasattr(thing, '__iter__'):
649 if thing is not None:
649 if thing is not None:
650 yield str(thing)
650 yield str(thing)
651 else:
651 else:
652 for i in thing:
652 for i in thing:
653 if isinstance(i, str):
653 if isinstance(i, str):
654 yield i
654 yield i
655 elif not util.safehasattr(i, '__iter__'):
655 elif not util.safehasattr(i, '__iter__'):
656 if i is not None:
656 if i is not None:
657 yield str(i)
657 yield str(i)
658 elif i is not None:
658 elif i is not None:
659 for j in _flatten(i):
659 for j in _flatten(i):
660 yield j
660 yield j
661
661
662 def unquotestring(s):
662 def unquotestring(s):
663 '''unwrap quotes'''
663 '''unwrap quotes'''
664 if len(s) < 2 or s[0] != s[-1]:
664 if len(s) < 2 or s[0] != s[-1]:
665 raise SyntaxError(_('unmatched quotes'))
665 raise SyntaxError(_('unmatched quotes'))
666 # de-backslash-ify only <\">. it is invalid syntax in non-string part of
666 # de-backslash-ify only <\">. it is invalid syntax in non-string part of
667 # template, but we are likely to escape <"> in quoted string and it was
667 # template, but we are likely to escape <"> in quoted string and it was
668 # accepted before, thanks to issue4290. <\\"> is unmodified because it
668 # accepted before, thanks to issue4290. <\\"> is unmodified because it
669 # is ambiguous and it was processed as such before 2.8.1.
669 # is ambiguous and it was processed as such before 2.8.1.
670 #
670 #
671 # template result
671 # template result
672 # --------- ------------------------
672 # --------- ------------------------
673 # {\"\"} parse error
673 # {\"\"} parse error
674 # "{""}" {""} -> <>
674 # "{""}" {""} -> <>
675 # "{\"\"}" {""} -> <>
675 # "{\"\"}" {""} -> <>
676 # {"\""} {"\""} -> <">
676 # {"\""} {"\""} -> <">
677 # '{"\""}' {"\""} -> <">
677 # '{"\""}' {"\""} -> <">
678 # "{"\""}" parse error (don't care)
678 # "{"\""}" parse error (don't care)
679 q = s[0]
679 q = s[0]
680 return s[1:-1].replace('\\\\' + q, '\\\\\\' + q).replace('\\' + q, q)
680 return s[1:-1].replace('\\\\' + q, '\\\\\\' + q).replace('\\' + q, q)
681
681
682 class engine(object):
682 class engine(object):
683 '''template expansion engine.
683 '''template expansion engine.
684
684
685 template expansion works like this. a map file contains key=value
685 template expansion works like this. a map file contains key=value
686 pairs. if value is quoted, it is treated as string. otherwise, it
686 pairs. if value is quoted, it is treated as string. otherwise, it
687 is treated as name of template file.
687 is treated as name of template file.
688
688
689 templater is asked to expand a key in map. it looks up key, and
689 templater is asked to expand a key in map. it looks up key, and
690 looks for strings like this: {foo}. it expands {foo} by looking up
690 looks for strings like this: {foo}. it expands {foo} by looking up
691 foo in map, and substituting it. expansion is recursive: it stops
691 foo in map, and substituting it. expansion is recursive: it stops
692 when there is no more {foo} to replace.
692 when there is no more {foo} to replace.
693
693
694 expansion also allows formatting and filtering.
694 expansion also allows formatting and filtering.
695
695
696 format uses key to expand each item in list. syntax is
696 format uses key to expand each item in list. syntax is
697 {key%format}.
697 {key%format}.
698
698
699 filter uses function to transform value. syntax is
699 filter uses function to transform value. syntax is
700 {key|filter1|filter2|...}.'''
700 {key|filter1|filter2|...}.'''
701
701
702 def __init__(self, loader, filters={}, defaults={}):
702 def __init__(self, loader, filters={}, defaults={}):
703 self._loader = loader
703 self._loader = loader
704 self._filters = filters
704 self._filters = filters
705 self._defaults = defaults
705 self._defaults = defaults
706 self._cache = {}
706 self._cache = {}
707
707
708 def _load(self, t):
708 def _load(self, t):
709 '''load, parse, and cache a template'''
709 '''load, parse, and cache a template'''
710 if t not in self._cache:
710 if t not in self._cache:
711 self._cache[t] = compiletemplate(self._loader(t), self)
711 self._cache[t] = compiletemplate(self._loader(t), self)
712 return self._cache[t]
712 return self._cache[t]
713
713
714 def process(self, t, mapping):
714 def process(self, t, mapping):
715 '''Perform expansion. t is name of map element to expand.
715 '''Perform expansion. t is name of map element to expand.
716 mapping contains added elements for use during expansion. Is a
716 mapping contains added elements for use during expansion. Is a
717 generator.'''
717 generator.'''
718 return _flatten(runtemplate(self, mapping, self._load(t)))
718 return _flatten(runtemplate(self, mapping, self._load(t)))
719
719
720 engines = {'default': engine}
720 engines = {'default': engine}
721
721
722 def stylelist():
722 def stylelist():
723 paths = templatepaths()
723 paths = templatepaths()
724 if not paths:
724 if not paths:
725 return _('no templates found, try `hg debuginstall` for more info')
725 return _('no templates found, try `hg debuginstall` for more info')
726 dirlist = os.listdir(paths[0])
726 dirlist = os.listdir(paths[0])
727 stylelist = []
727 stylelist = []
728 for file in dirlist:
728 for file in dirlist:
729 split = file.split(".")
729 split = file.split(".")
730 if split[0] == "map-cmdline":
730 if split[0] == "map-cmdline":
731 stylelist.append(split[1])
731 stylelist.append(split[1])
732 return ", ".join(sorted(stylelist))
732 return ", ".join(sorted(stylelist))
733
733
734 class TemplateNotFound(util.Abort):
734 class TemplateNotFound(util.Abort):
735 pass
735 pass
736
736
737 class templater(object):
737 class templater(object):
738
738
739 def __init__(self, mapfile, filters={}, defaults={}, cache={},
739 def __init__(self, mapfile, filters={}, defaults={}, cache={},
740 minchunk=1024, maxchunk=65536):
740 minchunk=1024, maxchunk=65536):
741 '''set up template engine.
741 '''set up template engine.
742 mapfile is name of file to read map definitions from.
742 mapfile is name of file to read map definitions from.
743 filters is dict of functions. each transforms a value into another.
743 filters is dict of functions. each transforms a value into another.
744 defaults is dict of default map definitions.'''
744 defaults is dict of default map definitions.'''
745 self.mapfile = mapfile or 'template'
745 self.mapfile = mapfile or 'template'
746 self.cache = cache.copy()
746 self.cache = cache.copy()
747 self.map = {}
747 self.map = {}
748 if mapfile:
748 if mapfile:
749 self.base = os.path.dirname(mapfile)
749 self.base = os.path.dirname(mapfile)
750 else:
750 else:
751 self.base = ''
751 self.base = ''
752 self.filters = templatefilters.filters.copy()
752 self.filters = templatefilters.filters.copy()
753 self.filters.update(filters)
753 self.filters.update(filters)
754 self.defaults = defaults
754 self.defaults = defaults
755 self.minchunk, self.maxchunk = minchunk, maxchunk
755 self.minchunk, self.maxchunk = minchunk, maxchunk
756 self.ecache = {}
756 self.ecache = {}
757
757
758 if not mapfile:
758 if not mapfile:
759 return
759 return
760 if not os.path.exists(mapfile):
760 if not os.path.exists(mapfile):
761 raise util.Abort(_("style '%s' not found") % mapfile,
761 raise util.Abort(_("style '%s' not found") % mapfile,
762 hint=_("available styles: %s") % stylelist())
762 hint=_("available styles: %s") % stylelist())
763
763
764 conf = config.config(includepaths=templatepaths())
764 conf = config.config(includepaths=templatepaths())
765 conf.read(mapfile)
765 conf.read(mapfile)
766
766
767 for key, val in conf[''].items():
767 for key, val in conf[''].items():
768 if not val:
768 if not val:
769 raise SyntaxError(_('%s: missing value') % conf.source('', key))
769 raise SyntaxError(_('%s: missing value') % conf.source('', key))
770 if val[0] in "'\"":
770 if val[0] in "'\"":
771 try:
771 try:
772 self.cache[key] = unquotestring(val)
772 self.cache[key] = unquotestring(val)
773 except SyntaxError as inst:
773 except SyntaxError as inst:
774 raise SyntaxError('%s: %s' %
774 raise SyntaxError('%s: %s' %
775 (conf.source('', key), inst.args[0]))
775 (conf.source('', key), inst.args[0]))
776 else:
776 else:
777 val = 'default', val
777 val = 'default', val
778 if ':' in val[1]:
778 if ':' in val[1]:
779 val = val[1].split(':', 1)
779 val = val[1].split(':', 1)
780 self.map[key] = val[0], os.path.join(self.base, val[1])
780 self.map[key] = val[0], os.path.join(self.base, val[1])
781
781
782 def __contains__(self, key):
782 def __contains__(self, key):
783 return key in self.cache or key in self.map
783 return key in self.cache or key in self.map
784
784
785 def load(self, t):
785 def load(self, t):
786 '''Get the template for the given template name. Use a local cache.'''
786 '''Get the template for the given template name. Use a local cache.'''
787 if t not in self.cache:
787 if t not in self.cache:
788 try:
788 try:
789 self.cache[t] = util.readfile(self.map[t][1])
789 self.cache[t] = util.readfile(self.map[t][1])
790 except KeyError as inst:
790 except KeyError as inst:
791 raise TemplateNotFound(_('"%s" not in template map') %
791 raise TemplateNotFound(_('"%s" not in template map') %
792 inst.args[0])
792 inst.args[0])
793 except IOError as inst:
793 except IOError as inst:
794 raise IOError(inst.args[0], _('template file %s: %s') %
794 raise IOError(inst.args[0], _('template file %s: %s') %
795 (self.map[t][1], inst.args[1]))
795 (self.map[t][1], inst.args[1]))
796 return self.cache[t]
796 return self.cache[t]
797
797
798 def __call__(self, t, **mapping):
798 def __call__(self, t, **mapping):
799 ttype = t in self.map and self.map[t][0] or 'default'
799 ttype = t in self.map and self.map[t][0] or 'default'
800 if ttype not in self.ecache:
800 if ttype not in self.ecache:
801 self.ecache[ttype] = engines[ttype](self.load,
801 self.ecache[ttype] = engines[ttype](self.load,
802 self.filters, self.defaults)
802 self.filters, self.defaults)
803 proc = self.ecache[ttype]
803 proc = self.ecache[ttype]
804
804
805 stream = proc.process(t, mapping)
805 stream = proc.process(t, mapping)
806 if self.minchunk:
806 if self.minchunk:
807 stream = util.increasingchunks(stream, min=self.minchunk,
807 stream = util.increasingchunks(stream, min=self.minchunk,
808 max=self.maxchunk)
808 max=self.maxchunk)
809 return stream
809 return stream
810
810
811 def templatepaths():
811 def templatepaths():
812 '''return locations used for template files.'''
812 '''return locations used for template files.'''
813 pathsrel = ['templates']
813 pathsrel = ['templates']
814 paths = [os.path.normpath(os.path.join(util.datapath, f))
814 paths = [os.path.normpath(os.path.join(util.datapath, f))
815 for f in pathsrel]
815 for f in pathsrel]
816 return [p for p in paths if os.path.isdir(p)]
816 return [p for p in paths if os.path.isdir(p)]
817
817
818 def templatepath(name):
818 def templatepath(name):
819 '''return location of template file. returns None if not found.'''
819 '''return location of template file. returns None if not found.'''
820 for p in templatepaths():
820 for p in templatepaths():
821 f = os.path.join(p, name)
821 f = os.path.join(p, name)
822 if os.path.exists(f):
822 if os.path.exists(f):
823 return f
823 return f
824 return None
824 return None
825
825
826 def stylemap(styles, paths=None):
826 def stylemap(styles, paths=None):
827 """Return path to mapfile for a given style.
827 """Return path to mapfile for a given style.
828
828
829 Searches mapfile in the following locations:
829 Searches mapfile in the following locations:
830 1. templatepath/style/map
830 1. templatepath/style/map
831 2. templatepath/map-style
831 2. templatepath/map-style
832 3. templatepath/map
832 3. templatepath/map
833 """
833 """
834
834
835 if paths is None:
835 if paths is None:
836 paths = templatepaths()
836 paths = templatepaths()
837 elif isinstance(paths, str):
837 elif isinstance(paths, str):
838 paths = [paths]
838 paths = [paths]
839
839
840 if isinstance(styles, str):
840 if isinstance(styles, str):
841 styles = [styles]
841 styles = [styles]
842
842
843 for style in styles:
843 for style in styles:
844 # only plain name is allowed to honor template paths
844 # only plain name is allowed to honor template paths
845 if (not style
845 if (not style
846 or style in (os.curdir, os.pardir)
846 or style in (os.curdir, os.pardir)
847 or os.sep in style
847 or os.sep in style
848 or os.altsep and os.altsep in style):
848 or os.altsep and os.altsep in style):
849 continue
849 continue
850 locations = [os.path.join(style, 'map'), 'map-' + style]
850 locations = [os.path.join(style, 'map'), 'map-' + style]
851 locations.append('map')
851 locations.append('map')
852
852
853 for path in paths:
853 for path in paths:
854 for location in locations:
854 for location in locations:
855 mapfile = os.path.join(path, location)
855 mapfile = os.path.join(path, location)
856 if os.path.isfile(mapfile):
856 if os.path.isfile(mapfile):
857 return style, mapfile
857 return style, mapfile
858
858
859 raise RuntimeError("No hgweb templates found in %r" % paths)
859 raise RuntimeError("No hgweb templates found in %r" % paths)
860
860
861 # tell hggettext to extract docstrings from these functions:
861 # tell hggettext to extract docstrings from these functions:
862 i18nfunctions = funcs.values()
862 i18nfunctions = funcs.values()
@@ -1,3311 +1,3325
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo a > a
3 $ echo a > a
4 $ hg add a
4 $ hg add a
5 $ echo line 1 > b
5 $ echo line 1 > b
6 $ echo line 2 >> b
6 $ echo line 2 >> b
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
8
8
9 $ hg add b
9 $ hg add b
10 $ echo other 1 > c
10 $ echo other 1 > c
11 $ echo other 2 >> c
11 $ echo other 2 >> c
12 $ echo >> c
12 $ echo >> c
13 $ echo other 3 >> c
13 $ echo other 3 >> c
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15
15
16 $ hg add c
16 $ hg add c
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 $ echo c >> c
18 $ echo c >> c
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20
20
21 $ echo foo > .hg/branch
21 $ echo foo > .hg/branch
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
23
23
24 $ hg co -q 3
24 $ hg co -q 3
25 $ echo other 4 >> d
25 $ echo other 4 >> d
26 $ hg add d
26 $ hg add d
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
28
28
29 $ hg merge -q foo
29 $ hg merge -q foo
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
31
31
32 Second branch starting at nullrev:
32 Second branch starting at nullrev:
33
33
34 $ hg update null
34 $ hg update null
35 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
35 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
36 $ echo second > second
36 $ echo second > second
37 $ hg add second
37 $ hg add second
38 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
38 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
39 created new head
39 created new head
40
40
41 $ echo third > third
41 $ echo third > third
42 $ hg add third
42 $ hg add third
43 $ hg mv second fourth
43 $ hg mv second fourth
44 $ hg commit -m third -d "2020-01-01 10:01"
44 $ hg commit -m third -d "2020-01-01 10:01"
45
45
46 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
46 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
47 fourth (second)
47 fourth (second)
48 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
48 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
49 second -> fourth
49 second -> fourth
50 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
50 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
51 8 t
51 8 t
52 7 f
52 7 f
53
53
54 Quoting for ui.logtemplate
54 Quoting for ui.logtemplate
55
55
56 $ hg tip --config "ui.logtemplate={rev}\n"
56 $ hg tip --config "ui.logtemplate={rev}\n"
57 8
57 8
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
59 8
59 8
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
61 8
61 8
62
62
63 Make sure user/global hgrc does not affect tests
63 Make sure user/global hgrc does not affect tests
64
64
65 $ echo '[ui]' > .hg/hgrc
65 $ echo '[ui]' > .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
68
68
69 Add some simple styles to settings
69 Add some simple styles to settings
70
70
71 $ echo '[templates]' >> .hg/hgrc
71 $ echo '[templates]' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
74
74
75 $ hg log -l1 -Tsimple
75 $ hg log -l1 -Tsimple
76 8
76 8
77 $ hg log -l1 -Tsimple2
77 $ hg log -l1 -Tsimple2
78 8
78 8
79
79
80 Test templates and style maps in files:
80 Test templates and style maps in files:
81
81
82 $ echo "{rev}" > tmpl
82 $ echo "{rev}" > tmpl
83 $ hg log -l1 -T./tmpl
83 $ hg log -l1 -T./tmpl
84 8
84 8
85 $ hg log -l1 -Tblah/blah
85 $ hg log -l1 -Tblah/blah
86 blah/blah (no-eol)
86 blah/blah (no-eol)
87
87
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
89 $ hg log -l1 -T./map-simple
89 $ hg log -l1 -T./map-simple
90 8
90 8
91
91
92 Template should precede style option
92 Template should precede style option
93
93
94 $ hg log -l1 --style default -T '{rev}\n'
94 $ hg log -l1 --style default -T '{rev}\n'
95 8
95 8
96
96
97 Add a commit with empty description, to ensure that the templates
97 Add a commit with empty description, to ensure that the templates
98 below will omit the description line.
98 below will omit the description line.
99
99
100 $ echo c >> c
100 $ echo c >> c
101 $ hg add c
101 $ hg add c
102 $ hg commit -qm ' '
102 $ hg commit -qm ' '
103
103
104 Default style is like normal output. Phases style should be the same
104 Default style is like normal output. Phases style should be the same
105 as default style, except for extra phase lines.
105 as default style, except for extra phase lines.
106
106
107 $ hg log > log.out
107 $ hg log > log.out
108 $ hg log --style default > style.out
108 $ hg log --style default > style.out
109 $ cmp log.out style.out || diff -u log.out style.out
109 $ cmp log.out style.out || diff -u log.out style.out
110 $ hg log -T phases > phases.out
110 $ hg log -T phases > phases.out
111 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
111 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
112 @@ -2,0 +3 @@
112 @@ -2,0 +3 @@
113 +phase: draft
113 +phase: draft
114 @@ -6,0 +8 @@
114 @@ -6,0 +8 @@
115 +phase: draft
115 +phase: draft
116 @@ -11,0 +14 @@
116 @@ -11,0 +14 @@
117 +phase: draft
117 +phase: draft
118 @@ -17,0 +21 @@
118 @@ -17,0 +21 @@
119 +phase: draft
119 +phase: draft
120 @@ -24,0 +29 @@
120 @@ -24,0 +29 @@
121 +phase: draft
121 +phase: draft
122 @@ -31,0 +37 @@
122 @@ -31,0 +37 @@
123 +phase: draft
123 +phase: draft
124 @@ -36,0 +43 @@
124 @@ -36,0 +43 @@
125 +phase: draft
125 +phase: draft
126 @@ -41,0 +49 @@
126 @@ -41,0 +49 @@
127 +phase: draft
127 +phase: draft
128 @@ -46,0 +55 @@
128 @@ -46,0 +55 @@
129 +phase: draft
129 +phase: draft
130 @@ -51,0 +61 @@
130 @@ -51,0 +61 @@
131 +phase: draft
131 +phase: draft
132
132
133 $ hg log -v > log.out
133 $ hg log -v > log.out
134 $ hg log -v --style default > style.out
134 $ hg log -v --style default > style.out
135 $ cmp log.out style.out || diff -u log.out style.out
135 $ cmp log.out style.out || diff -u log.out style.out
136 $ hg log -v -T phases > phases.out
136 $ hg log -v -T phases > phases.out
137 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
137 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
138 @@ -2,0 +3 @@
138 @@ -2,0 +3 @@
139 +phase: draft
139 +phase: draft
140 @@ -7,0 +9 @@
140 @@ -7,0 +9 @@
141 +phase: draft
141 +phase: draft
142 @@ -15,0 +18 @@
142 @@ -15,0 +18 @@
143 +phase: draft
143 +phase: draft
144 @@ -24,0 +28 @@
144 @@ -24,0 +28 @@
145 +phase: draft
145 +phase: draft
146 @@ -33,0 +38 @@
146 @@ -33,0 +38 @@
147 +phase: draft
147 +phase: draft
148 @@ -43,0 +49 @@
148 @@ -43,0 +49 @@
149 +phase: draft
149 +phase: draft
150 @@ -50,0 +57 @@
150 @@ -50,0 +57 @@
151 +phase: draft
151 +phase: draft
152 @@ -58,0 +66 @@
152 @@ -58,0 +66 @@
153 +phase: draft
153 +phase: draft
154 @@ -66,0 +75 @@
154 @@ -66,0 +75 @@
155 +phase: draft
155 +phase: draft
156 @@ -77,0 +87 @@
156 @@ -77,0 +87 @@
157 +phase: draft
157 +phase: draft
158
158
159 $ hg log -q > log.out
159 $ hg log -q > log.out
160 $ hg log -q --style default > style.out
160 $ hg log -q --style default > style.out
161 $ cmp log.out style.out || diff -u log.out style.out
161 $ cmp log.out style.out || diff -u log.out style.out
162 $ hg log -q -T phases > phases.out
162 $ hg log -q -T phases > phases.out
163 $ cmp log.out phases.out || diff -u log.out phases.out
163 $ cmp log.out phases.out || diff -u log.out phases.out
164
164
165 $ hg log --debug > log.out
165 $ hg log --debug > log.out
166 $ hg log --debug --style default > style.out
166 $ hg log --debug --style default > style.out
167 $ cmp log.out style.out || diff -u log.out style.out
167 $ cmp log.out style.out || diff -u log.out style.out
168 $ hg log --debug -T phases > phases.out
168 $ hg log --debug -T phases > phases.out
169 $ cmp log.out phases.out || diff -u log.out phases.out
169 $ cmp log.out phases.out || diff -u log.out phases.out
170
170
171 Default style should also preserve color information (issue2866):
171 Default style should also preserve color information (issue2866):
172
172
173 $ cp $HGRCPATH $HGRCPATH-bak
173 $ cp $HGRCPATH $HGRCPATH-bak
174 $ cat <<EOF >> $HGRCPATH
174 $ cat <<EOF >> $HGRCPATH
175 > [extensions]
175 > [extensions]
176 > color=
176 > color=
177 > EOF
177 > EOF
178
178
179 $ hg --color=debug log > log.out
179 $ hg --color=debug log > log.out
180 $ hg --color=debug log --style default > style.out
180 $ hg --color=debug log --style default > style.out
181 $ cmp log.out style.out || diff -u log.out style.out
181 $ cmp log.out style.out || diff -u log.out style.out
182 $ hg --color=debug log -T phases > phases.out
182 $ hg --color=debug log -T phases > phases.out
183 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
183 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
184 @@ -2,0 +3 @@
184 @@ -2,0 +3 @@
185 +[log.phase|phase: draft]
185 +[log.phase|phase: draft]
186 @@ -6,0 +8 @@
186 @@ -6,0 +8 @@
187 +[log.phase|phase: draft]
187 +[log.phase|phase: draft]
188 @@ -11,0 +14 @@
188 @@ -11,0 +14 @@
189 +[log.phase|phase: draft]
189 +[log.phase|phase: draft]
190 @@ -17,0 +21 @@
190 @@ -17,0 +21 @@
191 +[log.phase|phase: draft]
191 +[log.phase|phase: draft]
192 @@ -24,0 +29 @@
192 @@ -24,0 +29 @@
193 +[log.phase|phase: draft]
193 +[log.phase|phase: draft]
194 @@ -31,0 +37 @@
194 @@ -31,0 +37 @@
195 +[log.phase|phase: draft]
195 +[log.phase|phase: draft]
196 @@ -36,0 +43 @@
196 @@ -36,0 +43 @@
197 +[log.phase|phase: draft]
197 +[log.phase|phase: draft]
198 @@ -41,0 +49 @@
198 @@ -41,0 +49 @@
199 +[log.phase|phase: draft]
199 +[log.phase|phase: draft]
200 @@ -46,0 +55 @@
200 @@ -46,0 +55 @@
201 +[log.phase|phase: draft]
201 +[log.phase|phase: draft]
202 @@ -51,0 +61 @@
202 @@ -51,0 +61 @@
203 +[log.phase|phase: draft]
203 +[log.phase|phase: draft]
204
204
205 $ hg --color=debug -v log > log.out
205 $ hg --color=debug -v log > log.out
206 $ hg --color=debug -v log --style default > style.out
206 $ hg --color=debug -v log --style default > style.out
207 $ cmp log.out style.out || diff -u log.out style.out
207 $ cmp log.out style.out || diff -u log.out style.out
208 $ hg --color=debug -v log -T phases > phases.out
208 $ hg --color=debug -v log -T phases > phases.out
209 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
209 $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
210 @@ -2,0 +3 @@
210 @@ -2,0 +3 @@
211 +[log.phase|phase: draft]
211 +[log.phase|phase: draft]
212 @@ -7,0 +9 @@
212 @@ -7,0 +9 @@
213 +[log.phase|phase: draft]
213 +[log.phase|phase: draft]
214 @@ -15,0 +18 @@
214 @@ -15,0 +18 @@
215 +[log.phase|phase: draft]
215 +[log.phase|phase: draft]
216 @@ -24,0 +28 @@
216 @@ -24,0 +28 @@
217 +[log.phase|phase: draft]
217 +[log.phase|phase: draft]
218 @@ -33,0 +38 @@
218 @@ -33,0 +38 @@
219 +[log.phase|phase: draft]
219 +[log.phase|phase: draft]
220 @@ -43,0 +49 @@
220 @@ -43,0 +49 @@
221 +[log.phase|phase: draft]
221 +[log.phase|phase: draft]
222 @@ -50,0 +57 @@
222 @@ -50,0 +57 @@
223 +[log.phase|phase: draft]
223 +[log.phase|phase: draft]
224 @@ -58,0 +66 @@
224 @@ -58,0 +66 @@
225 +[log.phase|phase: draft]
225 +[log.phase|phase: draft]
226 @@ -66,0 +75 @@
226 @@ -66,0 +75 @@
227 +[log.phase|phase: draft]
227 +[log.phase|phase: draft]
228 @@ -77,0 +87 @@
228 @@ -77,0 +87 @@
229 +[log.phase|phase: draft]
229 +[log.phase|phase: draft]
230
230
231 $ hg --color=debug -q log > log.out
231 $ hg --color=debug -q log > log.out
232 $ hg --color=debug -q log --style default > style.out
232 $ hg --color=debug -q log --style default > style.out
233 $ cmp log.out style.out || diff -u log.out style.out
233 $ cmp log.out style.out || diff -u log.out style.out
234 $ hg --color=debug -q log -T phases > phases.out
234 $ hg --color=debug -q log -T phases > phases.out
235 $ cmp log.out phases.out || diff -u log.out phases.out
235 $ cmp log.out phases.out || diff -u log.out phases.out
236
236
237 $ hg --color=debug --debug log > log.out
237 $ hg --color=debug --debug log > log.out
238 $ hg --color=debug --debug log --style default > style.out
238 $ hg --color=debug --debug log --style default > style.out
239 $ cmp log.out style.out || diff -u log.out style.out
239 $ cmp log.out style.out || diff -u log.out style.out
240 $ hg --color=debug --debug log -T phases > phases.out
240 $ hg --color=debug --debug log -T phases > phases.out
241 $ cmp log.out phases.out || diff -u log.out phases.out
241 $ cmp log.out phases.out || diff -u log.out phases.out
242
242
243 $ mv $HGRCPATH-bak $HGRCPATH
243 $ mv $HGRCPATH-bak $HGRCPATH
244
244
245 Remove commit with empty commit message, so as to not pollute further
245 Remove commit with empty commit message, so as to not pollute further
246 tests.
246 tests.
247
247
248 $ hg --config extensions.strip= strip -q .
248 $ hg --config extensions.strip= strip -q .
249
249
250 Revision with no copies (used to print a traceback):
250 Revision with no copies (used to print a traceback):
251
251
252 $ hg tip -v --template '\n'
252 $ hg tip -v --template '\n'
253
253
254
254
255 Compact style works:
255 Compact style works:
256
256
257 $ hg log -Tcompact
257 $ hg log -Tcompact
258 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
258 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
259 third
259 third
260
260
261 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
261 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
262 second
262 second
263
263
264 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
264 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
265 merge
265 merge
266
266
267 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
267 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
268 new head
268 new head
269
269
270 4 bbe44766e73d 1970-01-17 04:53 +0000 person
270 4 bbe44766e73d 1970-01-17 04:53 +0000 person
271 new branch
271 new branch
272
272
273 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
273 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
274 no user, no domain
274 no user, no domain
275
275
276 2 97054abb4ab8 1970-01-14 21:20 +0000 other
276 2 97054abb4ab8 1970-01-14 21:20 +0000 other
277 no person
277 no person
278
278
279 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
279 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
280 other 1
280 other 1
281
281
282 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
282 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
283 line 1
283 line 1
284
284
285
285
286 $ hg log -v --style compact
286 $ hg log -v --style compact
287 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
287 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
288 third
288 third
289
289
290 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
290 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
291 second
291 second
292
292
293 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
293 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
294 merge
294 merge
295
295
296 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
296 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
297 new head
297 new head
298
298
299 4 bbe44766e73d 1970-01-17 04:53 +0000 person
299 4 bbe44766e73d 1970-01-17 04:53 +0000 person
300 new branch
300 new branch
301
301
302 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
302 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
303 no user, no domain
303 no user, no domain
304
304
305 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
305 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
306 no person
306 no person
307
307
308 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
308 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
309 other 1
309 other 1
310 other 2
310 other 2
311
311
312 other 3
312 other 3
313
313
314 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
314 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
315 line 1
315 line 1
316 line 2
316 line 2
317
317
318
318
319 $ hg log --debug --style compact
319 $ hg log --debug --style compact
320 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
320 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
321 third
321 third
322
322
323 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
323 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
324 second
324 second
325
325
326 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
326 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
327 merge
327 merge
328
328
329 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
329 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
330 new head
330 new head
331
331
332 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
332 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
333 new branch
333 new branch
334
334
335 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
335 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
336 no user, no domain
336 no user, no domain
337
337
338 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
338 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
339 no person
339 no person
340
340
341 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
341 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
342 other 1
342 other 1
343 other 2
343 other 2
344
344
345 other 3
345 other 3
346
346
347 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
347 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
348 line 1
348 line 1
349 line 2
349 line 2
350
350
351
351
352 Test xml styles:
352 Test xml styles:
353
353
354 $ hg log --style xml
354 $ hg log --style xml
355 <?xml version="1.0"?>
355 <?xml version="1.0"?>
356 <log>
356 <log>
357 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
357 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
358 <tag>tip</tag>
358 <tag>tip</tag>
359 <author email="test">test</author>
359 <author email="test">test</author>
360 <date>2020-01-01T10:01:00+00:00</date>
360 <date>2020-01-01T10:01:00+00:00</date>
361 <msg xml:space="preserve">third</msg>
361 <msg xml:space="preserve">third</msg>
362 </logentry>
362 </logentry>
363 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
363 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
364 <parent revision="-1" node="0000000000000000000000000000000000000000" />
364 <parent revision="-1" node="0000000000000000000000000000000000000000" />
365 <author email="user@hostname">User Name</author>
365 <author email="user@hostname">User Name</author>
366 <date>1970-01-12T13:46:40+00:00</date>
366 <date>1970-01-12T13:46:40+00:00</date>
367 <msg xml:space="preserve">second</msg>
367 <msg xml:space="preserve">second</msg>
368 </logentry>
368 </logentry>
369 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
369 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
370 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
370 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
371 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
371 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
372 <author email="person">person</author>
372 <author email="person">person</author>
373 <date>1970-01-18T08:40:01+00:00</date>
373 <date>1970-01-18T08:40:01+00:00</date>
374 <msg xml:space="preserve">merge</msg>
374 <msg xml:space="preserve">merge</msg>
375 </logentry>
375 </logentry>
376 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
376 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
377 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
377 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
378 <author email="person">person</author>
378 <author email="person">person</author>
379 <date>1970-01-18T08:40:00+00:00</date>
379 <date>1970-01-18T08:40:00+00:00</date>
380 <msg xml:space="preserve">new head</msg>
380 <msg xml:space="preserve">new head</msg>
381 </logentry>
381 </logentry>
382 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
382 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
383 <branch>foo</branch>
383 <branch>foo</branch>
384 <author email="person">person</author>
384 <author email="person">person</author>
385 <date>1970-01-17T04:53:20+00:00</date>
385 <date>1970-01-17T04:53:20+00:00</date>
386 <msg xml:space="preserve">new branch</msg>
386 <msg xml:space="preserve">new branch</msg>
387 </logentry>
387 </logentry>
388 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
388 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
389 <author email="person">person</author>
389 <author email="person">person</author>
390 <date>1970-01-16T01:06:40+00:00</date>
390 <date>1970-01-16T01:06:40+00:00</date>
391 <msg xml:space="preserve">no user, no domain</msg>
391 <msg xml:space="preserve">no user, no domain</msg>
392 </logentry>
392 </logentry>
393 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
393 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
394 <author email="other@place">other</author>
394 <author email="other@place">other</author>
395 <date>1970-01-14T21:20:00+00:00</date>
395 <date>1970-01-14T21:20:00+00:00</date>
396 <msg xml:space="preserve">no person</msg>
396 <msg xml:space="preserve">no person</msg>
397 </logentry>
397 </logentry>
398 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
398 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
399 <author email="other@place">A. N. Other</author>
399 <author email="other@place">A. N. Other</author>
400 <date>1970-01-13T17:33:20+00:00</date>
400 <date>1970-01-13T17:33:20+00:00</date>
401 <msg xml:space="preserve">other 1
401 <msg xml:space="preserve">other 1
402 other 2
402 other 2
403
403
404 other 3</msg>
404 other 3</msg>
405 </logentry>
405 </logentry>
406 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
406 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
407 <author email="user@hostname">User Name</author>
407 <author email="user@hostname">User Name</author>
408 <date>1970-01-12T13:46:40+00:00</date>
408 <date>1970-01-12T13:46:40+00:00</date>
409 <msg xml:space="preserve">line 1
409 <msg xml:space="preserve">line 1
410 line 2</msg>
410 line 2</msg>
411 </logentry>
411 </logentry>
412 </log>
412 </log>
413
413
414 $ hg log -v --style xml
414 $ hg log -v --style xml
415 <?xml version="1.0"?>
415 <?xml version="1.0"?>
416 <log>
416 <log>
417 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
417 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
418 <tag>tip</tag>
418 <tag>tip</tag>
419 <author email="test">test</author>
419 <author email="test">test</author>
420 <date>2020-01-01T10:01:00+00:00</date>
420 <date>2020-01-01T10:01:00+00:00</date>
421 <msg xml:space="preserve">third</msg>
421 <msg xml:space="preserve">third</msg>
422 <paths>
422 <paths>
423 <path action="A">fourth</path>
423 <path action="A">fourth</path>
424 <path action="A">third</path>
424 <path action="A">third</path>
425 <path action="R">second</path>
425 <path action="R">second</path>
426 </paths>
426 </paths>
427 <copies>
427 <copies>
428 <copy source="second">fourth</copy>
428 <copy source="second">fourth</copy>
429 </copies>
429 </copies>
430 </logentry>
430 </logentry>
431 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
431 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
432 <parent revision="-1" node="0000000000000000000000000000000000000000" />
432 <parent revision="-1" node="0000000000000000000000000000000000000000" />
433 <author email="user@hostname">User Name</author>
433 <author email="user@hostname">User Name</author>
434 <date>1970-01-12T13:46:40+00:00</date>
434 <date>1970-01-12T13:46:40+00:00</date>
435 <msg xml:space="preserve">second</msg>
435 <msg xml:space="preserve">second</msg>
436 <paths>
436 <paths>
437 <path action="A">second</path>
437 <path action="A">second</path>
438 </paths>
438 </paths>
439 </logentry>
439 </logentry>
440 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
440 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
441 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
441 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
442 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
442 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
443 <author email="person">person</author>
443 <author email="person">person</author>
444 <date>1970-01-18T08:40:01+00:00</date>
444 <date>1970-01-18T08:40:01+00:00</date>
445 <msg xml:space="preserve">merge</msg>
445 <msg xml:space="preserve">merge</msg>
446 <paths>
446 <paths>
447 </paths>
447 </paths>
448 </logentry>
448 </logentry>
449 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
449 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
450 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
450 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
451 <author email="person">person</author>
451 <author email="person">person</author>
452 <date>1970-01-18T08:40:00+00:00</date>
452 <date>1970-01-18T08:40:00+00:00</date>
453 <msg xml:space="preserve">new head</msg>
453 <msg xml:space="preserve">new head</msg>
454 <paths>
454 <paths>
455 <path action="A">d</path>
455 <path action="A">d</path>
456 </paths>
456 </paths>
457 </logentry>
457 </logentry>
458 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
458 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
459 <branch>foo</branch>
459 <branch>foo</branch>
460 <author email="person">person</author>
460 <author email="person">person</author>
461 <date>1970-01-17T04:53:20+00:00</date>
461 <date>1970-01-17T04:53:20+00:00</date>
462 <msg xml:space="preserve">new branch</msg>
462 <msg xml:space="preserve">new branch</msg>
463 <paths>
463 <paths>
464 </paths>
464 </paths>
465 </logentry>
465 </logentry>
466 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
466 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
467 <author email="person">person</author>
467 <author email="person">person</author>
468 <date>1970-01-16T01:06:40+00:00</date>
468 <date>1970-01-16T01:06:40+00:00</date>
469 <msg xml:space="preserve">no user, no domain</msg>
469 <msg xml:space="preserve">no user, no domain</msg>
470 <paths>
470 <paths>
471 <path action="M">c</path>
471 <path action="M">c</path>
472 </paths>
472 </paths>
473 </logentry>
473 </logentry>
474 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
474 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
475 <author email="other@place">other</author>
475 <author email="other@place">other</author>
476 <date>1970-01-14T21:20:00+00:00</date>
476 <date>1970-01-14T21:20:00+00:00</date>
477 <msg xml:space="preserve">no person</msg>
477 <msg xml:space="preserve">no person</msg>
478 <paths>
478 <paths>
479 <path action="A">c</path>
479 <path action="A">c</path>
480 </paths>
480 </paths>
481 </logentry>
481 </logentry>
482 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
482 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
483 <author email="other@place">A. N. Other</author>
483 <author email="other@place">A. N. Other</author>
484 <date>1970-01-13T17:33:20+00:00</date>
484 <date>1970-01-13T17:33:20+00:00</date>
485 <msg xml:space="preserve">other 1
485 <msg xml:space="preserve">other 1
486 other 2
486 other 2
487
487
488 other 3</msg>
488 other 3</msg>
489 <paths>
489 <paths>
490 <path action="A">b</path>
490 <path action="A">b</path>
491 </paths>
491 </paths>
492 </logentry>
492 </logentry>
493 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
493 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
494 <author email="user@hostname">User Name</author>
494 <author email="user@hostname">User Name</author>
495 <date>1970-01-12T13:46:40+00:00</date>
495 <date>1970-01-12T13:46:40+00:00</date>
496 <msg xml:space="preserve">line 1
496 <msg xml:space="preserve">line 1
497 line 2</msg>
497 line 2</msg>
498 <paths>
498 <paths>
499 <path action="A">a</path>
499 <path action="A">a</path>
500 </paths>
500 </paths>
501 </logentry>
501 </logentry>
502 </log>
502 </log>
503
503
504 $ hg log --debug --style xml
504 $ hg log --debug --style xml
505 <?xml version="1.0"?>
505 <?xml version="1.0"?>
506 <log>
506 <log>
507 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
507 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
508 <tag>tip</tag>
508 <tag>tip</tag>
509 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
509 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
510 <parent revision="-1" node="0000000000000000000000000000000000000000" />
510 <parent revision="-1" node="0000000000000000000000000000000000000000" />
511 <author email="test">test</author>
511 <author email="test">test</author>
512 <date>2020-01-01T10:01:00+00:00</date>
512 <date>2020-01-01T10:01:00+00:00</date>
513 <msg xml:space="preserve">third</msg>
513 <msg xml:space="preserve">third</msg>
514 <paths>
514 <paths>
515 <path action="A">fourth</path>
515 <path action="A">fourth</path>
516 <path action="A">third</path>
516 <path action="A">third</path>
517 <path action="R">second</path>
517 <path action="R">second</path>
518 </paths>
518 </paths>
519 <copies>
519 <copies>
520 <copy source="second">fourth</copy>
520 <copy source="second">fourth</copy>
521 </copies>
521 </copies>
522 <extra key="branch">default</extra>
522 <extra key="branch">default</extra>
523 </logentry>
523 </logentry>
524 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
524 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
525 <parent revision="-1" node="0000000000000000000000000000000000000000" />
525 <parent revision="-1" node="0000000000000000000000000000000000000000" />
526 <parent revision="-1" node="0000000000000000000000000000000000000000" />
526 <parent revision="-1" node="0000000000000000000000000000000000000000" />
527 <author email="user@hostname">User Name</author>
527 <author email="user@hostname">User Name</author>
528 <date>1970-01-12T13:46:40+00:00</date>
528 <date>1970-01-12T13:46:40+00:00</date>
529 <msg xml:space="preserve">second</msg>
529 <msg xml:space="preserve">second</msg>
530 <paths>
530 <paths>
531 <path action="A">second</path>
531 <path action="A">second</path>
532 </paths>
532 </paths>
533 <extra key="branch">default</extra>
533 <extra key="branch">default</extra>
534 </logentry>
534 </logentry>
535 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
535 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
536 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
536 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
537 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
537 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
538 <author email="person">person</author>
538 <author email="person">person</author>
539 <date>1970-01-18T08:40:01+00:00</date>
539 <date>1970-01-18T08:40:01+00:00</date>
540 <msg xml:space="preserve">merge</msg>
540 <msg xml:space="preserve">merge</msg>
541 <paths>
541 <paths>
542 </paths>
542 </paths>
543 <extra key="branch">default</extra>
543 <extra key="branch">default</extra>
544 </logentry>
544 </logentry>
545 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
545 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
546 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
546 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
547 <parent revision="-1" node="0000000000000000000000000000000000000000" />
547 <parent revision="-1" node="0000000000000000000000000000000000000000" />
548 <author email="person">person</author>
548 <author email="person">person</author>
549 <date>1970-01-18T08:40:00+00:00</date>
549 <date>1970-01-18T08:40:00+00:00</date>
550 <msg xml:space="preserve">new head</msg>
550 <msg xml:space="preserve">new head</msg>
551 <paths>
551 <paths>
552 <path action="A">d</path>
552 <path action="A">d</path>
553 </paths>
553 </paths>
554 <extra key="branch">default</extra>
554 <extra key="branch">default</extra>
555 </logentry>
555 </logentry>
556 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
556 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
557 <branch>foo</branch>
557 <branch>foo</branch>
558 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
558 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
559 <parent revision="-1" node="0000000000000000000000000000000000000000" />
559 <parent revision="-1" node="0000000000000000000000000000000000000000" />
560 <author email="person">person</author>
560 <author email="person">person</author>
561 <date>1970-01-17T04:53:20+00:00</date>
561 <date>1970-01-17T04:53:20+00:00</date>
562 <msg xml:space="preserve">new branch</msg>
562 <msg xml:space="preserve">new branch</msg>
563 <paths>
563 <paths>
564 </paths>
564 </paths>
565 <extra key="branch">foo</extra>
565 <extra key="branch">foo</extra>
566 </logentry>
566 </logentry>
567 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
567 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
568 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
568 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
569 <parent revision="-1" node="0000000000000000000000000000000000000000" />
569 <parent revision="-1" node="0000000000000000000000000000000000000000" />
570 <author email="person">person</author>
570 <author email="person">person</author>
571 <date>1970-01-16T01:06:40+00:00</date>
571 <date>1970-01-16T01:06:40+00:00</date>
572 <msg xml:space="preserve">no user, no domain</msg>
572 <msg xml:space="preserve">no user, no domain</msg>
573 <paths>
573 <paths>
574 <path action="M">c</path>
574 <path action="M">c</path>
575 </paths>
575 </paths>
576 <extra key="branch">default</extra>
576 <extra key="branch">default</extra>
577 </logentry>
577 </logentry>
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
579 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
579 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
581 <author email="other@place">other</author>
581 <author email="other@place">other</author>
582 <date>1970-01-14T21:20:00+00:00</date>
582 <date>1970-01-14T21:20:00+00:00</date>
583 <msg xml:space="preserve">no person</msg>
583 <msg xml:space="preserve">no person</msg>
584 <paths>
584 <paths>
585 <path action="A">c</path>
585 <path action="A">c</path>
586 </paths>
586 </paths>
587 <extra key="branch">default</extra>
587 <extra key="branch">default</extra>
588 </logentry>
588 </logentry>
589 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
589 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
590 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
590 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
591 <parent revision="-1" node="0000000000000000000000000000000000000000" />
591 <parent revision="-1" node="0000000000000000000000000000000000000000" />
592 <author email="other@place">A. N. Other</author>
592 <author email="other@place">A. N. Other</author>
593 <date>1970-01-13T17:33:20+00:00</date>
593 <date>1970-01-13T17:33:20+00:00</date>
594 <msg xml:space="preserve">other 1
594 <msg xml:space="preserve">other 1
595 other 2
595 other 2
596
596
597 other 3</msg>
597 other 3</msg>
598 <paths>
598 <paths>
599 <path action="A">b</path>
599 <path action="A">b</path>
600 </paths>
600 </paths>
601 <extra key="branch">default</extra>
601 <extra key="branch">default</extra>
602 </logentry>
602 </logentry>
603 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
603 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
604 <parent revision="-1" node="0000000000000000000000000000000000000000" />
604 <parent revision="-1" node="0000000000000000000000000000000000000000" />
605 <parent revision="-1" node="0000000000000000000000000000000000000000" />
605 <parent revision="-1" node="0000000000000000000000000000000000000000" />
606 <author email="user@hostname">User Name</author>
606 <author email="user@hostname">User Name</author>
607 <date>1970-01-12T13:46:40+00:00</date>
607 <date>1970-01-12T13:46:40+00:00</date>
608 <msg xml:space="preserve">line 1
608 <msg xml:space="preserve">line 1
609 line 2</msg>
609 line 2</msg>
610 <paths>
610 <paths>
611 <path action="A">a</path>
611 <path action="A">a</path>
612 </paths>
612 </paths>
613 <extra key="branch">default</extra>
613 <extra key="branch">default</extra>
614 </logentry>
614 </logentry>
615 </log>
615 </log>
616
616
617
617
618 Test JSON style:
618 Test JSON style:
619
619
620 $ hg log -k nosuch -Tjson
620 $ hg log -k nosuch -Tjson
621 []
621 []
622
622
623 $ hg log -qr . -Tjson
623 $ hg log -qr . -Tjson
624 [
624 [
625 {
625 {
626 "rev": 8,
626 "rev": 8,
627 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
627 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
628 }
628 }
629 ]
629 ]
630
630
631 $ hg log -vpr . -Tjson --stat
631 $ hg log -vpr . -Tjson --stat
632 [
632 [
633 {
633 {
634 "rev": 8,
634 "rev": 8,
635 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
635 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
636 "branch": "default",
636 "branch": "default",
637 "phase": "draft",
637 "phase": "draft",
638 "user": "test",
638 "user": "test",
639 "date": [1577872860, 0],
639 "date": [1577872860, 0],
640 "desc": "third",
640 "desc": "third",
641 "bookmarks": [],
641 "bookmarks": [],
642 "tags": ["tip"],
642 "tags": ["tip"],
643 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
643 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
644 "files": ["fourth", "second", "third"],
644 "files": ["fourth", "second", "third"],
645 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
645 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
646 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
646 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
647 }
647 }
648 ]
648 ]
649
649
650 honor --git but not format-breaking diffopts
650 honor --git but not format-breaking diffopts
651 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
651 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
652 [
652 [
653 {
653 {
654 "rev": 8,
654 "rev": 8,
655 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
655 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
656 "branch": "default",
656 "branch": "default",
657 "phase": "draft",
657 "phase": "draft",
658 "user": "test",
658 "user": "test",
659 "date": [1577872860, 0],
659 "date": [1577872860, 0],
660 "desc": "third",
660 "desc": "third",
661 "bookmarks": [],
661 "bookmarks": [],
662 "tags": ["tip"],
662 "tags": ["tip"],
663 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
663 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
664 "files": ["fourth", "second", "third"],
664 "files": ["fourth", "second", "third"],
665 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
665 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
666 }
666 }
667 ]
667 ]
668
668
669 $ hg log -T json
669 $ hg log -T json
670 [
670 [
671 {
671 {
672 "rev": 8,
672 "rev": 8,
673 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
673 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
674 "branch": "default",
674 "branch": "default",
675 "phase": "draft",
675 "phase": "draft",
676 "user": "test",
676 "user": "test",
677 "date": [1577872860, 0],
677 "date": [1577872860, 0],
678 "desc": "third",
678 "desc": "third",
679 "bookmarks": [],
679 "bookmarks": [],
680 "tags": ["tip"],
680 "tags": ["tip"],
681 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
681 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
682 },
682 },
683 {
683 {
684 "rev": 7,
684 "rev": 7,
685 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
685 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
686 "branch": "default",
686 "branch": "default",
687 "phase": "draft",
687 "phase": "draft",
688 "user": "User Name <user@hostname>",
688 "user": "User Name <user@hostname>",
689 "date": [1000000, 0],
689 "date": [1000000, 0],
690 "desc": "second",
690 "desc": "second",
691 "bookmarks": [],
691 "bookmarks": [],
692 "tags": [],
692 "tags": [],
693 "parents": ["0000000000000000000000000000000000000000"]
693 "parents": ["0000000000000000000000000000000000000000"]
694 },
694 },
695 {
695 {
696 "rev": 6,
696 "rev": 6,
697 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
697 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
698 "branch": "default",
698 "branch": "default",
699 "phase": "draft",
699 "phase": "draft",
700 "user": "person",
700 "user": "person",
701 "date": [1500001, 0],
701 "date": [1500001, 0],
702 "desc": "merge",
702 "desc": "merge",
703 "bookmarks": [],
703 "bookmarks": [],
704 "tags": [],
704 "tags": [],
705 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
705 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
706 },
706 },
707 {
707 {
708 "rev": 5,
708 "rev": 5,
709 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
709 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
710 "branch": "default",
710 "branch": "default",
711 "phase": "draft",
711 "phase": "draft",
712 "user": "person",
712 "user": "person",
713 "date": [1500000, 0],
713 "date": [1500000, 0],
714 "desc": "new head",
714 "desc": "new head",
715 "bookmarks": [],
715 "bookmarks": [],
716 "tags": [],
716 "tags": [],
717 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
717 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
718 },
718 },
719 {
719 {
720 "rev": 4,
720 "rev": 4,
721 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
721 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
722 "branch": "foo",
722 "branch": "foo",
723 "phase": "draft",
723 "phase": "draft",
724 "user": "person",
724 "user": "person",
725 "date": [1400000, 0],
725 "date": [1400000, 0],
726 "desc": "new branch",
726 "desc": "new branch",
727 "bookmarks": [],
727 "bookmarks": [],
728 "tags": [],
728 "tags": [],
729 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
729 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
730 },
730 },
731 {
731 {
732 "rev": 3,
732 "rev": 3,
733 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
733 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
734 "branch": "default",
734 "branch": "default",
735 "phase": "draft",
735 "phase": "draft",
736 "user": "person",
736 "user": "person",
737 "date": [1300000, 0],
737 "date": [1300000, 0],
738 "desc": "no user, no domain",
738 "desc": "no user, no domain",
739 "bookmarks": [],
739 "bookmarks": [],
740 "tags": [],
740 "tags": [],
741 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
741 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
742 },
742 },
743 {
743 {
744 "rev": 2,
744 "rev": 2,
745 "node": "97054abb4ab824450e9164180baf491ae0078465",
745 "node": "97054abb4ab824450e9164180baf491ae0078465",
746 "branch": "default",
746 "branch": "default",
747 "phase": "draft",
747 "phase": "draft",
748 "user": "other@place",
748 "user": "other@place",
749 "date": [1200000, 0],
749 "date": [1200000, 0],
750 "desc": "no person",
750 "desc": "no person",
751 "bookmarks": [],
751 "bookmarks": [],
752 "tags": [],
752 "tags": [],
753 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
753 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
754 },
754 },
755 {
755 {
756 "rev": 1,
756 "rev": 1,
757 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
757 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
758 "branch": "default",
758 "branch": "default",
759 "phase": "draft",
759 "phase": "draft",
760 "user": "A. N. Other <other@place>",
760 "user": "A. N. Other <other@place>",
761 "date": [1100000, 0],
761 "date": [1100000, 0],
762 "desc": "other 1\nother 2\n\nother 3",
762 "desc": "other 1\nother 2\n\nother 3",
763 "bookmarks": [],
763 "bookmarks": [],
764 "tags": [],
764 "tags": [],
765 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
765 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
766 },
766 },
767 {
767 {
768 "rev": 0,
768 "rev": 0,
769 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
769 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
770 "branch": "default",
770 "branch": "default",
771 "phase": "draft",
771 "phase": "draft",
772 "user": "User Name <user@hostname>",
772 "user": "User Name <user@hostname>",
773 "date": [1000000, 0],
773 "date": [1000000, 0],
774 "desc": "line 1\nline 2",
774 "desc": "line 1\nline 2",
775 "bookmarks": [],
775 "bookmarks": [],
776 "tags": [],
776 "tags": [],
777 "parents": ["0000000000000000000000000000000000000000"]
777 "parents": ["0000000000000000000000000000000000000000"]
778 }
778 }
779 ]
779 ]
780
780
781 $ hg heads -v -Tjson
781 $ hg heads -v -Tjson
782 [
782 [
783 {
783 {
784 "rev": 8,
784 "rev": 8,
785 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
785 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
786 "branch": "default",
786 "branch": "default",
787 "phase": "draft",
787 "phase": "draft",
788 "user": "test",
788 "user": "test",
789 "date": [1577872860, 0],
789 "date": [1577872860, 0],
790 "desc": "third",
790 "desc": "third",
791 "bookmarks": [],
791 "bookmarks": [],
792 "tags": ["tip"],
792 "tags": ["tip"],
793 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
793 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
794 "files": ["fourth", "second", "third"]
794 "files": ["fourth", "second", "third"]
795 },
795 },
796 {
796 {
797 "rev": 6,
797 "rev": 6,
798 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
798 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
799 "branch": "default",
799 "branch": "default",
800 "phase": "draft",
800 "phase": "draft",
801 "user": "person",
801 "user": "person",
802 "date": [1500001, 0],
802 "date": [1500001, 0],
803 "desc": "merge",
803 "desc": "merge",
804 "bookmarks": [],
804 "bookmarks": [],
805 "tags": [],
805 "tags": [],
806 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
806 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
807 "files": []
807 "files": []
808 },
808 },
809 {
809 {
810 "rev": 4,
810 "rev": 4,
811 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
811 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
812 "branch": "foo",
812 "branch": "foo",
813 "phase": "draft",
813 "phase": "draft",
814 "user": "person",
814 "user": "person",
815 "date": [1400000, 0],
815 "date": [1400000, 0],
816 "desc": "new branch",
816 "desc": "new branch",
817 "bookmarks": [],
817 "bookmarks": [],
818 "tags": [],
818 "tags": [],
819 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
819 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
820 "files": []
820 "files": []
821 }
821 }
822 ]
822 ]
823
823
824 $ hg log --debug -Tjson
824 $ hg log --debug -Tjson
825 [
825 [
826 {
826 {
827 "rev": 8,
827 "rev": 8,
828 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
828 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
829 "branch": "default",
829 "branch": "default",
830 "phase": "draft",
830 "phase": "draft",
831 "user": "test",
831 "user": "test",
832 "date": [1577872860, 0],
832 "date": [1577872860, 0],
833 "desc": "third",
833 "desc": "third",
834 "bookmarks": [],
834 "bookmarks": [],
835 "tags": ["tip"],
835 "tags": ["tip"],
836 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
836 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
837 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
837 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
838 "extra": {"branch": "default"},
838 "extra": {"branch": "default"},
839 "modified": [],
839 "modified": [],
840 "added": ["fourth", "third"],
840 "added": ["fourth", "third"],
841 "removed": ["second"]
841 "removed": ["second"]
842 },
842 },
843 {
843 {
844 "rev": 7,
844 "rev": 7,
845 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
845 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
846 "branch": "default",
846 "branch": "default",
847 "phase": "draft",
847 "phase": "draft",
848 "user": "User Name <user@hostname>",
848 "user": "User Name <user@hostname>",
849 "date": [1000000, 0],
849 "date": [1000000, 0],
850 "desc": "second",
850 "desc": "second",
851 "bookmarks": [],
851 "bookmarks": [],
852 "tags": [],
852 "tags": [],
853 "parents": ["0000000000000000000000000000000000000000"],
853 "parents": ["0000000000000000000000000000000000000000"],
854 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
854 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
855 "extra": {"branch": "default"},
855 "extra": {"branch": "default"},
856 "modified": [],
856 "modified": [],
857 "added": ["second"],
857 "added": ["second"],
858 "removed": []
858 "removed": []
859 },
859 },
860 {
860 {
861 "rev": 6,
861 "rev": 6,
862 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
862 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
863 "branch": "default",
863 "branch": "default",
864 "phase": "draft",
864 "phase": "draft",
865 "user": "person",
865 "user": "person",
866 "date": [1500001, 0],
866 "date": [1500001, 0],
867 "desc": "merge",
867 "desc": "merge",
868 "bookmarks": [],
868 "bookmarks": [],
869 "tags": [],
869 "tags": [],
870 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
870 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
871 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
871 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
872 "extra": {"branch": "default"},
872 "extra": {"branch": "default"},
873 "modified": [],
873 "modified": [],
874 "added": [],
874 "added": [],
875 "removed": []
875 "removed": []
876 },
876 },
877 {
877 {
878 "rev": 5,
878 "rev": 5,
879 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
879 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
880 "branch": "default",
880 "branch": "default",
881 "phase": "draft",
881 "phase": "draft",
882 "user": "person",
882 "user": "person",
883 "date": [1500000, 0],
883 "date": [1500000, 0],
884 "desc": "new head",
884 "desc": "new head",
885 "bookmarks": [],
885 "bookmarks": [],
886 "tags": [],
886 "tags": [],
887 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
887 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
888 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
888 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
889 "extra": {"branch": "default"},
889 "extra": {"branch": "default"},
890 "modified": [],
890 "modified": [],
891 "added": ["d"],
891 "added": ["d"],
892 "removed": []
892 "removed": []
893 },
893 },
894 {
894 {
895 "rev": 4,
895 "rev": 4,
896 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
896 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
897 "branch": "foo",
897 "branch": "foo",
898 "phase": "draft",
898 "phase": "draft",
899 "user": "person",
899 "user": "person",
900 "date": [1400000, 0],
900 "date": [1400000, 0],
901 "desc": "new branch",
901 "desc": "new branch",
902 "bookmarks": [],
902 "bookmarks": [],
903 "tags": [],
903 "tags": [],
904 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
904 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
905 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
905 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
906 "extra": {"branch": "foo"},
906 "extra": {"branch": "foo"},
907 "modified": [],
907 "modified": [],
908 "added": [],
908 "added": [],
909 "removed": []
909 "removed": []
910 },
910 },
911 {
911 {
912 "rev": 3,
912 "rev": 3,
913 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
913 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
914 "branch": "default",
914 "branch": "default",
915 "phase": "draft",
915 "phase": "draft",
916 "user": "person",
916 "user": "person",
917 "date": [1300000, 0],
917 "date": [1300000, 0],
918 "desc": "no user, no domain",
918 "desc": "no user, no domain",
919 "bookmarks": [],
919 "bookmarks": [],
920 "tags": [],
920 "tags": [],
921 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
921 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
922 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
922 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
923 "extra": {"branch": "default"},
923 "extra": {"branch": "default"},
924 "modified": ["c"],
924 "modified": ["c"],
925 "added": [],
925 "added": [],
926 "removed": []
926 "removed": []
927 },
927 },
928 {
928 {
929 "rev": 2,
929 "rev": 2,
930 "node": "97054abb4ab824450e9164180baf491ae0078465",
930 "node": "97054abb4ab824450e9164180baf491ae0078465",
931 "branch": "default",
931 "branch": "default",
932 "phase": "draft",
932 "phase": "draft",
933 "user": "other@place",
933 "user": "other@place",
934 "date": [1200000, 0],
934 "date": [1200000, 0],
935 "desc": "no person",
935 "desc": "no person",
936 "bookmarks": [],
936 "bookmarks": [],
937 "tags": [],
937 "tags": [],
938 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
938 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
939 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
939 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
940 "extra": {"branch": "default"},
940 "extra": {"branch": "default"},
941 "modified": [],
941 "modified": [],
942 "added": ["c"],
942 "added": ["c"],
943 "removed": []
943 "removed": []
944 },
944 },
945 {
945 {
946 "rev": 1,
946 "rev": 1,
947 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
947 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
948 "branch": "default",
948 "branch": "default",
949 "phase": "draft",
949 "phase": "draft",
950 "user": "A. N. Other <other@place>",
950 "user": "A. N. Other <other@place>",
951 "date": [1100000, 0],
951 "date": [1100000, 0],
952 "desc": "other 1\nother 2\n\nother 3",
952 "desc": "other 1\nother 2\n\nother 3",
953 "bookmarks": [],
953 "bookmarks": [],
954 "tags": [],
954 "tags": [],
955 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
955 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
956 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
956 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
957 "extra": {"branch": "default"},
957 "extra": {"branch": "default"},
958 "modified": [],
958 "modified": [],
959 "added": ["b"],
959 "added": ["b"],
960 "removed": []
960 "removed": []
961 },
961 },
962 {
962 {
963 "rev": 0,
963 "rev": 0,
964 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
964 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
965 "branch": "default",
965 "branch": "default",
966 "phase": "draft",
966 "phase": "draft",
967 "user": "User Name <user@hostname>",
967 "user": "User Name <user@hostname>",
968 "date": [1000000, 0],
968 "date": [1000000, 0],
969 "desc": "line 1\nline 2",
969 "desc": "line 1\nline 2",
970 "bookmarks": [],
970 "bookmarks": [],
971 "tags": [],
971 "tags": [],
972 "parents": ["0000000000000000000000000000000000000000"],
972 "parents": ["0000000000000000000000000000000000000000"],
973 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
973 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
974 "extra": {"branch": "default"},
974 "extra": {"branch": "default"},
975 "modified": [],
975 "modified": [],
976 "added": ["a"],
976 "added": ["a"],
977 "removed": []
977 "removed": []
978 }
978 }
979 ]
979 ]
980
980
981 Error if style not readable:
981 Error if style not readable:
982
982
983 #if unix-permissions no-root
983 #if unix-permissions no-root
984 $ touch q
984 $ touch q
985 $ chmod 0 q
985 $ chmod 0 q
986 $ hg log --style ./q
986 $ hg log --style ./q
987 abort: Permission denied: ./q
987 abort: Permission denied: ./q
988 [255]
988 [255]
989 #endif
989 #endif
990
990
991 Error if no style:
991 Error if no style:
992
992
993 $ hg log --style notexist
993 $ hg log --style notexist
994 abort: style 'notexist' not found
994 abort: style 'notexist' not found
995 (available styles: bisect, changelog, compact, default, phases, status, xml)
995 (available styles: bisect, changelog, compact, default, phases, status, xml)
996 [255]
996 [255]
997
997
998 $ hg log -T list
998 $ hg log -T list
999 available styles: bisect, changelog, compact, default, phases, status, xml
999 available styles: bisect, changelog, compact, default, phases, status, xml
1000 abort: specify a template
1000 abort: specify a template
1001 [255]
1001 [255]
1002
1002
1003 Error if style missing key:
1003 Error if style missing key:
1004
1004
1005 $ echo 'q = q' > t
1005 $ echo 'q = q' > t
1006 $ hg log --style ./t
1006 $ hg log --style ./t
1007 abort: "changeset" not in template map
1007 abort: "changeset" not in template map
1008 [255]
1008 [255]
1009
1009
1010 Error if style missing value:
1010 Error if style missing value:
1011
1011
1012 $ echo 'changeset =' > t
1012 $ echo 'changeset =' > t
1013 $ hg log --style t
1013 $ hg log --style t
1014 abort: t:1: missing value
1014 abort: t:1: missing value
1015 [255]
1015 [255]
1016
1016
1017 Error if include fails:
1017 Error if include fails:
1018
1018
1019 $ echo 'changeset = q' >> t
1019 $ echo 'changeset = q' >> t
1020 #if unix-permissions no-root
1020 #if unix-permissions no-root
1021 $ hg log --style ./t
1021 $ hg log --style ./t
1022 abort: template file ./q: Permission denied
1022 abort: template file ./q: Permission denied
1023 [255]
1023 [255]
1024 $ rm q
1024 $ rm q
1025 #endif
1025 #endif
1026
1026
1027 Include works:
1027 Include works:
1028
1028
1029 $ echo '{rev}' > q
1029 $ echo '{rev}' > q
1030 $ hg log --style ./t
1030 $ hg log --style ./t
1031 8
1031 8
1032 7
1032 7
1033 6
1033 6
1034 5
1034 5
1035 4
1035 4
1036 3
1036 3
1037 2
1037 2
1038 1
1038 1
1039 0
1039 0
1040
1040
1041 Check that {phase} works correctly on parents:
1041 Check that {phase} works correctly on parents:
1042
1042
1043 $ cat << EOF > parentphase
1043 $ cat << EOF > parentphase
1044 > changeset_debug = '{rev} ({phase}):{parents}\n'
1044 > changeset_debug = '{rev} ({phase}):{parents}\n'
1045 > parent = ' {rev} ({phase})'
1045 > parent = ' {rev} ({phase})'
1046 > EOF
1046 > EOF
1047 $ hg phase -r 5 --public
1047 $ hg phase -r 5 --public
1048 $ hg phase -r 7 --secret --force
1048 $ hg phase -r 7 --secret --force
1049 $ hg log --debug -G --style ./parentphase
1049 $ hg log --debug -G --style ./parentphase
1050 @ 8 (secret): 7 (secret) -1 (public)
1050 @ 8 (secret): 7 (secret) -1 (public)
1051 |
1051 |
1052 o 7 (secret): -1 (public) -1 (public)
1052 o 7 (secret): -1 (public) -1 (public)
1053
1053
1054 o 6 (draft): 5 (public) 4 (draft)
1054 o 6 (draft): 5 (public) 4 (draft)
1055 |\
1055 |\
1056 | o 5 (public): 3 (public) -1 (public)
1056 | o 5 (public): 3 (public) -1 (public)
1057 | |
1057 | |
1058 o | 4 (draft): 3 (public) -1 (public)
1058 o | 4 (draft): 3 (public) -1 (public)
1059 |/
1059 |/
1060 o 3 (public): 2 (public) -1 (public)
1060 o 3 (public): 2 (public) -1 (public)
1061 |
1061 |
1062 o 2 (public): 1 (public) -1 (public)
1062 o 2 (public): 1 (public) -1 (public)
1063 |
1063 |
1064 o 1 (public): 0 (public) -1 (public)
1064 o 1 (public): 0 (public) -1 (public)
1065 |
1065 |
1066 o 0 (public): -1 (public) -1 (public)
1066 o 0 (public): -1 (public) -1 (public)
1067
1067
1068
1068
1069 Missing non-standard names give no error (backward compatibility):
1069 Missing non-standard names give no error (backward compatibility):
1070
1070
1071 $ echo "changeset = '{c}'" > t
1071 $ echo "changeset = '{c}'" > t
1072 $ hg log --style ./t
1072 $ hg log --style ./t
1073
1073
1074 Defining non-standard name works:
1074 Defining non-standard name works:
1075
1075
1076 $ cat <<EOF > t
1076 $ cat <<EOF > t
1077 > changeset = '{c}'
1077 > changeset = '{c}'
1078 > c = q
1078 > c = q
1079 > EOF
1079 > EOF
1080 $ hg log --style ./t
1080 $ hg log --style ./t
1081 8
1081 8
1082 7
1082 7
1083 6
1083 6
1084 5
1084 5
1085 4
1085 4
1086 3
1086 3
1087 2
1087 2
1088 1
1088 1
1089 0
1089 0
1090
1090
1091 ui.style works:
1091 ui.style works:
1092
1092
1093 $ echo '[ui]' > .hg/hgrc
1093 $ echo '[ui]' > .hg/hgrc
1094 $ echo 'style = t' >> .hg/hgrc
1094 $ echo 'style = t' >> .hg/hgrc
1095 $ hg log
1095 $ hg log
1096 8
1096 8
1097 7
1097 7
1098 6
1098 6
1099 5
1099 5
1100 4
1100 4
1101 3
1101 3
1102 2
1102 2
1103 1
1103 1
1104 0
1104 0
1105
1105
1106
1106
1107 Issue338:
1107 Issue338:
1108
1108
1109 $ hg log --style=changelog > changelog
1109 $ hg log --style=changelog > changelog
1110
1110
1111 $ cat changelog
1111 $ cat changelog
1112 2020-01-01 test <test>
1112 2020-01-01 test <test>
1113
1113
1114 * fourth, second, third:
1114 * fourth, second, third:
1115 third
1115 third
1116 [95c24699272e] [tip]
1116 [95c24699272e] [tip]
1117
1117
1118 1970-01-12 User Name <user@hostname>
1118 1970-01-12 User Name <user@hostname>
1119
1119
1120 * second:
1120 * second:
1121 second
1121 second
1122 [29114dbae42b]
1122 [29114dbae42b]
1123
1123
1124 1970-01-18 person <person>
1124 1970-01-18 person <person>
1125
1125
1126 * merge
1126 * merge
1127 [d41e714fe50d]
1127 [d41e714fe50d]
1128
1128
1129 * d:
1129 * d:
1130 new head
1130 new head
1131 [13207e5a10d9]
1131 [13207e5a10d9]
1132
1132
1133 1970-01-17 person <person>
1133 1970-01-17 person <person>
1134
1134
1135 * new branch
1135 * new branch
1136 [bbe44766e73d] <foo>
1136 [bbe44766e73d] <foo>
1137
1137
1138 1970-01-16 person <person>
1138 1970-01-16 person <person>
1139
1139
1140 * c:
1140 * c:
1141 no user, no domain
1141 no user, no domain
1142 [10e46f2dcbf4]
1142 [10e46f2dcbf4]
1143
1143
1144 1970-01-14 other <other@place>
1144 1970-01-14 other <other@place>
1145
1145
1146 * c:
1146 * c:
1147 no person
1147 no person
1148 [97054abb4ab8]
1148 [97054abb4ab8]
1149
1149
1150 1970-01-13 A. N. Other <other@place>
1150 1970-01-13 A. N. Other <other@place>
1151
1151
1152 * b:
1152 * b:
1153 other 1 other 2
1153 other 1 other 2
1154
1154
1155 other 3
1155 other 3
1156 [b608e9d1a3f0]
1156 [b608e9d1a3f0]
1157
1157
1158 1970-01-12 User Name <user@hostname>
1158 1970-01-12 User Name <user@hostname>
1159
1159
1160 * a:
1160 * a:
1161 line 1 line 2
1161 line 1 line 2
1162 [1e4e1b8f71e0]
1162 [1e4e1b8f71e0]
1163
1163
1164
1164
1165 Issue2130: xml output for 'hg heads' is malformed
1165 Issue2130: xml output for 'hg heads' is malformed
1166
1166
1167 $ hg heads --style changelog
1167 $ hg heads --style changelog
1168 2020-01-01 test <test>
1168 2020-01-01 test <test>
1169
1169
1170 * fourth, second, third:
1170 * fourth, second, third:
1171 third
1171 third
1172 [95c24699272e] [tip]
1172 [95c24699272e] [tip]
1173
1173
1174 1970-01-18 person <person>
1174 1970-01-18 person <person>
1175
1175
1176 * merge
1176 * merge
1177 [d41e714fe50d]
1177 [d41e714fe50d]
1178
1178
1179 1970-01-17 person <person>
1179 1970-01-17 person <person>
1180
1180
1181 * new branch
1181 * new branch
1182 [bbe44766e73d] <foo>
1182 [bbe44766e73d] <foo>
1183
1183
1184
1184
1185 Keys work:
1185 Keys work:
1186
1186
1187 $ for key in author branch branches date desc file_adds file_dels file_mods \
1187 $ for key in author branch branches date desc file_adds file_dels file_mods \
1188 > file_copies file_copies_switch files \
1188 > file_copies file_copies_switch files \
1189 > manifest node parents rev tags diffstat extras \
1189 > manifest node parents rev tags diffstat extras \
1190 > p1rev p2rev p1node p2node; do
1190 > p1rev p2rev p1node p2node; do
1191 > for mode in '' --verbose --debug; do
1191 > for mode in '' --verbose --debug; do
1192 > hg log $mode --template "$key$mode: {$key}\n"
1192 > hg log $mode --template "$key$mode: {$key}\n"
1193 > done
1193 > done
1194 > done
1194 > done
1195 author: test
1195 author: test
1196 author: User Name <user@hostname>
1196 author: User Name <user@hostname>
1197 author: person
1197 author: person
1198 author: person
1198 author: person
1199 author: person
1199 author: person
1200 author: person
1200 author: person
1201 author: other@place
1201 author: other@place
1202 author: A. N. Other <other@place>
1202 author: A. N. Other <other@place>
1203 author: User Name <user@hostname>
1203 author: User Name <user@hostname>
1204 author--verbose: test
1204 author--verbose: test
1205 author--verbose: User Name <user@hostname>
1205 author--verbose: User Name <user@hostname>
1206 author--verbose: person
1206 author--verbose: person
1207 author--verbose: person
1207 author--verbose: person
1208 author--verbose: person
1208 author--verbose: person
1209 author--verbose: person
1209 author--verbose: person
1210 author--verbose: other@place
1210 author--verbose: other@place
1211 author--verbose: A. N. Other <other@place>
1211 author--verbose: A. N. Other <other@place>
1212 author--verbose: User Name <user@hostname>
1212 author--verbose: User Name <user@hostname>
1213 author--debug: test
1213 author--debug: test
1214 author--debug: User Name <user@hostname>
1214 author--debug: User Name <user@hostname>
1215 author--debug: person
1215 author--debug: person
1216 author--debug: person
1216 author--debug: person
1217 author--debug: person
1217 author--debug: person
1218 author--debug: person
1218 author--debug: person
1219 author--debug: other@place
1219 author--debug: other@place
1220 author--debug: A. N. Other <other@place>
1220 author--debug: A. N. Other <other@place>
1221 author--debug: User Name <user@hostname>
1221 author--debug: User Name <user@hostname>
1222 branch: default
1222 branch: default
1223 branch: default
1223 branch: default
1224 branch: default
1224 branch: default
1225 branch: default
1225 branch: default
1226 branch: foo
1226 branch: foo
1227 branch: default
1227 branch: default
1228 branch: default
1228 branch: default
1229 branch: default
1229 branch: default
1230 branch: default
1230 branch: default
1231 branch--verbose: default
1231 branch--verbose: default
1232 branch--verbose: default
1232 branch--verbose: default
1233 branch--verbose: default
1233 branch--verbose: default
1234 branch--verbose: default
1234 branch--verbose: default
1235 branch--verbose: foo
1235 branch--verbose: foo
1236 branch--verbose: default
1236 branch--verbose: default
1237 branch--verbose: default
1237 branch--verbose: default
1238 branch--verbose: default
1238 branch--verbose: default
1239 branch--verbose: default
1239 branch--verbose: default
1240 branch--debug: default
1240 branch--debug: default
1241 branch--debug: default
1241 branch--debug: default
1242 branch--debug: default
1242 branch--debug: default
1243 branch--debug: default
1243 branch--debug: default
1244 branch--debug: foo
1244 branch--debug: foo
1245 branch--debug: default
1245 branch--debug: default
1246 branch--debug: default
1246 branch--debug: default
1247 branch--debug: default
1247 branch--debug: default
1248 branch--debug: default
1248 branch--debug: default
1249 branches:
1249 branches:
1250 branches:
1250 branches:
1251 branches:
1251 branches:
1252 branches:
1252 branches:
1253 branches: foo
1253 branches: foo
1254 branches:
1254 branches:
1255 branches:
1255 branches:
1256 branches:
1256 branches:
1257 branches:
1257 branches:
1258 branches--verbose:
1258 branches--verbose:
1259 branches--verbose:
1259 branches--verbose:
1260 branches--verbose:
1260 branches--verbose:
1261 branches--verbose:
1261 branches--verbose:
1262 branches--verbose: foo
1262 branches--verbose: foo
1263 branches--verbose:
1263 branches--verbose:
1264 branches--verbose:
1264 branches--verbose:
1265 branches--verbose:
1265 branches--verbose:
1266 branches--verbose:
1266 branches--verbose:
1267 branches--debug:
1267 branches--debug:
1268 branches--debug:
1268 branches--debug:
1269 branches--debug:
1269 branches--debug:
1270 branches--debug:
1270 branches--debug:
1271 branches--debug: foo
1271 branches--debug: foo
1272 branches--debug:
1272 branches--debug:
1273 branches--debug:
1273 branches--debug:
1274 branches--debug:
1274 branches--debug:
1275 branches--debug:
1275 branches--debug:
1276 date: 1577872860.00
1276 date: 1577872860.00
1277 date: 1000000.00
1277 date: 1000000.00
1278 date: 1500001.00
1278 date: 1500001.00
1279 date: 1500000.00
1279 date: 1500000.00
1280 date: 1400000.00
1280 date: 1400000.00
1281 date: 1300000.00
1281 date: 1300000.00
1282 date: 1200000.00
1282 date: 1200000.00
1283 date: 1100000.00
1283 date: 1100000.00
1284 date: 1000000.00
1284 date: 1000000.00
1285 date--verbose: 1577872860.00
1285 date--verbose: 1577872860.00
1286 date--verbose: 1000000.00
1286 date--verbose: 1000000.00
1287 date--verbose: 1500001.00
1287 date--verbose: 1500001.00
1288 date--verbose: 1500000.00
1288 date--verbose: 1500000.00
1289 date--verbose: 1400000.00
1289 date--verbose: 1400000.00
1290 date--verbose: 1300000.00
1290 date--verbose: 1300000.00
1291 date--verbose: 1200000.00
1291 date--verbose: 1200000.00
1292 date--verbose: 1100000.00
1292 date--verbose: 1100000.00
1293 date--verbose: 1000000.00
1293 date--verbose: 1000000.00
1294 date--debug: 1577872860.00
1294 date--debug: 1577872860.00
1295 date--debug: 1000000.00
1295 date--debug: 1000000.00
1296 date--debug: 1500001.00
1296 date--debug: 1500001.00
1297 date--debug: 1500000.00
1297 date--debug: 1500000.00
1298 date--debug: 1400000.00
1298 date--debug: 1400000.00
1299 date--debug: 1300000.00
1299 date--debug: 1300000.00
1300 date--debug: 1200000.00
1300 date--debug: 1200000.00
1301 date--debug: 1100000.00
1301 date--debug: 1100000.00
1302 date--debug: 1000000.00
1302 date--debug: 1000000.00
1303 desc: third
1303 desc: third
1304 desc: second
1304 desc: second
1305 desc: merge
1305 desc: merge
1306 desc: new head
1306 desc: new head
1307 desc: new branch
1307 desc: new branch
1308 desc: no user, no domain
1308 desc: no user, no domain
1309 desc: no person
1309 desc: no person
1310 desc: other 1
1310 desc: other 1
1311 other 2
1311 other 2
1312
1312
1313 other 3
1313 other 3
1314 desc: line 1
1314 desc: line 1
1315 line 2
1315 line 2
1316 desc--verbose: third
1316 desc--verbose: third
1317 desc--verbose: second
1317 desc--verbose: second
1318 desc--verbose: merge
1318 desc--verbose: merge
1319 desc--verbose: new head
1319 desc--verbose: new head
1320 desc--verbose: new branch
1320 desc--verbose: new branch
1321 desc--verbose: no user, no domain
1321 desc--verbose: no user, no domain
1322 desc--verbose: no person
1322 desc--verbose: no person
1323 desc--verbose: other 1
1323 desc--verbose: other 1
1324 other 2
1324 other 2
1325
1325
1326 other 3
1326 other 3
1327 desc--verbose: line 1
1327 desc--verbose: line 1
1328 line 2
1328 line 2
1329 desc--debug: third
1329 desc--debug: third
1330 desc--debug: second
1330 desc--debug: second
1331 desc--debug: merge
1331 desc--debug: merge
1332 desc--debug: new head
1332 desc--debug: new head
1333 desc--debug: new branch
1333 desc--debug: new branch
1334 desc--debug: no user, no domain
1334 desc--debug: no user, no domain
1335 desc--debug: no person
1335 desc--debug: no person
1336 desc--debug: other 1
1336 desc--debug: other 1
1337 other 2
1337 other 2
1338
1338
1339 other 3
1339 other 3
1340 desc--debug: line 1
1340 desc--debug: line 1
1341 line 2
1341 line 2
1342 file_adds: fourth third
1342 file_adds: fourth third
1343 file_adds: second
1343 file_adds: second
1344 file_adds:
1344 file_adds:
1345 file_adds: d
1345 file_adds: d
1346 file_adds:
1346 file_adds:
1347 file_adds:
1347 file_adds:
1348 file_adds: c
1348 file_adds: c
1349 file_adds: b
1349 file_adds: b
1350 file_adds: a
1350 file_adds: a
1351 file_adds--verbose: fourth third
1351 file_adds--verbose: fourth third
1352 file_adds--verbose: second
1352 file_adds--verbose: second
1353 file_adds--verbose:
1353 file_adds--verbose:
1354 file_adds--verbose: d
1354 file_adds--verbose: d
1355 file_adds--verbose:
1355 file_adds--verbose:
1356 file_adds--verbose:
1356 file_adds--verbose:
1357 file_adds--verbose: c
1357 file_adds--verbose: c
1358 file_adds--verbose: b
1358 file_adds--verbose: b
1359 file_adds--verbose: a
1359 file_adds--verbose: a
1360 file_adds--debug: fourth third
1360 file_adds--debug: fourth third
1361 file_adds--debug: second
1361 file_adds--debug: second
1362 file_adds--debug:
1362 file_adds--debug:
1363 file_adds--debug: d
1363 file_adds--debug: d
1364 file_adds--debug:
1364 file_adds--debug:
1365 file_adds--debug:
1365 file_adds--debug:
1366 file_adds--debug: c
1366 file_adds--debug: c
1367 file_adds--debug: b
1367 file_adds--debug: b
1368 file_adds--debug: a
1368 file_adds--debug: a
1369 file_dels: second
1369 file_dels: second
1370 file_dels:
1370 file_dels:
1371 file_dels:
1371 file_dels:
1372 file_dels:
1372 file_dels:
1373 file_dels:
1373 file_dels:
1374 file_dels:
1374 file_dels:
1375 file_dels:
1375 file_dels:
1376 file_dels:
1376 file_dels:
1377 file_dels:
1377 file_dels:
1378 file_dels--verbose: second
1378 file_dels--verbose: second
1379 file_dels--verbose:
1379 file_dels--verbose:
1380 file_dels--verbose:
1380 file_dels--verbose:
1381 file_dels--verbose:
1381 file_dels--verbose:
1382 file_dels--verbose:
1382 file_dels--verbose:
1383 file_dels--verbose:
1383 file_dels--verbose:
1384 file_dels--verbose:
1384 file_dels--verbose:
1385 file_dels--verbose:
1385 file_dels--verbose:
1386 file_dels--verbose:
1386 file_dels--verbose:
1387 file_dels--debug: second
1387 file_dels--debug: second
1388 file_dels--debug:
1388 file_dels--debug:
1389 file_dels--debug:
1389 file_dels--debug:
1390 file_dels--debug:
1390 file_dels--debug:
1391 file_dels--debug:
1391 file_dels--debug:
1392 file_dels--debug:
1392 file_dels--debug:
1393 file_dels--debug:
1393 file_dels--debug:
1394 file_dels--debug:
1394 file_dels--debug:
1395 file_dels--debug:
1395 file_dels--debug:
1396 file_mods:
1396 file_mods:
1397 file_mods:
1397 file_mods:
1398 file_mods:
1398 file_mods:
1399 file_mods:
1399 file_mods:
1400 file_mods:
1400 file_mods:
1401 file_mods: c
1401 file_mods: c
1402 file_mods:
1402 file_mods:
1403 file_mods:
1403 file_mods:
1404 file_mods:
1404 file_mods:
1405 file_mods--verbose:
1405 file_mods--verbose:
1406 file_mods--verbose:
1406 file_mods--verbose:
1407 file_mods--verbose:
1407 file_mods--verbose:
1408 file_mods--verbose:
1408 file_mods--verbose:
1409 file_mods--verbose:
1409 file_mods--verbose:
1410 file_mods--verbose: c
1410 file_mods--verbose: c
1411 file_mods--verbose:
1411 file_mods--verbose:
1412 file_mods--verbose:
1412 file_mods--verbose:
1413 file_mods--verbose:
1413 file_mods--verbose:
1414 file_mods--debug:
1414 file_mods--debug:
1415 file_mods--debug:
1415 file_mods--debug:
1416 file_mods--debug:
1416 file_mods--debug:
1417 file_mods--debug:
1417 file_mods--debug:
1418 file_mods--debug:
1418 file_mods--debug:
1419 file_mods--debug: c
1419 file_mods--debug: c
1420 file_mods--debug:
1420 file_mods--debug:
1421 file_mods--debug:
1421 file_mods--debug:
1422 file_mods--debug:
1422 file_mods--debug:
1423 file_copies: fourth (second)
1423 file_copies: fourth (second)
1424 file_copies:
1424 file_copies:
1425 file_copies:
1425 file_copies:
1426 file_copies:
1426 file_copies:
1427 file_copies:
1427 file_copies:
1428 file_copies:
1428 file_copies:
1429 file_copies:
1429 file_copies:
1430 file_copies:
1430 file_copies:
1431 file_copies:
1431 file_copies:
1432 file_copies--verbose: fourth (second)
1432 file_copies--verbose: fourth (second)
1433 file_copies--verbose:
1433 file_copies--verbose:
1434 file_copies--verbose:
1434 file_copies--verbose:
1435 file_copies--verbose:
1435 file_copies--verbose:
1436 file_copies--verbose:
1436 file_copies--verbose:
1437 file_copies--verbose:
1437 file_copies--verbose:
1438 file_copies--verbose:
1438 file_copies--verbose:
1439 file_copies--verbose:
1439 file_copies--verbose:
1440 file_copies--verbose:
1440 file_copies--verbose:
1441 file_copies--debug: fourth (second)
1441 file_copies--debug: fourth (second)
1442 file_copies--debug:
1442 file_copies--debug:
1443 file_copies--debug:
1443 file_copies--debug:
1444 file_copies--debug:
1444 file_copies--debug:
1445 file_copies--debug:
1445 file_copies--debug:
1446 file_copies--debug:
1446 file_copies--debug:
1447 file_copies--debug:
1447 file_copies--debug:
1448 file_copies--debug:
1448 file_copies--debug:
1449 file_copies--debug:
1449 file_copies--debug:
1450 file_copies_switch:
1450 file_copies_switch:
1451 file_copies_switch:
1451 file_copies_switch:
1452 file_copies_switch:
1452 file_copies_switch:
1453 file_copies_switch:
1453 file_copies_switch:
1454 file_copies_switch:
1454 file_copies_switch:
1455 file_copies_switch:
1455 file_copies_switch:
1456 file_copies_switch:
1456 file_copies_switch:
1457 file_copies_switch:
1457 file_copies_switch:
1458 file_copies_switch:
1458 file_copies_switch:
1459 file_copies_switch--verbose:
1459 file_copies_switch--verbose:
1460 file_copies_switch--verbose:
1460 file_copies_switch--verbose:
1461 file_copies_switch--verbose:
1461 file_copies_switch--verbose:
1462 file_copies_switch--verbose:
1462 file_copies_switch--verbose:
1463 file_copies_switch--verbose:
1463 file_copies_switch--verbose:
1464 file_copies_switch--verbose:
1464 file_copies_switch--verbose:
1465 file_copies_switch--verbose:
1465 file_copies_switch--verbose:
1466 file_copies_switch--verbose:
1466 file_copies_switch--verbose:
1467 file_copies_switch--verbose:
1467 file_copies_switch--verbose:
1468 file_copies_switch--debug:
1468 file_copies_switch--debug:
1469 file_copies_switch--debug:
1469 file_copies_switch--debug:
1470 file_copies_switch--debug:
1470 file_copies_switch--debug:
1471 file_copies_switch--debug:
1471 file_copies_switch--debug:
1472 file_copies_switch--debug:
1472 file_copies_switch--debug:
1473 file_copies_switch--debug:
1473 file_copies_switch--debug:
1474 file_copies_switch--debug:
1474 file_copies_switch--debug:
1475 file_copies_switch--debug:
1475 file_copies_switch--debug:
1476 file_copies_switch--debug:
1476 file_copies_switch--debug:
1477 files: fourth second third
1477 files: fourth second third
1478 files: second
1478 files: second
1479 files:
1479 files:
1480 files: d
1480 files: d
1481 files:
1481 files:
1482 files: c
1482 files: c
1483 files: c
1483 files: c
1484 files: b
1484 files: b
1485 files: a
1485 files: a
1486 files--verbose: fourth second third
1486 files--verbose: fourth second third
1487 files--verbose: second
1487 files--verbose: second
1488 files--verbose:
1488 files--verbose:
1489 files--verbose: d
1489 files--verbose: d
1490 files--verbose:
1490 files--verbose:
1491 files--verbose: c
1491 files--verbose: c
1492 files--verbose: c
1492 files--verbose: c
1493 files--verbose: b
1493 files--verbose: b
1494 files--verbose: a
1494 files--verbose: a
1495 files--debug: fourth second third
1495 files--debug: fourth second third
1496 files--debug: second
1496 files--debug: second
1497 files--debug:
1497 files--debug:
1498 files--debug: d
1498 files--debug: d
1499 files--debug:
1499 files--debug:
1500 files--debug: c
1500 files--debug: c
1501 files--debug: c
1501 files--debug: c
1502 files--debug: b
1502 files--debug: b
1503 files--debug: a
1503 files--debug: a
1504 manifest: 6:94961b75a2da
1504 manifest: 6:94961b75a2da
1505 manifest: 5:f2dbc354b94e
1505 manifest: 5:f2dbc354b94e
1506 manifest: 4:4dc3def4f9b4
1506 manifest: 4:4dc3def4f9b4
1507 manifest: 4:4dc3def4f9b4
1507 manifest: 4:4dc3def4f9b4
1508 manifest: 3:cb5a1327723b
1508 manifest: 3:cb5a1327723b
1509 manifest: 3:cb5a1327723b
1509 manifest: 3:cb5a1327723b
1510 manifest: 2:6e0e82995c35
1510 manifest: 2:6e0e82995c35
1511 manifest: 1:4e8d705b1e53
1511 manifest: 1:4e8d705b1e53
1512 manifest: 0:a0c8bcbbb45c
1512 manifest: 0:a0c8bcbbb45c
1513 manifest--verbose: 6:94961b75a2da
1513 manifest--verbose: 6:94961b75a2da
1514 manifest--verbose: 5:f2dbc354b94e
1514 manifest--verbose: 5:f2dbc354b94e
1515 manifest--verbose: 4:4dc3def4f9b4
1515 manifest--verbose: 4:4dc3def4f9b4
1516 manifest--verbose: 4:4dc3def4f9b4
1516 manifest--verbose: 4:4dc3def4f9b4
1517 manifest--verbose: 3:cb5a1327723b
1517 manifest--verbose: 3:cb5a1327723b
1518 manifest--verbose: 3:cb5a1327723b
1518 manifest--verbose: 3:cb5a1327723b
1519 manifest--verbose: 2:6e0e82995c35
1519 manifest--verbose: 2:6e0e82995c35
1520 manifest--verbose: 1:4e8d705b1e53
1520 manifest--verbose: 1:4e8d705b1e53
1521 manifest--verbose: 0:a0c8bcbbb45c
1521 manifest--verbose: 0:a0c8bcbbb45c
1522 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1522 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1523 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1523 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1524 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1524 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1525 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1525 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1526 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1526 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1527 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1527 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1528 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1528 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1529 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1529 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1530 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1530 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1531 node: 95c24699272ef57d062b8bccc32c878bf841784a
1531 node: 95c24699272ef57d062b8bccc32c878bf841784a
1532 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1532 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1533 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1533 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1534 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1534 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1535 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1535 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1536 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1536 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1537 node: 97054abb4ab824450e9164180baf491ae0078465
1537 node: 97054abb4ab824450e9164180baf491ae0078465
1538 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1538 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1539 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1539 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1540 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1540 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1541 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1541 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1542 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1542 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1543 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1543 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1544 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1544 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1545 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1545 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1546 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1546 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1547 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1547 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1548 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1548 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1549 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1549 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1550 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1550 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1551 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1551 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1552 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1552 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1553 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1553 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1554 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1554 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1555 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1555 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1556 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1556 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1557 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1557 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1558 parents:
1558 parents:
1559 parents: -1:000000000000
1559 parents: -1:000000000000
1560 parents: 5:13207e5a10d9 4:bbe44766e73d
1560 parents: 5:13207e5a10d9 4:bbe44766e73d
1561 parents: 3:10e46f2dcbf4
1561 parents: 3:10e46f2dcbf4
1562 parents:
1562 parents:
1563 parents:
1563 parents:
1564 parents:
1564 parents:
1565 parents:
1565 parents:
1566 parents:
1566 parents:
1567 parents--verbose:
1567 parents--verbose:
1568 parents--verbose: -1:000000000000
1568 parents--verbose: -1:000000000000
1569 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1569 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1570 parents--verbose: 3:10e46f2dcbf4
1570 parents--verbose: 3:10e46f2dcbf4
1571 parents--verbose:
1571 parents--verbose:
1572 parents--verbose:
1572 parents--verbose:
1573 parents--verbose:
1573 parents--verbose:
1574 parents--verbose:
1574 parents--verbose:
1575 parents--verbose:
1575 parents--verbose:
1576 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1576 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1577 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1577 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1578 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1578 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1579 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1579 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1580 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1580 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1581 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1581 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1582 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1582 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1583 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1583 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1584 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1584 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1585 rev: 8
1585 rev: 8
1586 rev: 7
1586 rev: 7
1587 rev: 6
1587 rev: 6
1588 rev: 5
1588 rev: 5
1589 rev: 4
1589 rev: 4
1590 rev: 3
1590 rev: 3
1591 rev: 2
1591 rev: 2
1592 rev: 1
1592 rev: 1
1593 rev: 0
1593 rev: 0
1594 rev--verbose: 8
1594 rev--verbose: 8
1595 rev--verbose: 7
1595 rev--verbose: 7
1596 rev--verbose: 6
1596 rev--verbose: 6
1597 rev--verbose: 5
1597 rev--verbose: 5
1598 rev--verbose: 4
1598 rev--verbose: 4
1599 rev--verbose: 3
1599 rev--verbose: 3
1600 rev--verbose: 2
1600 rev--verbose: 2
1601 rev--verbose: 1
1601 rev--verbose: 1
1602 rev--verbose: 0
1602 rev--verbose: 0
1603 rev--debug: 8
1603 rev--debug: 8
1604 rev--debug: 7
1604 rev--debug: 7
1605 rev--debug: 6
1605 rev--debug: 6
1606 rev--debug: 5
1606 rev--debug: 5
1607 rev--debug: 4
1607 rev--debug: 4
1608 rev--debug: 3
1608 rev--debug: 3
1609 rev--debug: 2
1609 rev--debug: 2
1610 rev--debug: 1
1610 rev--debug: 1
1611 rev--debug: 0
1611 rev--debug: 0
1612 tags: tip
1612 tags: tip
1613 tags:
1613 tags:
1614 tags:
1614 tags:
1615 tags:
1615 tags:
1616 tags:
1616 tags:
1617 tags:
1617 tags:
1618 tags:
1618 tags:
1619 tags:
1619 tags:
1620 tags:
1620 tags:
1621 tags--verbose: tip
1621 tags--verbose: tip
1622 tags--verbose:
1622 tags--verbose:
1623 tags--verbose:
1623 tags--verbose:
1624 tags--verbose:
1624 tags--verbose:
1625 tags--verbose:
1625 tags--verbose:
1626 tags--verbose:
1626 tags--verbose:
1627 tags--verbose:
1627 tags--verbose:
1628 tags--verbose:
1628 tags--verbose:
1629 tags--verbose:
1629 tags--verbose:
1630 tags--debug: tip
1630 tags--debug: tip
1631 tags--debug:
1631 tags--debug:
1632 tags--debug:
1632 tags--debug:
1633 tags--debug:
1633 tags--debug:
1634 tags--debug:
1634 tags--debug:
1635 tags--debug:
1635 tags--debug:
1636 tags--debug:
1636 tags--debug:
1637 tags--debug:
1637 tags--debug:
1638 tags--debug:
1638 tags--debug:
1639 diffstat: 3: +2/-1
1639 diffstat: 3: +2/-1
1640 diffstat: 1: +1/-0
1640 diffstat: 1: +1/-0
1641 diffstat: 0: +0/-0
1641 diffstat: 0: +0/-0
1642 diffstat: 1: +1/-0
1642 diffstat: 1: +1/-0
1643 diffstat: 0: +0/-0
1643 diffstat: 0: +0/-0
1644 diffstat: 1: +1/-0
1644 diffstat: 1: +1/-0
1645 diffstat: 1: +4/-0
1645 diffstat: 1: +4/-0
1646 diffstat: 1: +2/-0
1646 diffstat: 1: +2/-0
1647 diffstat: 1: +1/-0
1647 diffstat: 1: +1/-0
1648 diffstat--verbose: 3: +2/-1
1648 diffstat--verbose: 3: +2/-1
1649 diffstat--verbose: 1: +1/-0
1649 diffstat--verbose: 1: +1/-0
1650 diffstat--verbose: 0: +0/-0
1650 diffstat--verbose: 0: +0/-0
1651 diffstat--verbose: 1: +1/-0
1651 diffstat--verbose: 1: +1/-0
1652 diffstat--verbose: 0: +0/-0
1652 diffstat--verbose: 0: +0/-0
1653 diffstat--verbose: 1: +1/-0
1653 diffstat--verbose: 1: +1/-0
1654 diffstat--verbose: 1: +4/-0
1654 diffstat--verbose: 1: +4/-0
1655 diffstat--verbose: 1: +2/-0
1655 diffstat--verbose: 1: +2/-0
1656 diffstat--verbose: 1: +1/-0
1656 diffstat--verbose: 1: +1/-0
1657 diffstat--debug: 3: +2/-1
1657 diffstat--debug: 3: +2/-1
1658 diffstat--debug: 1: +1/-0
1658 diffstat--debug: 1: +1/-0
1659 diffstat--debug: 0: +0/-0
1659 diffstat--debug: 0: +0/-0
1660 diffstat--debug: 1: +1/-0
1660 diffstat--debug: 1: +1/-0
1661 diffstat--debug: 0: +0/-0
1661 diffstat--debug: 0: +0/-0
1662 diffstat--debug: 1: +1/-0
1662 diffstat--debug: 1: +1/-0
1663 diffstat--debug: 1: +4/-0
1663 diffstat--debug: 1: +4/-0
1664 diffstat--debug: 1: +2/-0
1664 diffstat--debug: 1: +2/-0
1665 diffstat--debug: 1: +1/-0
1665 diffstat--debug: 1: +1/-0
1666 extras: branch=default
1666 extras: branch=default
1667 extras: branch=default
1667 extras: branch=default
1668 extras: branch=default
1668 extras: branch=default
1669 extras: branch=default
1669 extras: branch=default
1670 extras: branch=foo
1670 extras: branch=foo
1671 extras: branch=default
1671 extras: branch=default
1672 extras: branch=default
1672 extras: branch=default
1673 extras: branch=default
1673 extras: branch=default
1674 extras: branch=default
1674 extras: branch=default
1675 extras--verbose: branch=default
1675 extras--verbose: branch=default
1676 extras--verbose: branch=default
1676 extras--verbose: branch=default
1677 extras--verbose: branch=default
1677 extras--verbose: branch=default
1678 extras--verbose: branch=default
1678 extras--verbose: branch=default
1679 extras--verbose: branch=foo
1679 extras--verbose: branch=foo
1680 extras--verbose: branch=default
1680 extras--verbose: branch=default
1681 extras--verbose: branch=default
1681 extras--verbose: branch=default
1682 extras--verbose: branch=default
1682 extras--verbose: branch=default
1683 extras--verbose: branch=default
1683 extras--verbose: branch=default
1684 extras--debug: branch=default
1684 extras--debug: branch=default
1685 extras--debug: branch=default
1685 extras--debug: branch=default
1686 extras--debug: branch=default
1686 extras--debug: branch=default
1687 extras--debug: branch=default
1687 extras--debug: branch=default
1688 extras--debug: branch=foo
1688 extras--debug: branch=foo
1689 extras--debug: branch=default
1689 extras--debug: branch=default
1690 extras--debug: branch=default
1690 extras--debug: branch=default
1691 extras--debug: branch=default
1691 extras--debug: branch=default
1692 extras--debug: branch=default
1692 extras--debug: branch=default
1693 p1rev: 7
1693 p1rev: 7
1694 p1rev: -1
1694 p1rev: -1
1695 p1rev: 5
1695 p1rev: 5
1696 p1rev: 3
1696 p1rev: 3
1697 p1rev: 3
1697 p1rev: 3
1698 p1rev: 2
1698 p1rev: 2
1699 p1rev: 1
1699 p1rev: 1
1700 p1rev: 0
1700 p1rev: 0
1701 p1rev: -1
1701 p1rev: -1
1702 p1rev--verbose: 7
1702 p1rev--verbose: 7
1703 p1rev--verbose: -1
1703 p1rev--verbose: -1
1704 p1rev--verbose: 5
1704 p1rev--verbose: 5
1705 p1rev--verbose: 3
1705 p1rev--verbose: 3
1706 p1rev--verbose: 3
1706 p1rev--verbose: 3
1707 p1rev--verbose: 2
1707 p1rev--verbose: 2
1708 p1rev--verbose: 1
1708 p1rev--verbose: 1
1709 p1rev--verbose: 0
1709 p1rev--verbose: 0
1710 p1rev--verbose: -1
1710 p1rev--verbose: -1
1711 p1rev--debug: 7
1711 p1rev--debug: 7
1712 p1rev--debug: -1
1712 p1rev--debug: -1
1713 p1rev--debug: 5
1713 p1rev--debug: 5
1714 p1rev--debug: 3
1714 p1rev--debug: 3
1715 p1rev--debug: 3
1715 p1rev--debug: 3
1716 p1rev--debug: 2
1716 p1rev--debug: 2
1717 p1rev--debug: 1
1717 p1rev--debug: 1
1718 p1rev--debug: 0
1718 p1rev--debug: 0
1719 p1rev--debug: -1
1719 p1rev--debug: -1
1720 p2rev: -1
1720 p2rev: -1
1721 p2rev: -1
1721 p2rev: -1
1722 p2rev: 4
1722 p2rev: 4
1723 p2rev: -1
1723 p2rev: -1
1724 p2rev: -1
1724 p2rev: -1
1725 p2rev: -1
1725 p2rev: -1
1726 p2rev: -1
1726 p2rev: -1
1727 p2rev: -1
1727 p2rev: -1
1728 p2rev: -1
1728 p2rev: -1
1729 p2rev--verbose: -1
1729 p2rev--verbose: -1
1730 p2rev--verbose: -1
1730 p2rev--verbose: -1
1731 p2rev--verbose: 4
1731 p2rev--verbose: 4
1732 p2rev--verbose: -1
1732 p2rev--verbose: -1
1733 p2rev--verbose: -1
1733 p2rev--verbose: -1
1734 p2rev--verbose: -1
1734 p2rev--verbose: -1
1735 p2rev--verbose: -1
1735 p2rev--verbose: -1
1736 p2rev--verbose: -1
1736 p2rev--verbose: -1
1737 p2rev--verbose: -1
1737 p2rev--verbose: -1
1738 p2rev--debug: -1
1738 p2rev--debug: -1
1739 p2rev--debug: -1
1739 p2rev--debug: -1
1740 p2rev--debug: 4
1740 p2rev--debug: 4
1741 p2rev--debug: -1
1741 p2rev--debug: -1
1742 p2rev--debug: -1
1742 p2rev--debug: -1
1743 p2rev--debug: -1
1743 p2rev--debug: -1
1744 p2rev--debug: -1
1744 p2rev--debug: -1
1745 p2rev--debug: -1
1745 p2rev--debug: -1
1746 p2rev--debug: -1
1746 p2rev--debug: -1
1747 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1747 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1748 p1node: 0000000000000000000000000000000000000000
1748 p1node: 0000000000000000000000000000000000000000
1749 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1749 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1750 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1750 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1751 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1751 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1752 p1node: 97054abb4ab824450e9164180baf491ae0078465
1752 p1node: 97054abb4ab824450e9164180baf491ae0078465
1753 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1753 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1754 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1754 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1755 p1node: 0000000000000000000000000000000000000000
1755 p1node: 0000000000000000000000000000000000000000
1756 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1756 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1757 p1node--verbose: 0000000000000000000000000000000000000000
1757 p1node--verbose: 0000000000000000000000000000000000000000
1758 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1758 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1759 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1759 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1760 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1760 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1761 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1761 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1762 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1762 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1763 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1763 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1764 p1node--verbose: 0000000000000000000000000000000000000000
1764 p1node--verbose: 0000000000000000000000000000000000000000
1765 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1765 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1766 p1node--debug: 0000000000000000000000000000000000000000
1766 p1node--debug: 0000000000000000000000000000000000000000
1767 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1767 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1768 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1768 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1769 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1769 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1770 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1770 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1771 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1771 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1772 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1772 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1773 p1node--debug: 0000000000000000000000000000000000000000
1773 p1node--debug: 0000000000000000000000000000000000000000
1774 p2node: 0000000000000000000000000000000000000000
1774 p2node: 0000000000000000000000000000000000000000
1775 p2node: 0000000000000000000000000000000000000000
1775 p2node: 0000000000000000000000000000000000000000
1776 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1776 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1777 p2node: 0000000000000000000000000000000000000000
1777 p2node: 0000000000000000000000000000000000000000
1778 p2node: 0000000000000000000000000000000000000000
1778 p2node: 0000000000000000000000000000000000000000
1779 p2node: 0000000000000000000000000000000000000000
1779 p2node: 0000000000000000000000000000000000000000
1780 p2node: 0000000000000000000000000000000000000000
1780 p2node: 0000000000000000000000000000000000000000
1781 p2node: 0000000000000000000000000000000000000000
1781 p2node: 0000000000000000000000000000000000000000
1782 p2node: 0000000000000000000000000000000000000000
1782 p2node: 0000000000000000000000000000000000000000
1783 p2node--verbose: 0000000000000000000000000000000000000000
1783 p2node--verbose: 0000000000000000000000000000000000000000
1784 p2node--verbose: 0000000000000000000000000000000000000000
1784 p2node--verbose: 0000000000000000000000000000000000000000
1785 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1785 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1786 p2node--verbose: 0000000000000000000000000000000000000000
1786 p2node--verbose: 0000000000000000000000000000000000000000
1787 p2node--verbose: 0000000000000000000000000000000000000000
1787 p2node--verbose: 0000000000000000000000000000000000000000
1788 p2node--verbose: 0000000000000000000000000000000000000000
1788 p2node--verbose: 0000000000000000000000000000000000000000
1789 p2node--verbose: 0000000000000000000000000000000000000000
1789 p2node--verbose: 0000000000000000000000000000000000000000
1790 p2node--verbose: 0000000000000000000000000000000000000000
1790 p2node--verbose: 0000000000000000000000000000000000000000
1791 p2node--verbose: 0000000000000000000000000000000000000000
1791 p2node--verbose: 0000000000000000000000000000000000000000
1792 p2node--debug: 0000000000000000000000000000000000000000
1792 p2node--debug: 0000000000000000000000000000000000000000
1793 p2node--debug: 0000000000000000000000000000000000000000
1793 p2node--debug: 0000000000000000000000000000000000000000
1794 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1794 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1795 p2node--debug: 0000000000000000000000000000000000000000
1795 p2node--debug: 0000000000000000000000000000000000000000
1796 p2node--debug: 0000000000000000000000000000000000000000
1796 p2node--debug: 0000000000000000000000000000000000000000
1797 p2node--debug: 0000000000000000000000000000000000000000
1797 p2node--debug: 0000000000000000000000000000000000000000
1798 p2node--debug: 0000000000000000000000000000000000000000
1798 p2node--debug: 0000000000000000000000000000000000000000
1799 p2node--debug: 0000000000000000000000000000000000000000
1799 p2node--debug: 0000000000000000000000000000000000000000
1800 p2node--debug: 0000000000000000000000000000000000000000
1800 p2node--debug: 0000000000000000000000000000000000000000
1801
1801
1802 Filters work:
1802 Filters work:
1803
1803
1804 $ hg log --template '{author|domain}\n'
1804 $ hg log --template '{author|domain}\n'
1805
1805
1806 hostname
1806 hostname
1807
1807
1808
1808
1809
1809
1810
1810
1811 place
1811 place
1812 place
1812 place
1813 hostname
1813 hostname
1814
1814
1815 $ hg log --template '{author|person}\n'
1815 $ hg log --template '{author|person}\n'
1816 test
1816 test
1817 User Name
1817 User Name
1818 person
1818 person
1819 person
1819 person
1820 person
1820 person
1821 person
1821 person
1822 other
1822 other
1823 A. N. Other
1823 A. N. Other
1824 User Name
1824 User Name
1825
1825
1826 $ hg log --template '{author|user}\n'
1826 $ hg log --template '{author|user}\n'
1827 test
1827 test
1828 user
1828 user
1829 person
1829 person
1830 person
1830 person
1831 person
1831 person
1832 person
1832 person
1833 other
1833 other
1834 other
1834 other
1835 user
1835 user
1836
1836
1837 $ hg log --template '{date|date}\n'
1837 $ hg log --template '{date|date}\n'
1838 Wed Jan 01 10:01:00 2020 +0000
1838 Wed Jan 01 10:01:00 2020 +0000
1839 Mon Jan 12 13:46:40 1970 +0000
1839 Mon Jan 12 13:46:40 1970 +0000
1840 Sun Jan 18 08:40:01 1970 +0000
1840 Sun Jan 18 08:40:01 1970 +0000
1841 Sun Jan 18 08:40:00 1970 +0000
1841 Sun Jan 18 08:40:00 1970 +0000
1842 Sat Jan 17 04:53:20 1970 +0000
1842 Sat Jan 17 04:53:20 1970 +0000
1843 Fri Jan 16 01:06:40 1970 +0000
1843 Fri Jan 16 01:06:40 1970 +0000
1844 Wed Jan 14 21:20:00 1970 +0000
1844 Wed Jan 14 21:20:00 1970 +0000
1845 Tue Jan 13 17:33:20 1970 +0000
1845 Tue Jan 13 17:33:20 1970 +0000
1846 Mon Jan 12 13:46:40 1970 +0000
1846 Mon Jan 12 13:46:40 1970 +0000
1847
1847
1848 $ hg log --template '{date|isodate}\n'
1848 $ hg log --template '{date|isodate}\n'
1849 2020-01-01 10:01 +0000
1849 2020-01-01 10:01 +0000
1850 1970-01-12 13:46 +0000
1850 1970-01-12 13:46 +0000
1851 1970-01-18 08:40 +0000
1851 1970-01-18 08:40 +0000
1852 1970-01-18 08:40 +0000
1852 1970-01-18 08:40 +0000
1853 1970-01-17 04:53 +0000
1853 1970-01-17 04:53 +0000
1854 1970-01-16 01:06 +0000
1854 1970-01-16 01:06 +0000
1855 1970-01-14 21:20 +0000
1855 1970-01-14 21:20 +0000
1856 1970-01-13 17:33 +0000
1856 1970-01-13 17:33 +0000
1857 1970-01-12 13:46 +0000
1857 1970-01-12 13:46 +0000
1858
1858
1859 $ hg log --template '{date|isodatesec}\n'
1859 $ hg log --template '{date|isodatesec}\n'
1860 2020-01-01 10:01:00 +0000
1860 2020-01-01 10:01:00 +0000
1861 1970-01-12 13:46:40 +0000
1861 1970-01-12 13:46:40 +0000
1862 1970-01-18 08:40:01 +0000
1862 1970-01-18 08:40:01 +0000
1863 1970-01-18 08:40:00 +0000
1863 1970-01-18 08:40:00 +0000
1864 1970-01-17 04:53:20 +0000
1864 1970-01-17 04:53:20 +0000
1865 1970-01-16 01:06:40 +0000
1865 1970-01-16 01:06:40 +0000
1866 1970-01-14 21:20:00 +0000
1866 1970-01-14 21:20:00 +0000
1867 1970-01-13 17:33:20 +0000
1867 1970-01-13 17:33:20 +0000
1868 1970-01-12 13:46:40 +0000
1868 1970-01-12 13:46:40 +0000
1869
1869
1870 $ hg log --template '{date|rfc822date}\n'
1870 $ hg log --template '{date|rfc822date}\n'
1871 Wed, 01 Jan 2020 10:01:00 +0000
1871 Wed, 01 Jan 2020 10:01:00 +0000
1872 Mon, 12 Jan 1970 13:46:40 +0000
1872 Mon, 12 Jan 1970 13:46:40 +0000
1873 Sun, 18 Jan 1970 08:40:01 +0000
1873 Sun, 18 Jan 1970 08:40:01 +0000
1874 Sun, 18 Jan 1970 08:40:00 +0000
1874 Sun, 18 Jan 1970 08:40:00 +0000
1875 Sat, 17 Jan 1970 04:53:20 +0000
1875 Sat, 17 Jan 1970 04:53:20 +0000
1876 Fri, 16 Jan 1970 01:06:40 +0000
1876 Fri, 16 Jan 1970 01:06:40 +0000
1877 Wed, 14 Jan 1970 21:20:00 +0000
1877 Wed, 14 Jan 1970 21:20:00 +0000
1878 Tue, 13 Jan 1970 17:33:20 +0000
1878 Tue, 13 Jan 1970 17:33:20 +0000
1879 Mon, 12 Jan 1970 13:46:40 +0000
1879 Mon, 12 Jan 1970 13:46:40 +0000
1880
1880
1881 $ hg log --template '{desc|firstline}\n'
1881 $ hg log --template '{desc|firstline}\n'
1882 third
1882 third
1883 second
1883 second
1884 merge
1884 merge
1885 new head
1885 new head
1886 new branch
1886 new branch
1887 no user, no domain
1887 no user, no domain
1888 no person
1888 no person
1889 other 1
1889 other 1
1890 line 1
1890 line 1
1891
1891
1892 $ hg log --template '{node|short}\n'
1892 $ hg log --template '{node|short}\n'
1893 95c24699272e
1893 95c24699272e
1894 29114dbae42b
1894 29114dbae42b
1895 d41e714fe50d
1895 d41e714fe50d
1896 13207e5a10d9
1896 13207e5a10d9
1897 bbe44766e73d
1897 bbe44766e73d
1898 10e46f2dcbf4
1898 10e46f2dcbf4
1899 97054abb4ab8
1899 97054abb4ab8
1900 b608e9d1a3f0
1900 b608e9d1a3f0
1901 1e4e1b8f71e0
1901 1e4e1b8f71e0
1902
1902
1903 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1903 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1904 <changeset author="test"/>
1904 <changeset author="test"/>
1905 <changeset author="User Name &lt;user@hostname&gt;"/>
1905 <changeset author="User Name &lt;user@hostname&gt;"/>
1906 <changeset author="person"/>
1906 <changeset author="person"/>
1907 <changeset author="person"/>
1907 <changeset author="person"/>
1908 <changeset author="person"/>
1908 <changeset author="person"/>
1909 <changeset author="person"/>
1909 <changeset author="person"/>
1910 <changeset author="other@place"/>
1910 <changeset author="other@place"/>
1911 <changeset author="A. N. Other &lt;other@place&gt;"/>
1911 <changeset author="A. N. Other &lt;other@place&gt;"/>
1912 <changeset author="User Name &lt;user@hostname&gt;"/>
1912 <changeset author="User Name &lt;user@hostname&gt;"/>
1913
1913
1914 $ hg log --template '{rev}: {children}\n'
1914 $ hg log --template '{rev}: {children}\n'
1915 8:
1915 8:
1916 7: 8:95c24699272e
1916 7: 8:95c24699272e
1917 6:
1917 6:
1918 5: 6:d41e714fe50d
1918 5: 6:d41e714fe50d
1919 4: 6:d41e714fe50d
1919 4: 6:d41e714fe50d
1920 3: 4:bbe44766e73d 5:13207e5a10d9
1920 3: 4:bbe44766e73d 5:13207e5a10d9
1921 2: 3:10e46f2dcbf4
1921 2: 3:10e46f2dcbf4
1922 1: 2:97054abb4ab8
1922 1: 2:97054abb4ab8
1923 0: 1:b608e9d1a3f0
1923 0: 1:b608e9d1a3f0
1924
1924
1925 Formatnode filter works:
1925 Formatnode filter works:
1926
1926
1927 $ hg -q log -r 0 --template '{node|formatnode}\n'
1927 $ hg -q log -r 0 --template '{node|formatnode}\n'
1928 1e4e1b8f71e0
1928 1e4e1b8f71e0
1929
1929
1930 $ hg log -r 0 --template '{node|formatnode}\n'
1930 $ hg log -r 0 --template '{node|formatnode}\n'
1931 1e4e1b8f71e0
1931 1e4e1b8f71e0
1932
1932
1933 $ hg -v log -r 0 --template '{node|formatnode}\n'
1933 $ hg -v log -r 0 --template '{node|formatnode}\n'
1934 1e4e1b8f71e0
1934 1e4e1b8f71e0
1935
1935
1936 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1936 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1937 1e4e1b8f71e05681d422154f5421e385fec3454f
1937 1e4e1b8f71e05681d422154f5421e385fec3454f
1938
1938
1939 Age filter:
1939 Age filter:
1940
1940
1941 $ hg init unstable-hash
1941 $ hg init unstable-hash
1942 $ cd unstable-hash
1942 $ cd unstable-hash
1943 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1943 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1944
1944
1945 >>> from datetime import datetime, timedelta
1945 >>> from datetime import datetime, timedelta
1946 >>> fp = open('a', 'w')
1946 >>> fp = open('a', 'w')
1947 >>> n = datetime.now() + timedelta(366 * 7)
1947 >>> n = datetime.now() + timedelta(366 * 7)
1948 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1948 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1949 >>> fp.close()
1949 >>> fp.close()
1950 $ hg add a
1950 $ hg add a
1951 $ hg commit -m future -d "`cat a`"
1951 $ hg commit -m future -d "`cat a`"
1952
1952
1953 $ hg log -l1 --template '{date|age}\n'
1953 $ hg log -l1 --template '{date|age}\n'
1954 7 years from now
1954 7 years from now
1955
1955
1956 $ cd ..
1956 $ cd ..
1957 $ rm -rf unstable-hash
1957 $ rm -rf unstable-hash
1958
1958
1959 Add a dummy commit to make up for the instability of the above:
1959 Add a dummy commit to make up for the instability of the above:
1960
1960
1961 $ echo a > a
1961 $ echo a > a
1962 $ hg add a
1962 $ hg add a
1963 $ hg ci -m future
1963 $ hg ci -m future
1964
1964
1965 Count filter:
1965 Count filter:
1966
1966
1967 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1967 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1968 40 12
1968 40 12
1969
1969
1970 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1970 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1971 0 1 4
1971 0 1 4
1972
1972
1973 $ hg log -G --template '{rev}: children: {children|count}, \
1973 $ hg log -G --template '{rev}: children: {children|count}, \
1974 > tags: {tags|count}, file_adds: {file_adds|count}, \
1974 > tags: {tags|count}, file_adds: {file_adds|count}, \
1975 > ancestors: {revset("ancestors(%s)", rev)|count}'
1975 > ancestors: {revset("ancestors(%s)", rev)|count}'
1976 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1976 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1977 |
1977 |
1978 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1978 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1979 |
1979 |
1980 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1980 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1981
1981
1982 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1982 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1983 |\
1983 |\
1984 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1984 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1985 | |
1985 | |
1986 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1986 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1987 |/
1987 |/
1988 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1988 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1989 |
1989 |
1990 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1990 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1991 |
1991 |
1992 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1992 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1993 |
1993 |
1994 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1994 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1995
1995
1996
1996
1997 Upper/lower filters:
1997 Upper/lower filters:
1998
1998
1999 $ hg log -r0 --template '{branch|upper}\n'
1999 $ hg log -r0 --template '{branch|upper}\n'
2000 DEFAULT
2000 DEFAULT
2001 $ hg log -r0 --template '{author|lower}\n'
2001 $ hg log -r0 --template '{author|lower}\n'
2002 user name <user@hostname>
2002 user name <user@hostname>
2003 $ hg log -r0 --template '{date|upper}\n'
2003 $ hg log -r0 --template '{date|upper}\n'
2004 abort: template filter 'upper' is not compatible with keyword 'date'
2004 abort: template filter 'upper' is not compatible with keyword 'date'
2005 [255]
2005 [255]
2006
2006
2007 Add a commit that does all possible modifications at once
2007 Add a commit that does all possible modifications at once
2008
2008
2009 $ echo modify >> third
2009 $ echo modify >> third
2010 $ touch b
2010 $ touch b
2011 $ hg add b
2011 $ hg add b
2012 $ hg mv fourth fifth
2012 $ hg mv fourth fifth
2013 $ hg rm a
2013 $ hg rm a
2014 $ hg ci -m "Modify, add, remove, rename"
2014 $ hg ci -m "Modify, add, remove, rename"
2015
2015
2016 Check the status template
2016 Check the status template
2017
2017
2018 $ cat <<EOF >> $HGRCPATH
2018 $ cat <<EOF >> $HGRCPATH
2019 > [extensions]
2019 > [extensions]
2020 > color=
2020 > color=
2021 > EOF
2021 > EOF
2022
2022
2023 $ hg log -T status -r 10
2023 $ hg log -T status -r 10
2024 changeset: 10:0f9759ec227a
2024 changeset: 10:0f9759ec227a
2025 tag: tip
2025 tag: tip
2026 user: test
2026 user: test
2027 date: Thu Jan 01 00:00:00 1970 +0000
2027 date: Thu Jan 01 00:00:00 1970 +0000
2028 summary: Modify, add, remove, rename
2028 summary: Modify, add, remove, rename
2029 files:
2029 files:
2030 M third
2030 M third
2031 A b
2031 A b
2032 A fifth
2032 A fifth
2033 R a
2033 R a
2034 R fourth
2034 R fourth
2035
2035
2036 $ hg log -T status -C -r 10
2036 $ hg log -T status -C -r 10
2037 changeset: 10:0f9759ec227a
2037 changeset: 10:0f9759ec227a
2038 tag: tip
2038 tag: tip
2039 user: test
2039 user: test
2040 date: Thu Jan 01 00:00:00 1970 +0000
2040 date: Thu Jan 01 00:00:00 1970 +0000
2041 summary: Modify, add, remove, rename
2041 summary: Modify, add, remove, rename
2042 files:
2042 files:
2043 M third
2043 M third
2044 A b
2044 A b
2045 A fifth
2045 A fifth
2046 fourth
2046 fourth
2047 R a
2047 R a
2048 R fourth
2048 R fourth
2049
2049
2050 $ hg log -T status -C -r 10 -v
2050 $ hg log -T status -C -r 10 -v
2051 changeset: 10:0f9759ec227a
2051 changeset: 10:0f9759ec227a
2052 tag: tip
2052 tag: tip
2053 user: test
2053 user: test
2054 date: Thu Jan 01 00:00:00 1970 +0000
2054 date: Thu Jan 01 00:00:00 1970 +0000
2055 description:
2055 description:
2056 Modify, add, remove, rename
2056 Modify, add, remove, rename
2057
2057
2058 files:
2058 files:
2059 M third
2059 M third
2060 A b
2060 A b
2061 A fifth
2061 A fifth
2062 fourth
2062 fourth
2063 R a
2063 R a
2064 R fourth
2064 R fourth
2065
2065
2066 $ hg log -T status -C -r 10 --debug
2066 $ hg log -T status -C -r 10 --debug
2067 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2067 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2068 tag: tip
2068 tag: tip
2069 phase: secret
2069 phase: secret
2070 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2070 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2071 parent: -1:0000000000000000000000000000000000000000
2071 parent: -1:0000000000000000000000000000000000000000
2072 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2072 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2073 user: test
2073 user: test
2074 date: Thu Jan 01 00:00:00 1970 +0000
2074 date: Thu Jan 01 00:00:00 1970 +0000
2075 extra: branch=default
2075 extra: branch=default
2076 description:
2076 description:
2077 Modify, add, remove, rename
2077 Modify, add, remove, rename
2078
2078
2079 files:
2079 files:
2080 M third
2080 M third
2081 A b
2081 A b
2082 A fifth
2082 A fifth
2083 fourth
2083 fourth
2084 R a
2084 R a
2085 R fourth
2085 R fourth
2086
2086
2087 $ hg log -T status -C -r 10 --quiet
2087 $ hg log -T status -C -r 10 --quiet
2088 10:0f9759ec227a
2088 10:0f9759ec227a
2089 $ hg --color=debug log -T status -r 10
2089 $ hg --color=debug log -T status -r 10
2090 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2090 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2091 [log.tag|tag: tip]
2091 [log.tag|tag: tip]
2092 [log.user|user: test]
2092 [log.user|user: test]
2093 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2093 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2094 [log.summary|summary: Modify, add, remove, rename]
2094 [log.summary|summary: Modify, add, remove, rename]
2095 [ui.note log.files|files:]
2095 [ui.note log.files|files:]
2096 [status.modified|M third]
2096 [status.modified|M third]
2097 [status.added|A b]
2097 [status.added|A b]
2098 [status.added|A fifth]
2098 [status.added|A fifth]
2099 [status.removed|R a]
2099 [status.removed|R a]
2100 [status.removed|R fourth]
2100 [status.removed|R fourth]
2101
2101
2102 $ hg --color=debug log -T status -C -r 10
2102 $ hg --color=debug log -T status -C -r 10
2103 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2103 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2104 [log.tag|tag: tip]
2104 [log.tag|tag: tip]
2105 [log.user|user: test]
2105 [log.user|user: test]
2106 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2106 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2107 [log.summary|summary: Modify, add, remove, rename]
2107 [log.summary|summary: Modify, add, remove, rename]
2108 [ui.note log.files|files:]
2108 [ui.note log.files|files:]
2109 [status.modified|M third]
2109 [status.modified|M third]
2110 [status.added|A b]
2110 [status.added|A b]
2111 [status.added|A fifth]
2111 [status.added|A fifth]
2112 [status.copied| fourth]
2112 [status.copied| fourth]
2113 [status.removed|R a]
2113 [status.removed|R a]
2114 [status.removed|R fourth]
2114 [status.removed|R fourth]
2115
2115
2116 $ hg --color=debug log -T status -C -r 10 -v
2116 $ hg --color=debug log -T status -C -r 10 -v
2117 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2117 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2118 [log.tag|tag: tip]
2118 [log.tag|tag: tip]
2119 [log.user|user: test]
2119 [log.user|user: test]
2120 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2120 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2121 [ui.note log.description|description:]
2121 [ui.note log.description|description:]
2122 [ui.note log.description|Modify, add, remove, rename]
2122 [ui.note log.description|Modify, add, remove, rename]
2123
2123
2124 [ui.note log.files|files:]
2124 [ui.note log.files|files:]
2125 [status.modified|M third]
2125 [status.modified|M third]
2126 [status.added|A b]
2126 [status.added|A b]
2127 [status.added|A fifth]
2127 [status.added|A fifth]
2128 [status.copied| fourth]
2128 [status.copied| fourth]
2129 [status.removed|R a]
2129 [status.removed|R a]
2130 [status.removed|R fourth]
2130 [status.removed|R fourth]
2131
2131
2132 $ hg --color=debug log -T status -C -r 10 --debug
2132 $ hg --color=debug log -T status -C -r 10 --debug
2133 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2133 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2134 [log.tag|tag: tip]
2134 [log.tag|tag: tip]
2135 [log.phase|phase: secret]
2135 [log.phase|phase: secret]
2136 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2136 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2137 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2137 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2138 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2138 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2139 [log.user|user: test]
2139 [log.user|user: test]
2140 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2140 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2141 [ui.debug log.extra|extra: branch=default]
2141 [ui.debug log.extra|extra: branch=default]
2142 [ui.note log.description|description:]
2142 [ui.note log.description|description:]
2143 [ui.note log.description|Modify, add, remove, rename]
2143 [ui.note log.description|Modify, add, remove, rename]
2144
2144
2145 [ui.note log.files|files:]
2145 [ui.note log.files|files:]
2146 [status.modified|M third]
2146 [status.modified|M third]
2147 [status.added|A b]
2147 [status.added|A b]
2148 [status.added|A fifth]
2148 [status.added|A fifth]
2149 [status.copied| fourth]
2149 [status.copied| fourth]
2150 [status.removed|R a]
2150 [status.removed|R a]
2151 [status.removed|R fourth]
2151 [status.removed|R fourth]
2152
2152
2153 $ hg --color=debug log -T status -C -r 10 --quiet
2153 $ hg --color=debug log -T status -C -r 10 --quiet
2154 [log.node|10:0f9759ec227a]
2154 [log.node|10:0f9759ec227a]
2155
2155
2156 Check the bisect template
2156 Check the bisect template
2157
2157
2158 $ hg bisect -g 1
2158 $ hg bisect -g 1
2159 $ hg bisect -b 3 --noupdate
2159 $ hg bisect -b 3 --noupdate
2160 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2160 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2161 $ hg log -T bisect -r 0:4
2161 $ hg log -T bisect -r 0:4
2162 changeset: 0:1e4e1b8f71e0
2162 changeset: 0:1e4e1b8f71e0
2163 bisect: good (implicit)
2163 bisect: good (implicit)
2164 user: User Name <user@hostname>
2164 user: User Name <user@hostname>
2165 date: Mon Jan 12 13:46:40 1970 +0000
2165 date: Mon Jan 12 13:46:40 1970 +0000
2166 summary: line 1
2166 summary: line 1
2167
2167
2168 changeset: 1:b608e9d1a3f0
2168 changeset: 1:b608e9d1a3f0
2169 bisect: good
2169 bisect: good
2170 user: A. N. Other <other@place>
2170 user: A. N. Other <other@place>
2171 date: Tue Jan 13 17:33:20 1970 +0000
2171 date: Tue Jan 13 17:33:20 1970 +0000
2172 summary: other 1
2172 summary: other 1
2173
2173
2174 changeset: 2:97054abb4ab8
2174 changeset: 2:97054abb4ab8
2175 bisect: untested
2175 bisect: untested
2176 user: other@place
2176 user: other@place
2177 date: Wed Jan 14 21:20:00 1970 +0000
2177 date: Wed Jan 14 21:20:00 1970 +0000
2178 summary: no person
2178 summary: no person
2179
2179
2180 changeset: 3:10e46f2dcbf4
2180 changeset: 3:10e46f2dcbf4
2181 bisect: bad
2181 bisect: bad
2182 user: person
2182 user: person
2183 date: Fri Jan 16 01:06:40 1970 +0000
2183 date: Fri Jan 16 01:06:40 1970 +0000
2184 summary: no user, no domain
2184 summary: no user, no domain
2185
2185
2186 changeset: 4:bbe44766e73d
2186 changeset: 4:bbe44766e73d
2187 bisect: bad (implicit)
2187 bisect: bad (implicit)
2188 branch: foo
2188 branch: foo
2189 user: person
2189 user: person
2190 date: Sat Jan 17 04:53:20 1970 +0000
2190 date: Sat Jan 17 04:53:20 1970 +0000
2191 summary: new branch
2191 summary: new branch
2192
2192
2193 $ hg log --debug -T bisect -r 0:4
2193 $ hg log --debug -T bisect -r 0:4
2194 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2194 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2195 bisect: good (implicit)
2195 bisect: good (implicit)
2196 phase: public
2196 phase: public
2197 parent: -1:0000000000000000000000000000000000000000
2197 parent: -1:0000000000000000000000000000000000000000
2198 parent: -1:0000000000000000000000000000000000000000
2198 parent: -1:0000000000000000000000000000000000000000
2199 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2199 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2200 user: User Name <user@hostname>
2200 user: User Name <user@hostname>
2201 date: Mon Jan 12 13:46:40 1970 +0000
2201 date: Mon Jan 12 13:46:40 1970 +0000
2202 files+: a
2202 files+: a
2203 extra: branch=default
2203 extra: branch=default
2204 description:
2204 description:
2205 line 1
2205 line 1
2206 line 2
2206 line 2
2207
2207
2208
2208
2209 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2209 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2210 bisect: good
2210 bisect: good
2211 phase: public
2211 phase: public
2212 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2212 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2213 parent: -1:0000000000000000000000000000000000000000
2213 parent: -1:0000000000000000000000000000000000000000
2214 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2214 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2215 user: A. N. Other <other@place>
2215 user: A. N. Other <other@place>
2216 date: Tue Jan 13 17:33:20 1970 +0000
2216 date: Tue Jan 13 17:33:20 1970 +0000
2217 files+: b
2217 files+: b
2218 extra: branch=default
2218 extra: branch=default
2219 description:
2219 description:
2220 other 1
2220 other 1
2221 other 2
2221 other 2
2222
2222
2223 other 3
2223 other 3
2224
2224
2225
2225
2226 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2226 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2227 bisect: untested
2227 bisect: untested
2228 phase: public
2228 phase: public
2229 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2229 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2230 parent: -1:0000000000000000000000000000000000000000
2230 parent: -1:0000000000000000000000000000000000000000
2231 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2231 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2232 user: other@place
2232 user: other@place
2233 date: Wed Jan 14 21:20:00 1970 +0000
2233 date: Wed Jan 14 21:20:00 1970 +0000
2234 files+: c
2234 files+: c
2235 extra: branch=default
2235 extra: branch=default
2236 description:
2236 description:
2237 no person
2237 no person
2238
2238
2239
2239
2240 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2240 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2241 bisect: bad
2241 bisect: bad
2242 phase: public
2242 phase: public
2243 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2243 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2244 parent: -1:0000000000000000000000000000000000000000
2244 parent: -1:0000000000000000000000000000000000000000
2245 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2245 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2246 user: person
2246 user: person
2247 date: Fri Jan 16 01:06:40 1970 +0000
2247 date: Fri Jan 16 01:06:40 1970 +0000
2248 files: c
2248 files: c
2249 extra: branch=default
2249 extra: branch=default
2250 description:
2250 description:
2251 no user, no domain
2251 no user, no domain
2252
2252
2253
2253
2254 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2254 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2255 bisect: bad (implicit)
2255 bisect: bad (implicit)
2256 branch: foo
2256 branch: foo
2257 phase: draft
2257 phase: draft
2258 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2258 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2259 parent: -1:0000000000000000000000000000000000000000
2259 parent: -1:0000000000000000000000000000000000000000
2260 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2260 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2261 user: person
2261 user: person
2262 date: Sat Jan 17 04:53:20 1970 +0000
2262 date: Sat Jan 17 04:53:20 1970 +0000
2263 extra: branch=foo
2263 extra: branch=foo
2264 description:
2264 description:
2265 new branch
2265 new branch
2266
2266
2267
2267
2268 $ hg log -v -T bisect -r 0:4
2268 $ hg log -v -T bisect -r 0:4
2269 changeset: 0:1e4e1b8f71e0
2269 changeset: 0:1e4e1b8f71e0
2270 bisect: good (implicit)
2270 bisect: good (implicit)
2271 user: User Name <user@hostname>
2271 user: User Name <user@hostname>
2272 date: Mon Jan 12 13:46:40 1970 +0000
2272 date: Mon Jan 12 13:46:40 1970 +0000
2273 files: a
2273 files: a
2274 description:
2274 description:
2275 line 1
2275 line 1
2276 line 2
2276 line 2
2277
2277
2278
2278
2279 changeset: 1:b608e9d1a3f0
2279 changeset: 1:b608e9d1a3f0
2280 bisect: good
2280 bisect: good
2281 user: A. N. Other <other@place>
2281 user: A. N. Other <other@place>
2282 date: Tue Jan 13 17:33:20 1970 +0000
2282 date: Tue Jan 13 17:33:20 1970 +0000
2283 files: b
2283 files: b
2284 description:
2284 description:
2285 other 1
2285 other 1
2286 other 2
2286 other 2
2287
2287
2288 other 3
2288 other 3
2289
2289
2290
2290
2291 changeset: 2:97054abb4ab8
2291 changeset: 2:97054abb4ab8
2292 bisect: untested
2292 bisect: untested
2293 user: other@place
2293 user: other@place
2294 date: Wed Jan 14 21:20:00 1970 +0000
2294 date: Wed Jan 14 21:20:00 1970 +0000
2295 files: c
2295 files: c
2296 description:
2296 description:
2297 no person
2297 no person
2298
2298
2299
2299
2300 changeset: 3:10e46f2dcbf4
2300 changeset: 3:10e46f2dcbf4
2301 bisect: bad
2301 bisect: bad
2302 user: person
2302 user: person
2303 date: Fri Jan 16 01:06:40 1970 +0000
2303 date: Fri Jan 16 01:06:40 1970 +0000
2304 files: c
2304 files: c
2305 description:
2305 description:
2306 no user, no domain
2306 no user, no domain
2307
2307
2308
2308
2309 changeset: 4:bbe44766e73d
2309 changeset: 4:bbe44766e73d
2310 bisect: bad (implicit)
2310 bisect: bad (implicit)
2311 branch: foo
2311 branch: foo
2312 user: person
2312 user: person
2313 date: Sat Jan 17 04:53:20 1970 +0000
2313 date: Sat Jan 17 04:53:20 1970 +0000
2314 description:
2314 description:
2315 new branch
2315 new branch
2316
2316
2317
2317
2318 $ hg --color=debug log -T bisect -r 0:4
2318 $ hg --color=debug log -T bisect -r 0:4
2319 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2319 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2320 [log.bisect bisect.good|bisect: good (implicit)]
2320 [log.bisect bisect.good|bisect: good (implicit)]
2321 [log.user|user: User Name <user@hostname>]
2321 [log.user|user: User Name <user@hostname>]
2322 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2322 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2323 [log.summary|summary: line 1]
2323 [log.summary|summary: line 1]
2324
2324
2325 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2325 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2326 [log.bisect bisect.good|bisect: good]
2326 [log.bisect bisect.good|bisect: good]
2327 [log.user|user: A. N. Other <other@place>]
2327 [log.user|user: A. N. Other <other@place>]
2328 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2328 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2329 [log.summary|summary: other 1]
2329 [log.summary|summary: other 1]
2330
2330
2331 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2331 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2332 [log.bisect bisect.untested|bisect: untested]
2332 [log.bisect bisect.untested|bisect: untested]
2333 [log.user|user: other@place]
2333 [log.user|user: other@place]
2334 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2334 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2335 [log.summary|summary: no person]
2335 [log.summary|summary: no person]
2336
2336
2337 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2337 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2338 [log.bisect bisect.bad|bisect: bad]
2338 [log.bisect bisect.bad|bisect: bad]
2339 [log.user|user: person]
2339 [log.user|user: person]
2340 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2340 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2341 [log.summary|summary: no user, no domain]
2341 [log.summary|summary: no user, no domain]
2342
2342
2343 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2343 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2344 [log.bisect bisect.bad|bisect: bad (implicit)]
2344 [log.bisect bisect.bad|bisect: bad (implicit)]
2345 [log.branch|branch: foo]
2345 [log.branch|branch: foo]
2346 [log.user|user: person]
2346 [log.user|user: person]
2347 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2347 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2348 [log.summary|summary: new branch]
2348 [log.summary|summary: new branch]
2349
2349
2350 $ hg --color=debug log --debug -T bisect -r 0:4
2350 $ hg --color=debug log --debug -T bisect -r 0:4
2351 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2351 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2352 [log.bisect bisect.good|bisect: good (implicit)]
2352 [log.bisect bisect.good|bisect: good (implicit)]
2353 [log.phase|phase: public]
2353 [log.phase|phase: public]
2354 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2354 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2355 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2355 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2356 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2356 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2357 [log.user|user: User Name <user@hostname>]
2357 [log.user|user: User Name <user@hostname>]
2358 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2358 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2359 [ui.debug log.files|files+: a]
2359 [ui.debug log.files|files+: a]
2360 [ui.debug log.extra|extra: branch=default]
2360 [ui.debug log.extra|extra: branch=default]
2361 [ui.note log.description|description:]
2361 [ui.note log.description|description:]
2362 [ui.note log.description|line 1
2362 [ui.note log.description|line 1
2363 line 2]
2363 line 2]
2364
2364
2365
2365
2366 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2366 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2367 [log.bisect bisect.good|bisect: good]
2367 [log.bisect bisect.good|bisect: good]
2368 [log.phase|phase: public]
2368 [log.phase|phase: public]
2369 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2369 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2370 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2370 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2371 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2371 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2372 [log.user|user: A. N. Other <other@place>]
2372 [log.user|user: A. N. Other <other@place>]
2373 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2373 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2374 [ui.debug log.files|files+: b]
2374 [ui.debug log.files|files+: b]
2375 [ui.debug log.extra|extra: branch=default]
2375 [ui.debug log.extra|extra: branch=default]
2376 [ui.note log.description|description:]
2376 [ui.note log.description|description:]
2377 [ui.note log.description|other 1
2377 [ui.note log.description|other 1
2378 other 2
2378 other 2
2379
2379
2380 other 3]
2380 other 3]
2381
2381
2382
2382
2383 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2383 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2384 [log.bisect bisect.untested|bisect: untested]
2384 [log.bisect bisect.untested|bisect: untested]
2385 [log.phase|phase: public]
2385 [log.phase|phase: public]
2386 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2386 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2387 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2387 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2388 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2388 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2389 [log.user|user: other@place]
2389 [log.user|user: other@place]
2390 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2390 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2391 [ui.debug log.files|files+: c]
2391 [ui.debug log.files|files+: c]
2392 [ui.debug log.extra|extra: branch=default]
2392 [ui.debug log.extra|extra: branch=default]
2393 [ui.note log.description|description:]
2393 [ui.note log.description|description:]
2394 [ui.note log.description|no person]
2394 [ui.note log.description|no person]
2395
2395
2396
2396
2397 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2397 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2398 [log.bisect bisect.bad|bisect: bad]
2398 [log.bisect bisect.bad|bisect: bad]
2399 [log.phase|phase: public]
2399 [log.phase|phase: public]
2400 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2400 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2401 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2401 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2402 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2402 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2403 [log.user|user: person]
2403 [log.user|user: person]
2404 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2404 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2405 [ui.debug log.files|files: c]
2405 [ui.debug log.files|files: c]
2406 [ui.debug log.extra|extra: branch=default]
2406 [ui.debug log.extra|extra: branch=default]
2407 [ui.note log.description|description:]
2407 [ui.note log.description|description:]
2408 [ui.note log.description|no user, no domain]
2408 [ui.note log.description|no user, no domain]
2409
2409
2410
2410
2411 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2411 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2412 [log.bisect bisect.bad|bisect: bad (implicit)]
2412 [log.bisect bisect.bad|bisect: bad (implicit)]
2413 [log.branch|branch: foo]
2413 [log.branch|branch: foo]
2414 [log.phase|phase: draft]
2414 [log.phase|phase: draft]
2415 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2415 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2416 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2416 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2417 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2417 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2418 [log.user|user: person]
2418 [log.user|user: person]
2419 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2419 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2420 [ui.debug log.extra|extra: branch=foo]
2420 [ui.debug log.extra|extra: branch=foo]
2421 [ui.note log.description|description:]
2421 [ui.note log.description|description:]
2422 [ui.note log.description|new branch]
2422 [ui.note log.description|new branch]
2423
2423
2424
2424
2425 $ hg --color=debug log -v -T bisect -r 0:4
2425 $ hg --color=debug log -v -T bisect -r 0:4
2426 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2426 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2427 [log.bisect bisect.good|bisect: good (implicit)]
2427 [log.bisect bisect.good|bisect: good (implicit)]
2428 [log.user|user: User Name <user@hostname>]
2428 [log.user|user: User Name <user@hostname>]
2429 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2429 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2430 [ui.note log.files|files: a]
2430 [ui.note log.files|files: a]
2431 [ui.note log.description|description:]
2431 [ui.note log.description|description:]
2432 [ui.note log.description|line 1
2432 [ui.note log.description|line 1
2433 line 2]
2433 line 2]
2434
2434
2435
2435
2436 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2436 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2437 [log.bisect bisect.good|bisect: good]
2437 [log.bisect bisect.good|bisect: good]
2438 [log.user|user: A. N. Other <other@place>]
2438 [log.user|user: A. N. Other <other@place>]
2439 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2439 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2440 [ui.note log.files|files: b]
2440 [ui.note log.files|files: b]
2441 [ui.note log.description|description:]
2441 [ui.note log.description|description:]
2442 [ui.note log.description|other 1
2442 [ui.note log.description|other 1
2443 other 2
2443 other 2
2444
2444
2445 other 3]
2445 other 3]
2446
2446
2447
2447
2448 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2448 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2449 [log.bisect bisect.untested|bisect: untested]
2449 [log.bisect bisect.untested|bisect: untested]
2450 [log.user|user: other@place]
2450 [log.user|user: other@place]
2451 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2451 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2452 [ui.note log.files|files: c]
2452 [ui.note log.files|files: c]
2453 [ui.note log.description|description:]
2453 [ui.note log.description|description:]
2454 [ui.note log.description|no person]
2454 [ui.note log.description|no person]
2455
2455
2456
2456
2457 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2457 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2458 [log.bisect bisect.bad|bisect: bad]
2458 [log.bisect bisect.bad|bisect: bad]
2459 [log.user|user: person]
2459 [log.user|user: person]
2460 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2460 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2461 [ui.note log.files|files: c]
2461 [ui.note log.files|files: c]
2462 [ui.note log.description|description:]
2462 [ui.note log.description|description:]
2463 [ui.note log.description|no user, no domain]
2463 [ui.note log.description|no user, no domain]
2464
2464
2465
2465
2466 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2466 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2467 [log.bisect bisect.bad|bisect: bad (implicit)]
2467 [log.bisect bisect.bad|bisect: bad (implicit)]
2468 [log.branch|branch: foo]
2468 [log.branch|branch: foo]
2469 [log.user|user: person]
2469 [log.user|user: person]
2470 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2470 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2471 [ui.note log.description|description:]
2471 [ui.note log.description|description:]
2472 [ui.note log.description|new branch]
2472 [ui.note log.description|new branch]
2473
2473
2474
2474
2475 $ hg bisect --reset
2475 $ hg bisect --reset
2476
2476
2477 Error on syntax:
2477 Error on syntax:
2478
2478
2479 $ echo 'x = "f' >> t
2479 $ echo 'x = "f' >> t
2480 $ hg log
2480 $ hg log
2481 abort: t:3: unmatched quotes
2481 abort: t:3: unmatched quotes
2482 [255]
2482 [255]
2483
2483
2484 Behind the scenes, this will throw TypeError
2484 Behind the scenes, this will throw TypeError
2485
2485
2486 $ hg log -l 3 --template '{date|obfuscate}\n'
2486 $ hg log -l 3 --template '{date|obfuscate}\n'
2487 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2487 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2488 [255]
2488 [255]
2489
2489
2490 Behind the scenes, this will throw a ValueError
2490 Behind the scenes, this will throw a ValueError
2491
2491
2492 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2492 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2493 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2493 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2494 [255]
2494 [255]
2495
2495
2496 Behind the scenes, this will throw AttributeError
2496 Behind the scenes, this will throw AttributeError
2497
2497
2498 $ hg log -l 3 --template 'line: {date|escape}\n'
2498 $ hg log -l 3 --template 'line: {date|escape}\n'
2499 abort: template filter 'escape' is not compatible with keyword 'date'
2499 abort: template filter 'escape' is not compatible with keyword 'date'
2500 [255]
2500 [255]
2501
2501
2502 Behind the scenes, this will throw ValueError
2502 Behind the scenes, this will throw ValueError
2503
2503
2504 $ hg tip --template '{author|email|date}\n'
2504 $ hg tip --template '{author|email|date}\n'
2505 abort: template filter 'datefilter' is not compatible with keyword 'author'
2505 abort: template filter 'datefilter' is not compatible with keyword 'author'
2506 [255]
2506 [255]
2507
2507
2508 Thrown an error if a template function doesn't exist
2508 Thrown an error if a template function doesn't exist
2509
2509
2510 $ hg tip --template '{foo()}\n'
2510 $ hg tip --template '{foo()}\n'
2511 hg: parse error: unknown function 'foo'
2511 hg: parse error: unknown function 'foo'
2512 [255]
2512 [255]
2513
2513
2514 Pass generator object created by template function to filter
2514 Pass generator object created by template function to filter
2515
2515
2516 $ hg log -l 1 --template '{if(author, author)|user}\n'
2516 $ hg log -l 1 --template '{if(author, author)|user}\n'
2517 test
2517 test
2518
2518
2519 Test diff function:
2519 Test diff function:
2520
2520
2521 $ hg diff -c 8
2521 $ hg diff -c 8
2522 diff -r 29114dbae42b -r 95c24699272e fourth
2522 diff -r 29114dbae42b -r 95c24699272e fourth
2523 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2523 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2524 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2524 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2525 @@ -0,0 +1,1 @@
2525 @@ -0,0 +1,1 @@
2526 +second
2526 +second
2527 diff -r 29114dbae42b -r 95c24699272e second
2527 diff -r 29114dbae42b -r 95c24699272e second
2528 --- a/second Mon Jan 12 13:46:40 1970 +0000
2528 --- a/second Mon Jan 12 13:46:40 1970 +0000
2529 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2529 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2530 @@ -1,1 +0,0 @@
2530 @@ -1,1 +0,0 @@
2531 -second
2531 -second
2532 diff -r 29114dbae42b -r 95c24699272e third
2532 diff -r 29114dbae42b -r 95c24699272e third
2533 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2533 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2534 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2534 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2535 @@ -0,0 +1,1 @@
2535 @@ -0,0 +1,1 @@
2536 +third
2536 +third
2537
2537
2538 $ hg log -r 8 -T "{diff()}"
2538 $ hg log -r 8 -T "{diff()}"
2539 diff -r 29114dbae42b -r 95c24699272e fourth
2539 diff -r 29114dbae42b -r 95c24699272e fourth
2540 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2540 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2541 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2541 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2542 @@ -0,0 +1,1 @@
2542 @@ -0,0 +1,1 @@
2543 +second
2543 +second
2544 diff -r 29114dbae42b -r 95c24699272e second
2544 diff -r 29114dbae42b -r 95c24699272e second
2545 --- a/second Mon Jan 12 13:46:40 1970 +0000
2545 --- a/second Mon Jan 12 13:46:40 1970 +0000
2546 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2546 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2547 @@ -1,1 +0,0 @@
2547 @@ -1,1 +0,0 @@
2548 -second
2548 -second
2549 diff -r 29114dbae42b -r 95c24699272e third
2549 diff -r 29114dbae42b -r 95c24699272e third
2550 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2550 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2551 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2551 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2552 @@ -0,0 +1,1 @@
2552 @@ -0,0 +1,1 @@
2553 +third
2553 +third
2554
2554
2555 $ hg log -r 8 -T "{diff('glob:f*')}"
2555 $ hg log -r 8 -T "{diff('glob:f*')}"
2556 diff -r 29114dbae42b -r 95c24699272e fourth
2556 diff -r 29114dbae42b -r 95c24699272e fourth
2557 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2557 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2558 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2558 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2559 @@ -0,0 +1,1 @@
2559 @@ -0,0 +1,1 @@
2560 +second
2560 +second
2561
2561
2562 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2562 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2563 diff -r 29114dbae42b -r 95c24699272e second
2563 diff -r 29114dbae42b -r 95c24699272e second
2564 --- a/second Mon Jan 12 13:46:40 1970 +0000
2564 --- a/second Mon Jan 12 13:46:40 1970 +0000
2565 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2565 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2566 @@ -1,1 +0,0 @@
2566 @@ -1,1 +0,0 @@
2567 -second
2567 -second
2568 diff -r 29114dbae42b -r 95c24699272e third
2568 diff -r 29114dbae42b -r 95c24699272e third
2569 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2569 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2570 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2570 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2571 @@ -0,0 +1,1 @@
2571 @@ -0,0 +1,1 @@
2572 +third
2572 +third
2573
2573
2574 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2574 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2575 diff -r 29114dbae42b -r 95c24699272e fourth
2575 diff -r 29114dbae42b -r 95c24699272e fourth
2576 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2576 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2577 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2577 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2578 @@ -0,0 +1,1 @@
2578 @@ -0,0 +1,1 @@
2579 +second
2579 +second
2580
2580
2581 $ cd ..
2581 $ cd ..
2582
2582
2583
2583
2584 latesttag:
2584 latesttag:
2585
2585
2586 $ hg init latesttag
2586 $ hg init latesttag
2587 $ cd latesttag
2587 $ cd latesttag
2588
2588
2589 $ echo a > file
2589 $ echo a > file
2590 $ hg ci -Am a -d '0 0'
2590 $ hg ci -Am a -d '0 0'
2591 adding file
2591 adding file
2592
2592
2593 $ echo b >> file
2593 $ echo b >> file
2594 $ hg ci -m b -d '1 0'
2594 $ hg ci -m b -d '1 0'
2595
2595
2596 $ echo c >> head1
2596 $ echo c >> head1
2597 $ hg ci -Am h1c -d '2 0'
2597 $ hg ci -Am h1c -d '2 0'
2598 adding head1
2598 adding head1
2599
2599
2600 $ hg update -q 1
2600 $ hg update -q 1
2601 $ echo d >> head2
2601 $ echo d >> head2
2602 $ hg ci -Am h2d -d '3 0'
2602 $ hg ci -Am h2d -d '3 0'
2603 adding head2
2603 adding head2
2604 created new head
2604 created new head
2605
2605
2606 $ echo e >> head2
2606 $ echo e >> head2
2607 $ hg ci -m h2e -d '4 0'
2607 $ hg ci -m h2e -d '4 0'
2608
2608
2609 $ hg merge -q
2609 $ hg merge -q
2610 $ hg ci -m merge -d '5 -3600'
2610 $ hg ci -m merge -d '5 -3600'
2611
2611
2612 No tag set:
2612 No tag set:
2613
2613
2614 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2614 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2615 5: null+5
2615 5: null+5
2616 4: null+4
2616 4: null+4
2617 3: null+3
2617 3: null+3
2618 2: null+3
2618 2: null+3
2619 1: null+2
2619 1: null+2
2620 0: null+1
2620 0: null+1
2621
2621
2622 One common tag: longest path wins:
2622 One common tag: longest path wins:
2623
2623
2624 $ hg tag -r 1 -m t1 -d '6 0' t1
2624 $ hg tag -r 1 -m t1 -d '6 0' t1
2625 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2625 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2626 6: t1+4
2626 6: t1+4
2627 5: t1+3
2627 5: t1+3
2628 4: t1+2
2628 4: t1+2
2629 3: t1+1
2629 3: t1+1
2630 2: t1+1
2630 2: t1+1
2631 1: t1+0
2631 1: t1+0
2632 0: null+1
2632 0: null+1
2633
2633
2634 One ancestor tag: more recent wins:
2634 One ancestor tag: more recent wins:
2635
2635
2636 $ hg tag -r 2 -m t2 -d '7 0' t2
2636 $ hg tag -r 2 -m t2 -d '7 0' t2
2637 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2637 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2638 7: t2+3
2638 7: t2+3
2639 6: t2+2
2639 6: t2+2
2640 5: t2+1
2640 5: t2+1
2641 4: t1+2
2641 4: t1+2
2642 3: t1+1
2642 3: t1+1
2643 2: t2+0
2643 2: t2+0
2644 1: t1+0
2644 1: t1+0
2645 0: null+1
2645 0: null+1
2646
2646
2647 Two branch tags: more recent wins:
2647 Two branch tags: more recent wins:
2648
2648
2649 $ hg tag -r 3 -m t3 -d '8 0' t3
2649 $ hg tag -r 3 -m t3 -d '8 0' t3
2650 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2650 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2651 8: t3+5
2651 8: t3+5
2652 7: t3+4
2652 7: t3+4
2653 6: t3+3
2653 6: t3+3
2654 5: t3+2
2654 5: t3+2
2655 4: t3+1
2655 4: t3+1
2656 3: t3+0
2656 3: t3+0
2657 2: t2+0
2657 2: t2+0
2658 1: t1+0
2658 1: t1+0
2659 0: null+1
2659 0: null+1
2660
2660
2661 Merged tag overrides:
2661 Merged tag overrides:
2662
2662
2663 $ hg tag -r 5 -m t5 -d '9 0' t5
2663 $ hg tag -r 5 -m t5 -d '9 0' t5
2664 $ hg tag -r 3 -m at3 -d '10 0' at3
2664 $ hg tag -r 3 -m at3 -d '10 0' at3
2665 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2665 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2666 10: t5+5
2666 10: t5+5
2667 9: t5+4
2667 9: t5+4
2668 8: t5+3
2668 8: t5+3
2669 7: t5+2
2669 7: t5+2
2670 6: t5+1
2670 6: t5+1
2671 5: t5+0
2671 5: t5+0
2672 4: at3:t3+1
2672 4: at3:t3+1
2673 3: at3:t3+0
2673 3: at3:t3+0
2674 2: t2+0
2674 2: t2+0
2675 1: t1+0
2675 1: t1+0
2676 0: null+1
2676 0: null+1
2677
2677
2678 $ cd ..
2678 $ cd ..
2679
2679
2680
2680
2681 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2681 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2682 if it is a relative path
2682 if it is a relative path
2683
2683
2684 $ mkdir -p home/styles
2684 $ mkdir -p home/styles
2685
2685
2686 $ cat > home/styles/teststyle <<EOF
2686 $ cat > home/styles/teststyle <<EOF
2687 > changeset = 'test {rev}:{node|short}\n'
2687 > changeset = 'test {rev}:{node|short}\n'
2688 > EOF
2688 > EOF
2689
2689
2690 $ HOME=`pwd`/home; export HOME
2690 $ HOME=`pwd`/home; export HOME
2691
2691
2692 $ cat > latesttag/.hg/hgrc <<EOF
2692 $ cat > latesttag/.hg/hgrc <<EOF
2693 > [ui]
2693 > [ui]
2694 > style = ~/styles/teststyle
2694 > style = ~/styles/teststyle
2695 > EOF
2695 > EOF
2696
2696
2697 $ hg -R latesttag tip
2697 $ hg -R latesttag tip
2698 test 10:9b4a630e5f5f
2698 test 10:9b4a630e5f5f
2699
2699
2700 Test recursive showlist template (issue1989):
2700 Test recursive showlist template (issue1989):
2701
2701
2702 $ cat > style1989 <<EOF
2702 $ cat > style1989 <<EOF
2703 > changeset = '{file_mods}{manifest}{extras}'
2703 > changeset = '{file_mods}{manifest}{extras}'
2704 > file_mod = 'M|{author|person}\n'
2704 > file_mod = 'M|{author|person}\n'
2705 > manifest = '{rev},{author}\n'
2705 > manifest = '{rev},{author}\n'
2706 > extra = '{key}: {author}\n'
2706 > extra = '{key}: {author}\n'
2707 > EOF
2707 > EOF
2708
2708
2709 $ hg -R latesttag log -r tip --style=style1989
2709 $ hg -R latesttag log -r tip --style=style1989
2710 M|test
2710 M|test
2711 10,test
2711 10,test
2712 branch: test
2712 branch: test
2713
2713
2714 Test new-style inline templating:
2714 Test new-style inline templating:
2715
2715
2716 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2716 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2717 modified files: .hgtags
2717 modified files: .hgtags
2718
2718
2719 Test the sub function of templating for expansion:
2719 Test the sub function of templating for expansion:
2720
2720
2721 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2721 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2722 xx
2722 xx
2723
2723
2724 Test the strip function with chars specified:
2724 Test the strip function with chars specified:
2725
2725
2726 $ hg log -R latesttag --template '{desc}\n'
2726 $ hg log -R latesttag --template '{desc}\n'
2727 at3
2727 at3
2728 t5
2728 t5
2729 t3
2729 t3
2730 t2
2730 t2
2731 t1
2731 t1
2732 merge
2732 merge
2733 h2e
2733 h2e
2734 h2d
2734 h2d
2735 h1c
2735 h1c
2736 b
2736 b
2737 a
2737 a
2738
2738
2739 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2739 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2740 at3
2740 at3
2741 5
2741 5
2742 3
2742 3
2743 2
2743 2
2744 1
2744 1
2745 merg
2745 merg
2746 h2
2746 h2
2747 h2d
2747 h2d
2748 h1c
2748 h1c
2749 b
2749 b
2750 a
2750 a
2751
2751
2752 Test date format:
2752 Test date format:
2753
2753
2754 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2754 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2755 date: 70 01 01 10 +0000
2755 date: 70 01 01 10 +0000
2756 date: 70 01 01 09 +0000
2756 date: 70 01 01 09 +0000
2757 date: 70 01 01 08 +0000
2757 date: 70 01 01 08 +0000
2758 date: 70 01 01 07 +0000
2758 date: 70 01 01 07 +0000
2759 date: 70 01 01 06 +0000
2759 date: 70 01 01 06 +0000
2760 date: 70 01 01 05 +0100
2760 date: 70 01 01 05 +0100
2761 date: 70 01 01 04 +0000
2761 date: 70 01 01 04 +0000
2762 date: 70 01 01 03 +0000
2762 date: 70 01 01 03 +0000
2763 date: 70 01 01 02 +0000
2763 date: 70 01 01 02 +0000
2764 date: 70 01 01 01 +0000
2764 date: 70 01 01 01 +0000
2765 date: 70 01 01 00 +0000
2765 date: 70 01 01 00 +0000
2766
2766
2767 Test invalid date:
2767 Test invalid date:
2768
2768
2769 $ hg log -R latesttag -T '{date(rev)}\n'
2769 $ hg log -R latesttag -T '{date(rev)}\n'
2770 hg: parse error: date expects a date information
2770 hg: parse error: date expects a date information
2771 [255]
2771 [255]
2772
2772
2773 Test integer literal:
2773 Test integer literal:
2774
2774
2775 $ hg log -Ra -r0 -T '{(0)}\n'
2775 $ hg log -Ra -r0 -T '{(0)}\n'
2776 0
2776 0
2777 $ hg log -Ra -r0 -T '{(123)}\n'
2777 $ hg log -Ra -r0 -T '{(123)}\n'
2778 123
2778 123
2779 $ hg log -Ra -r0 -T '{(-4)}\n'
2779 $ hg log -Ra -r0 -T '{(-4)}\n'
2780 -4
2780 -4
2781 $ hg log -Ra -r0 -T '{(-)}\n'
2781 $ hg log -Ra -r0 -T '{(-)}\n'
2782 hg: parse error at 2: integer literal without digits
2782 hg: parse error at 2: integer literal without digits
2783 [255]
2783 [255]
2784 $ hg log -Ra -r0 -T '{(-a)}\n'
2784 $ hg log -Ra -r0 -T '{(-a)}\n'
2785 hg: parse error at 2: integer literal without digits
2785 hg: parse error at 2: integer literal without digits
2786 [255]
2786 [255]
2787
2787
2788 top-level integer literal is interpreted as symbol (i.e. variable name):
2788 top-level integer literal is interpreted as symbol (i.e. variable name):
2789
2789
2790 $ hg log -Ra -r0 -T '{1}\n'
2790 $ hg log -Ra -r0 -T '{1}\n'
2791
2791
2792 $ hg log -Ra -r0 -T '{if("t", "{1}")}\n'
2792 $ hg log -Ra -r0 -T '{if("t", "{1}")}\n'
2793
2793
2794 $ hg log -Ra -r0 -T '{1|stringify}\n'
2794 $ hg log -Ra -r0 -T '{1|stringify}\n'
2795
2795
2796
2796
2797 unless explicit symbol is expected:
2797 unless explicit symbol is expected:
2798
2798
2799 $ hg log -Ra -r0 -T '{desc|1}\n'
2799 $ hg log -Ra -r0 -T '{desc|1}\n'
2800 hg: parse error: expected a symbol, got 'integer'
2800 hg: parse error: expected a symbol, got 'integer'
2801 [255]
2801 [255]
2802 $ hg log -Ra -r0 -T '{1()}\n'
2802 $ hg log -Ra -r0 -T '{1()}\n'
2803 hg: parse error: expected a symbol, got 'integer'
2803 hg: parse error: expected a symbol, got 'integer'
2804 [255]
2804 [255]
2805
2805
2806 Test string literal:
2806 Test string literal:
2807
2807
2808 $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
2808 $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
2809 string with no template fragment
2809 string with no template fragment
2810 $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
2810 $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
2811 template: 0
2811 template: 0
2812 $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
2812 $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
2813 rawstring: {rev}
2813 rawstring: {rev}
2814
2814
2815 because map operation requires template, raw string can't be used
2815 because map operation requires template, raw string can't be used
2816
2816
2817 $ hg log -Ra -r0 -T '{files % r"rawstring"}\n'
2817 $ hg log -Ra -r0 -T '{files % r"rawstring"}\n'
2818 hg: parse error: expected template specifier
2818 hg: parse error: expected template specifier
2819 [255]
2819 [255]
2820
2820
2821 Test string escaping:
2821 Test string escaping:
2822
2822
2823 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2823 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2824 >
2824 >
2825 <>\n<[>
2825 <>\n<[>
2826 <>\n<]>
2826 <>\n<]>
2827 <>\n<
2827 <>\n<
2828
2828
2829 $ hg log -R latesttag -r 0 \
2829 $ hg log -R latesttag -r 0 \
2830 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2830 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2831 >
2831 >
2832 <>\n<[>
2832 <>\n<[>
2833 <>\n<]>
2833 <>\n<]>
2834 <>\n<
2834 <>\n<
2835
2835
2836 $ hg log -R latesttag -r 0 -T esc \
2836 $ hg log -R latesttag -r 0 -T esc \
2837 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2837 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2838 >
2838 >
2839 <>\n<[>
2839 <>\n<[>
2840 <>\n<]>
2840 <>\n<]>
2841 <>\n<
2841 <>\n<
2842
2842
2843 $ cat <<'EOF' > esctmpl
2843 $ cat <<'EOF' > esctmpl
2844 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2844 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2845 > EOF
2845 > EOF
2846 $ hg log -R latesttag -r 0 --style ./esctmpl
2846 $ hg log -R latesttag -r 0 --style ./esctmpl
2847 >
2847 >
2848 <>\n<[>
2848 <>\n<[>
2849 <>\n<]>
2849 <>\n<]>
2850 <>\n<
2850 <>\n<
2851
2851
2852 Test string escaping of quotes:
2853
2854 $ hg log -Ra -r0 -T '{"\""}\n'
2855 "
2856 $ hg log -Ra -r0 -T '{"\\\""}\n'
2857 \"
2858 $ hg log -Ra -r0 -T '{r"\""}\n'
2859 \"
2860 $ hg log -Ra -r0 -T '{r"\\\""}\n'
2861 \\\"
2862
2852 Test exception in quoted template. single backslash before quotation mark is
2863 Test exception in quoted template. single backslash before quotation mark is
2853 stripped before parsing:
2864 stripped before parsing:
2854
2865
2855 $ cat <<'EOF' > escquotetmpl
2866 $ cat <<'EOF' > escquotetmpl
2856 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
2867 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
2857 > EOF
2868 > EOF
2858 $ cd latesttag
2869 $ cd latesttag
2859 $ hg log -r 2 --style ../escquotetmpl
2870 $ hg log -r 2 --style ../escquotetmpl
2860 " \" \" \\" head1
2871 " \" \" \\" head1
2861
2872
2862 $ hg log -r 2 -T esc --config templates.esc='{\"invalid\"}\n'
2873 $ hg log -r 2 -T esc --config templates.esc='{\"invalid\"}\n'
2863 hg: parse error at 1: syntax error
2874 hg: parse error at 1: syntax error
2864 [255]
2875 [255]
2865 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
2876 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
2866 valid
2877 valid
2867 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
2878 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
2868 valid
2879 valid
2869 $ cd ..
2880 $ cd ..
2870
2881
2871 Test leading backslashes:
2882 Test leading backslashes:
2872
2883
2873 $ cd latesttag
2884 $ cd latesttag
2874 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
2885 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
2875 {rev} {file}
2886 {rev} {file}
2876 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
2887 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
2877 \2 \head1
2888 \2 \head1
2878 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
2889 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
2879 \{rev} \{file}
2890 \{rev} \{file}
2880 $ cd ..
2891 $ cd ..
2881
2892
2882 Test leading backslashes in "if" expression (issue4714):
2893 Test leading backslashes in "if" expression (issue4714):
2883
2894
2884 $ cd latesttag
2895 $ cd latesttag
2885 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
2896 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
2886 {rev} \{rev}
2897 {rev} \{rev}
2887 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
2898 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
2888 \2 \\{rev}
2899 \2 \\{rev}
2889 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
2900 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
2890 \{rev} \\\{rev}
2901 \{rev} \\\{rev}
2891 $ cd ..
2902 $ cd ..
2892
2903
2893 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2904 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2894
2905
2895 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2906 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2896 \x6e
2907 \x6e
2897 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2908 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2898 \x5c\x786e
2909 \x5c\x786e
2899 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2910 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2900 \x6e
2911 \x6e
2901 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2912 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2902 \x5c\x786e
2913 \x5c\x786e
2903
2914
2904 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2915 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2905 \x6e
2916 \x6e
2906 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2917 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2907 \x5c\x786e
2918 \x5c\x786e
2908 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2919 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2909 \x6e
2920 \x6e
2910 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2921 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2911 \x5c\x786e
2922 \x5c\x786e
2912
2923
2913 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2924 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2914 fourth
2925 fourth
2915 second
2926 second
2916 third
2927 third
2917 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2928 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2918 fourth\nsecond\nthird
2929 fourth\nsecond\nthird
2919
2930
2920 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2931 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2921 <p>
2932 <p>
2922 1st
2933 1st
2923 </p>
2934 </p>
2924 <p>
2935 <p>
2925 2nd
2936 2nd
2926 </p>
2937 </p>
2927 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2938 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2928 <p>
2939 <p>
2929 1st\n\n2nd
2940 1st\n\n2nd
2930 </p>
2941 </p>
2931 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2942 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2932 1st
2943 1st
2933
2944
2934 2nd
2945 2nd
2935
2946
2936 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2947 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2937 o perso
2948 o perso
2938 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2949 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2939 no person
2950 no person
2940 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2951 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2941 o perso
2952 o perso
2942 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2953 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2943 no perso
2954 no perso
2944
2955
2945 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2956 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2946 -o perso-
2957 -o perso-
2947 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2958 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2948 no person
2959 no person
2949 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2960 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2950 \x2do perso\x2d
2961 \x2do perso\x2d
2951 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2962 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2952 -o perso-
2963 -o perso-
2953 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2964 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2954 \x2do perso\x6e
2965 \x2do perso\x6e
2955
2966
2956 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2967 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2957 fourth
2968 fourth
2958 second
2969 second
2959 third
2970 third
2960
2971
2961 Test string escaping in nested expression:
2972 Test string escaping in nested expression:
2962
2973
2963 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2974 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2964 fourth\x6esecond\x6ethird
2975 fourth\x6esecond\x6ethird
2965 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2976 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2966 fourth\x6esecond\x6ethird
2977 fourth\x6esecond\x6ethird
2967
2978
2968 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2979 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2969 fourth\x6esecond\x6ethird
2980 fourth\x6esecond\x6ethird
2970 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2981 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2971 fourth\x5c\x786esecond\x5c\x786ethird
2982 fourth\x5c\x786esecond\x5c\x786ethird
2972
2983
2973 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2984 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2974 3:\x6eo user, \x6eo domai\x6e
2985 3:\x6eo user, \x6eo domai\x6e
2975 4:\x5c\x786eew bra\x5c\x786ech
2986 4:\x5c\x786eew bra\x5c\x786ech
2976
2987
2977 Test recursive evaluation:
2988 Test recursive evaluation:
2978
2989
2979 $ hg init r
2990 $ hg init r
2980 $ cd r
2991 $ cd r
2981 $ echo a > a
2992 $ echo a > a
2982 $ hg ci -Am '{rev}'
2993 $ hg ci -Am '{rev}'
2983 adding a
2994 adding a
2984 $ hg log -r 0 --template '{if(rev, desc)}\n'
2995 $ hg log -r 0 --template '{if(rev, desc)}\n'
2985 {rev}
2996 {rev}
2986 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2997 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2987 test 0
2998 test 0
2988
2999
2989 $ hg branch -q 'text.{rev}'
3000 $ hg branch -q 'text.{rev}'
2990 $ echo aa >> aa
3001 $ echo aa >> aa
2991 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3002 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2992
3003
2993 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3004 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2994 {node|short}desc to
3005 {node|short}desc to
2995 text.{rev}be wrapped
3006 text.{rev}be wrapped
2996 text.{rev}desc to be
3007 text.{rev}desc to be
2997 text.{rev}wrapped (no-eol)
3008 text.{rev}wrapped (no-eol)
2998 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3009 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2999 bcc7ff960b8e:desc to
3010 bcc7ff960b8e:desc to
3000 text.1:be wrapped
3011 text.1:be wrapped
3001 text.1:desc to be
3012 text.1:desc to be
3002 text.1:wrapped (no-eol)
3013 text.1:wrapped (no-eol)
3003
3014
3004 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3015 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3005 {node|short} (no-eol)
3016 {node|short} (no-eol)
3006 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3017 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3007 bcc-ff---b-e (no-eol)
3018 bcc-ff---b-e (no-eol)
3008
3019
3009 $ cat >> .hg/hgrc <<EOF
3020 $ cat >> .hg/hgrc <<EOF
3010 > [extensions]
3021 > [extensions]
3011 > color=
3022 > color=
3012 > [color]
3023 > [color]
3013 > mode=ansi
3024 > mode=ansi
3014 > text.{rev} = red
3025 > text.{rev} = red
3015 > text.1 = green
3026 > text.1 = green
3016 > EOF
3027 > EOF
3017 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3028 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3018 \x1b[0;31mtext\x1b[0m (esc)
3029 \x1b[0;31mtext\x1b[0m (esc)
3019 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3030 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3020 \x1b[0;32mtext\x1b[0m (esc)
3031 \x1b[0;32mtext\x1b[0m (esc)
3021
3032
3022 Test branches inside if statement:
3033 Test branches inside if statement:
3023
3034
3024 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3035 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3025 no
3036 no
3026
3037
3027 Test get function:
3038 Test get function:
3028
3039
3029 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3040 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3030 default
3041 default
3031 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3042 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3032 hg: parse error: get() expects a dict as first argument
3043 hg: parse error: get() expects a dict as first argument
3033 [255]
3044 [255]
3034
3045
3035 Test shortest(node) function:
3046 Test shortest(node) function:
3036
3047
3037 $ echo b > b
3048 $ echo b > b
3038 $ hg ci -qAm b
3049 $ hg ci -qAm b
3039 $ hg log --template '{shortest(node)}\n'
3050 $ hg log --template '{shortest(node)}\n'
3040 e777
3051 e777
3041 bcc7
3052 bcc7
3042 f776
3053 f776
3043 $ hg log --template '{shortest(node, 10)}\n'
3054 $ hg log --template '{shortest(node, 10)}\n'
3044 e777603221
3055 e777603221
3045 bcc7ff960b
3056 bcc7ff960b
3046 f7769ec2ab
3057 f7769ec2ab
3047
3058
3048 Test pad function
3059 Test pad function
3049
3060
3050 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3061 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3051 2 test
3062 2 test
3052 1 {node|short}
3063 1 {node|short}
3053 0 test
3064 0 test
3054
3065
3055 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3066 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3056 2 test
3067 2 test
3057 1 {node|short}
3068 1 {node|short}
3058 0 test
3069 0 test
3059
3070
3060 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3071 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3061 2------------------- test
3072 2------------------- test
3062 1------------------- {node|short}
3073 1------------------- {node|short}
3063 0------------------- test
3074 0------------------- test
3064
3075
3065 Test template string in pad function
3076 Test template string in pad function
3066
3077
3067 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3078 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3068 {0} test
3079 {0} test
3069
3080
3070 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3081 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3071 \{rev} test
3082 \{rev} test
3072
3083
3073 Test ifcontains function
3084 Test ifcontains function
3074
3085
3075 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3086 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3076 2 is in the string
3087 2 is in the string
3077 1 is not
3088 1 is not
3078 0 is in the string
3089 0 is in the string
3079
3090
3080 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3091 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3081 2 did not add a
3092 2 did not add a
3082 1 did not add a
3093 1 did not add a
3083 0 added a
3094 0 added a
3084
3095
3085 Test revset function
3096 Test revset function
3086
3097
3087 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3098 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3088 2 current rev
3099 2 current rev
3089 1 not current rev
3100 1 not current rev
3090 0 not current rev
3101 0 not current rev
3091
3102
3092 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3103 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3093 2 match rev
3104 2 match rev
3094 1 match rev
3105 1 match rev
3095 0 not match rev
3106 0 not match rev
3096
3107
3097 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3108 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3098 2 Parents: 1
3109 2 Parents: 1
3099 1 Parents: 0
3110 1 Parents: 0
3100 0 Parents:
3111 0 Parents:
3101
3112
3102 $ cat >> .hg/hgrc <<EOF
3113 $ cat >> .hg/hgrc <<EOF
3103 > [revsetalias]
3114 > [revsetalias]
3104 > myparents(\$1) = parents(\$1)
3115 > myparents(\$1) = parents(\$1)
3105 > EOF
3116 > EOF
3106 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3117 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3107 2 Parents: 1
3118 2 Parents: 1
3108 1 Parents: 0
3119 1 Parents: 0
3109 0 Parents:
3120 0 Parents:
3110
3121
3111 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3122 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3112 Rev: 2
3123 Rev: 2
3113 Ancestor: 0
3124 Ancestor: 0
3114 Ancestor: 1
3125 Ancestor: 1
3115 Ancestor: 2
3126 Ancestor: 2
3116
3127
3117 Rev: 1
3128 Rev: 1
3118 Ancestor: 0
3129 Ancestor: 0
3119 Ancestor: 1
3130 Ancestor: 1
3120
3131
3121 Rev: 0
3132 Rev: 0
3122 Ancestor: 0
3133 Ancestor: 0
3123
3134
3135 $ hg log --template '{revset("TIP"|lower)}\n' -l1
3136 2
3137
3124 Test active bookmark templating
3138 Test active bookmark templating
3125
3139
3126 $ hg book foo
3140 $ hg book foo
3127 $ hg book bar
3141 $ hg book bar
3128 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3142 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3129 2 bar* foo
3143 2 bar* foo
3130 1
3144 1
3131 0
3145 0
3132 $ hg log --template "{rev} {activebookmark}\n"
3146 $ hg log --template "{rev} {activebookmark}\n"
3133 2 bar
3147 2 bar
3134 1
3148 1
3135 0
3149 0
3136 $ hg bookmarks --inactive bar
3150 $ hg bookmarks --inactive bar
3137 $ hg log --template "{rev} {activebookmark}\n"
3151 $ hg log --template "{rev} {activebookmark}\n"
3138 2
3152 2
3139 1
3153 1
3140 0
3154 0
3141 $ hg book -r1 baz
3155 $ hg book -r1 baz
3142 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3156 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3143 2 bar foo
3157 2 bar foo
3144 1 baz
3158 1 baz
3145 0
3159 0
3146 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3160 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3147 2 t
3161 2 t
3148 1 f
3162 1 f
3149 0 f
3163 0 f
3150
3164
3151 Test stringify on sub expressions
3165 Test stringify on sub expressions
3152
3166
3153 $ cd ..
3167 $ cd ..
3154 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3168 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3155 fourth, second, third
3169 fourth, second, third
3156 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3170 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3157 abc
3171 abc
3158
3172
3159 Test splitlines
3173 Test splitlines
3160
3174
3161 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3175 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3162 @ foo Modify, add, remove, rename
3176 @ foo Modify, add, remove, rename
3163 |
3177 |
3164 o foo future
3178 o foo future
3165 |
3179 |
3166 o foo third
3180 o foo third
3167 |
3181 |
3168 o foo second
3182 o foo second
3169
3183
3170 o foo merge
3184 o foo merge
3171 |\
3185 |\
3172 | o foo new head
3186 | o foo new head
3173 | |
3187 | |
3174 o | foo new branch
3188 o | foo new branch
3175 |/
3189 |/
3176 o foo no user, no domain
3190 o foo no user, no domain
3177 |
3191 |
3178 o foo no person
3192 o foo no person
3179 |
3193 |
3180 o foo other 1
3194 o foo other 1
3181 | foo other 2
3195 | foo other 2
3182 | foo
3196 | foo
3183 | foo other 3
3197 | foo other 3
3184 o foo line 1
3198 o foo line 1
3185 foo line 2
3199 foo line 2
3186
3200
3187 Test startswith
3201 Test startswith
3188 $ hg log -Gv -R a --template "{startswith(desc)}"
3202 $ hg log -Gv -R a --template "{startswith(desc)}"
3189 hg: parse error: startswith expects two arguments
3203 hg: parse error: startswith expects two arguments
3190 [255]
3204 [255]
3191
3205
3192 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3206 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3193 @
3207 @
3194 |
3208 |
3195 o
3209 o
3196 |
3210 |
3197 o
3211 o
3198 |
3212 |
3199 o
3213 o
3200
3214
3201 o
3215 o
3202 |\
3216 |\
3203 | o
3217 | o
3204 | |
3218 | |
3205 o |
3219 o |
3206 |/
3220 |/
3207 o
3221 o
3208 |
3222 |
3209 o
3223 o
3210 |
3224 |
3211 o
3225 o
3212 |
3226 |
3213 o line 1
3227 o line 1
3214 line 2
3228 line 2
3215
3229
3216 Test bad template with better error message
3230 Test bad template with better error message
3217
3231
3218 $ hg log -Gv -R a --template '{desc|user()}'
3232 $ hg log -Gv -R a --template '{desc|user()}'
3219 hg: parse error: expected a symbol, got 'func'
3233 hg: parse error: expected a symbol, got 'func'
3220 [255]
3234 [255]
3221
3235
3222 Test word function (including index out of bounds graceful failure)
3236 Test word function (including index out of bounds graceful failure)
3223
3237
3224 $ hg log -Gv -R a --template "{word('1', desc)}"
3238 $ hg log -Gv -R a --template "{word('1', desc)}"
3225 @ add,
3239 @ add,
3226 |
3240 |
3227 o
3241 o
3228 |
3242 |
3229 o
3243 o
3230 |
3244 |
3231 o
3245 o
3232
3246
3233 o
3247 o
3234 |\
3248 |\
3235 | o head
3249 | o head
3236 | |
3250 | |
3237 o | branch
3251 o | branch
3238 |/
3252 |/
3239 o user,
3253 o user,
3240 |
3254 |
3241 o person
3255 o person
3242 |
3256 |
3243 o 1
3257 o 1
3244 |
3258 |
3245 o 1
3259 o 1
3246
3260
3247
3261
3248 Test word third parameter used as splitter
3262 Test word third parameter used as splitter
3249
3263
3250 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3264 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3251 @ M
3265 @ M
3252 |
3266 |
3253 o future
3267 o future
3254 |
3268 |
3255 o third
3269 o third
3256 |
3270 |
3257 o sec
3271 o sec
3258
3272
3259 o merge
3273 o merge
3260 |\
3274 |\
3261 | o new head
3275 | o new head
3262 | |
3276 | |
3263 o | new branch
3277 o | new branch
3264 |/
3278 |/
3265 o n
3279 o n
3266 |
3280 |
3267 o n
3281 o n
3268 |
3282 |
3269 o
3283 o
3270 |
3284 |
3271 o line 1
3285 o line 1
3272 line 2
3286 line 2
3273
3287
3274 Test word error messages for not enough and too many arguments
3288 Test word error messages for not enough and too many arguments
3275
3289
3276 $ hg log -Gv -R a --template "{word('0')}"
3290 $ hg log -Gv -R a --template "{word('0')}"
3277 hg: parse error: word expects two or three arguments, got 1
3291 hg: parse error: word expects two or three arguments, got 1
3278 [255]
3292 [255]
3279
3293
3280 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3294 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3281 hg: parse error: word expects two or three arguments, got 7
3295 hg: parse error: word expects two or three arguments, got 7
3282 [255]
3296 [255]
3283
3297
3284 Test word for integer literal
3298 Test word for integer literal
3285
3299
3286 $ hg log -R a --template "{word(2, desc)}\n" -r0
3300 $ hg log -R a --template "{word(2, desc)}\n" -r0
3287 line
3301 line
3288
3302
3289 Test word for invalid numbers
3303 Test word for invalid numbers
3290
3304
3291 $ hg log -Gv -R a --template "{word('a', desc)}"
3305 $ hg log -Gv -R a --template "{word('a', desc)}"
3292 hg: parse error: word expects an integer index
3306 hg: parse error: word expects an integer index
3293 [255]
3307 [255]
3294
3308
3295 Test indent and not adding to empty lines
3309 Test indent and not adding to empty lines
3296
3310
3297 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3311 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3298 -----
3312 -----
3299 > line 1
3313 > line 1
3300 >> line 2
3314 >> line 2
3301 -----
3315 -----
3302 > other 1
3316 > other 1
3303 >> other 2
3317 >> other 2
3304
3318
3305 >> other 3
3319 >> other 3
3306
3320
3307 Test with non-strings like dates
3321 Test with non-strings like dates
3308
3322
3309 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3323 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3310 1200000.00
3324 1200000.00
3311 1300000.00
3325 1300000.00
@@ -1,141 +1,154
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3 $ echo 0 > a
3 $ echo 0 > a
4 $ echo 0 > b
4 $ echo 0 > b
5 $ echo 0 > t.h
5 $ echo 0 > t.h
6 $ mkdir t
6 $ mkdir t
7 $ echo 0 > t/x
7 $ echo 0 > t/x
8 $ echo 0 > t/b
8 $ echo 0 > t/b
9 $ echo 0 > t/e.h
9 $ echo 0 > t/e.h
10 $ mkdir dir.h
10 $ mkdir dir.h
11 $ echo 0 > dir.h/foo
11 $ echo 0 > dir.h/foo
12
12
13 $ hg ci -A -m m
13 $ hg ci -A -m m
14 adding a
14 adding a
15 adding b
15 adding b
16 adding dir.h/foo
16 adding dir.h/foo
17 adding t.h
17 adding t.h
18 adding t/b
18 adding t/b
19 adding t/e.h
19 adding t/e.h
20 adding t/x
20 adding t/x
21
21
22 $ touch nottracked
22 $ touch nottracked
23
23
24 $ hg locate a
24 $ hg locate a
25 a
25 a
26
26
27 $ hg locate NONEXISTENT
27 $ hg locate NONEXISTENT
28 [1]
28 [1]
29
29
30 $ hg locate
30 $ hg locate
31 a
31 a
32 b
32 b
33 dir.h/foo
33 dir.h/foo
34 t.h
34 t.h
35 t/b
35 t/b
36 t/e.h
36 t/e.h
37 t/x
37 t/x
38
38
39 $ hg rm a
39 $ hg rm a
40 $ hg ci -m m
40 $ hg ci -m m
41
41
42 $ hg locate a
42 $ hg locate a
43 [1]
43 [1]
44 $ hg locate NONEXISTENT
44 $ hg locate NONEXISTENT
45 [1]
45 [1]
46 $ hg locate relpath:NONEXISTENT
46 $ hg locate relpath:NONEXISTENT
47 [1]
47 [1]
48 $ hg locate
48 $ hg locate
49 b
49 b
50 dir.h/foo
50 dir.h/foo
51 t.h
51 t.h
52 t/b
52 t/b
53 t/e.h
53 t/e.h
54 t/x
54 t/x
55 $ hg locate -r 0 a
55 $ hg locate -r 0 a
56 a
56 a
57 $ hg locate -r 0 NONEXISTENT
57 $ hg locate -r 0 NONEXISTENT
58 [1]
58 [1]
59 $ hg locate -r 0 relpath:NONEXISTENT
59 $ hg locate -r 0 relpath:NONEXISTENT
60 [1]
60 [1]
61 $ hg locate -r 0
61 $ hg locate -r 0
62 a
62 a
63 b
63 b
64 dir.h/foo
64 dir.h/foo
65 t.h
65 t.h
66 t/b
66 t/b
67 t/e.h
67 t/e.h
68 t/x
68 t/x
69
69
70 -I/-X with relative path should work:
70 -I/-X with relative path should work:
71
71
72 $ cd t
72 $ cd t
73 $ hg locate
73 $ hg locate
74 b
74 b
75 dir.h/foo
75 dir.h/foo
76 t.h
76 t.h
77 t/b
77 t/b
78 t/e.h
78 t/e.h
79 t/x
79 t/x
80 $ hg locate -I ../t
80 $ hg locate -I ../t
81 t/b
81 t/b
82 t/e.h
82 t/e.h
83 t/x
83 t/x
84
84
85 Issue294: hg remove --after dir fails when dir.* also exists
85 Issue294: hg remove --after dir fails when dir.* also exists
86
86
87 $ cd ..
87 $ cd ..
88 $ rm -r t
88 $ rm -r t
89
89
90 $ hg rm t/b
90 $ hg rm t/b
91
91
92 $ hg locate 't/**'
92 $ hg locate 't/**'
93 t/b (glob)
93 t/b (glob)
94 t/e.h (glob)
94 t/e.h (glob)
95 t/x (glob)
95 t/x (glob)
96
96
97 $ hg files
97 $ hg files
98 b
98 b
99 dir.h/foo (glob)
99 dir.h/foo (glob)
100 t.h
100 t.h
101 t/e.h (glob)
101 t/e.h (glob)
102 t/x (glob)
102 t/x (glob)
103 $ hg files b
103 $ hg files b
104 b
104 b
105
105
106 $ mkdir otherdir
106 $ mkdir otherdir
107 $ cd otherdir
107 $ cd otherdir
108
108
109 $ hg files path:
110 ../b (glob)
111 ../dir.h/foo (glob)
112 ../t.h (glob)
113 ../t/e.h (glob)
114 ../t/x (glob)
115 $ hg files path:.
116 ../b (glob)
117 ../dir.h/foo (glob)
118 ../t.h (glob)
119 ../t/e.h (glob)
120 ../t/x (glob)
121
109 $ hg locate b
122 $ hg locate b
110 ../b (glob)
123 ../b (glob)
111 ../t/b (glob)
124 ../t/b (glob)
112 $ hg locate '*.h'
125 $ hg locate '*.h'
113 ../t.h (glob)
126 ../t.h (glob)
114 ../t/e.h (glob)
127 ../t/e.h (glob)
115 $ hg locate path:t/x
128 $ hg locate path:t/x
116 ../t/x (glob)
129 ../t/x (glob)
117 $ hg locate 're:.*\.h$'
130 $ hg locate 're:.*\.h$'
118 ../t.h (glob)
131 ../t.h (glob)
119 ../t/e.h (glob)
132 ../t/e.h (glob)
120 $ hg locate -r 0 b
133 $ hg locate -r 0 b
121 ../b (glob)
134 ../b (glob)
122 ../t/b (glob)
135 ../t/b (glob)
123 $ hg locate -r 0 '*.h'
136 $ hg locate -r 0 '*.h'
124 ../t.h (glob)
137 ../t.h (glob)
125 ../t/e.h (glob)
138 ../t/e.h (glob)
126 $ hg locate -r 0 path:t/x
139 $ hg locate -r 0 path:t/x
127 ../t/x (glob)
140 ../t/x (glob)
128 $ hg locate -r 0 're:.*\.h$'
141 $ hg locate -r 0 're:.*\.h$'
129 ../t.h (glob)
142 ../t.h (glob)
130 ../t/e.h (glob)
143 ../t/e.h (glob)
131
144
132 $ hg files
145 $ hg files
133 ../b (glob)
146 ../b (glob)
134 ../dir.h/foo (glob)
147 ../dir.h/foo (glob)
135 ../t.h (glob)
148 ../t.h (glob)
136 ../t/e.h (glob)
149 ../t/e.h (glob)
137 ../t/x (glob)
150 ../t/x (glob)
138 $ hg files .
151 $ hg files .
139 [1]
152 [1]
140
153
141 $ cd ../..
154 $ cd ../..
General Comments 0
You need to be logged in to leave comments. Login now