##// END OF EJS Templates
templater: implement _hybrid.__contains__ so that ifcontains can accept dict...
Yuya Nishihara -
r24240:bd504d90 default
parent child Browse files
Show More
@@ -1,457 +1,461 b''
1 # templatekw.py - common changeset template keywords
1 # templatekw.py - common changeset template keywords
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2009 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 node import hex
8 from node import hex
9 import patch, util, error
9 import patch, util, error
10 import hbisect
10 import hbisect
11
11
12 # This helper class allows us to handle both:
12 # This helper class allows us to handle both:
13 # "{files}" (legacy command-line-specific list hack) and
13 # "{files}" (legacy command-line-specific list hack) and
14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
15 # and to access raw values:
16 # "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
15
17
16 class _hybrid(object):
18 class _hybrid(object):
17 def __init__(self, gen, values, makemap, joinfmt=None):
19 def __init__(self, gen, values, makemap, joinfmt=None):
18 self.gen = gen
20 self.gen = gen
19 self.values = values
21 self.values = values
20 self._makemap = makemap
22 self._makemap = makemap
21 if joinfmt:
23 if joinfmt:
22 self.joinfmt = joinfmt
24 self.joinfmt = joinfmt
23 else:
25 else:
24 self.joinfmt = lambda x: x.values()[0]
26 self.joinfmt = lambda x: x.values()[0]
25 def __iter__(self):
27 def __iter__(self):
26 return self.gen
28 return self.gen
27 def __call__(self):
29 def __call__(self):
28 makemap = self._makemap
30 makemap = self._makemap
29 for x in self.values:
31 for x in self.values:
30 yield makemap(x)
32 yield makemap(x)
33 def __contains__(self, x):
34 return x in self.values
31 def __len__(self):
35 def __len__(self):
32 return len(self.values)
36 return len(self.values)
33
37
34 def showlist(name, values, plural=None, element=None, **args):
38 def showlist(name, values, plural=None, element=None, **args):
35 if not element:
39 if not element:
36 element = name
40 element = name
37 f = _showlist(name, values, plural, **args)
41 f = _showlist(name, values, plural, **args)
38 return _hybrid(f, values, lambda x: {element: x})
42 return _hybrid(f, values, lambda x: {element: x})
39
43
40 def _showlist(name, values, plural=None, **args):
44 def _showlist(name, values, plural=None, **args):
41 '''expand set of values.
45 '''expand set of values.
42 name is name of key in template map.
46 name is name of key in template map.
43 values is list of strings or dicts.
47 values is list of strings or dicts.
44 plural is plural of name, if not simply name + 's'.
48 plural is plural of name, if not simply name + 's'.
45
49
46 expansion works like this, given name 'foo'.
50 expansion works like this, given name 'foo'.
47
51
48 if values is empty, expand 'no_foos'.
52 if values is empty, expand 'no_foos'.
49
53
50 if 'foo' not in template map, return values as a string,
54 if 'foo' not in template map, return values as a string,
51 joined by space.
55 joined by space.
52
56
53 expand 'start_foos'.
57 expand 'start_foos'.
54
58
55 for each value, expand 'foo'. if 'last_foo' in template
59 for each value, expand 'foo'. if 'last_foo' in template
56 map, expand it instead of 'foo' for last key.
60 map, expand it instead of 'foo' for last key.
57
61
58 expand 'end_foos'.
62 expand 'end_foos'.
59 '''
63 '''
60 templ = args['templ']
64 templ = args['templ']
61 if plural:
65 if plural:
62 names = plural
66 names = plural
63 else: names = name + 's'
67 else: names = name + 's'
64 if not values:
68 if not values:
65 noname = 'no_' + names
69 noname = 'no_' + names
66 if noname in templ:
70 if noname in templ:
67 yield templ(noname, **args)
71 yield templ(noname, **args)
68 return
72 return
69 if name not in templ:
73 if name not in templ:
70 if isinstance(values[0], str):
74 if isinstance(values[0], str):
71 yield ' '.join(values)
75 yield ' '.join(values)
72 else:
76 else:
73 for v in values:
77 for v in values:
74 yield dict(v, **args)
78 yield dict(v, **args)
75 return
79 return
76 startname = 'start_' + names
80 startname = 'start_' + names
77 if startname in templ:
81 if startname in templ:
78 yield templ(startname, **args)
82 yield templ(startname, **args)
79 vargs = args.copy()
83 vargs = args.copy()
80 def one(v, tag=name):
84 def one(v, tag=name):
81 try:
85 try:
82 vargs.update(v)
86 vargs.update(v)
83 except (AttributeError, ValueError):
87 except (AttributeError, ValueError):
84 try:
88 try:
85 for a, b in v:
89 for a, b in v:
86 vargs[a] = b
90 vargs[a] = b
87 except ValueError:
91 except ValueError:
88 vargs[name] = v
92 vargs[name] = v
89 return templ(tag, **vargs)
93 return templ(tag, **vargs)
90 lastname = 'last_' + name
94 lastname = 'last_' + name
91 if lastname in templ:
95 if lastname in templ:
92 last = values.pop()
96 last = values.pop()
93 else:
97 else:
94 last = None
98 last = None
95 for v in values:
99 for v in values:
96 yield one(v)
100 yield one(v)
97 if last is not None:
101 if last is not None:
98 yield one(last, tag=lastname)
102 yield one(last, tag=lastname)
99 endname = 'end_' + names
103 endname = 'end_' + names
100 if endname in templ:
104 if endname in templ:
101 yield templ(endname, **args)
105 yield templ(endname, **args)
102
106
103 def getfiles(repo, ctx, revcache):
107 def getfiles(repo, ctx, revcache):
104 if 'files' not in revcache:
108 if 'files' not in revcache:
105 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
109 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
106 return revcache['files']
110 return revcache['files']
107
111
108 def getlatesttags(repo, ctx, cache):
112 def getlatesttags(repo, ctx, cache):
109 '''return date, distance and name for the latest tag of rev'''
113 '''return date, distance and name for the latest tag of rev'''
110
114
111 if 'latesttags' not in cache:
115 if 'latesttags' not in cache:
112 # Cache mapping from rev to a tuple with tag date, tag
116 # Cache mapping from rev to a tuple with tag date, tag
113 # distance and tag name
117 # distance and tag name
114 cache['latesttags'] = {-1: (0, 0, 'null')}
118 cache['latesttags'] = {-1: (0, 0, 'null')}
115 latesttags = cache['latesttags']
119 latesttags = cache['latesttags']
116
120
117 rev = ctx.rev()
121 rev = ctx.rev()
118 todo = [rev]
122 todo = [rev]
119 while todo:
123 while todo:
120 rev = todo.pop()
124 rev = todo.pop()
121 if rev in latesttags:
125 if rev in latesttags:
122 continue
126 continue
123 ctx = repo[rev]
127 ctx = repo[rev]
124 tags = [t for t in ctx.tags()
128 tags = [t for t in ctx.tags()
125 if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
129 if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
126 if tags:
130 if tags:
127 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
131 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
128 continue
132 continue
129 try:
133 try:
130 # The tuples are laid out so the right one can be found by
134 # The tuples are laid out so the right one can be found by
131 # comparison.
135 # comparison.
132 pdate, pdist, ptag = max(
136 pdate, pdist, ptag = max(
133 latesttags[p.rev()] for p in ctx.parents())
137 latesttags[p.rev()] for p in ctx.parents())
134 except KeyError:
138 except KeyError:
135 # Cache miss - recurse
139 # Cache miss - recurse
136 todo.append(rev)
140 todo.append(rev)
137 todo.extend(p.rev() for p in ctx.parents())
141 todo.extend(p.rev() for p in ctx.parents())
138 continue
142 continue
139 latesttags[rev] = pdate, pdist + 1, ptag
143 latesttags[rev] = pdate, pdist + 1, ptag
140 return latesttags[rev]
144 return latesttags[rev]
141
145
142 def getrenamedfn(repo, endrev=None):
146 def getrenamedfn(repo, endrev=None):
143 rcache = {}
147 rcache = {}
144 if endrev is None:
148 if endrev is None:
145 endrev = len(repo)
149 endrev = len(repo)
146
150
147 def getrenamed(fn, rev):
151 def getrenamed(fn, rev):
148 '''looks up all renames for a file (up to endrev) the first
152 '''looks up all renames for a file (up to endrev) the first
149 time the file is given. It indexes on the changerev and only
153 time the file is given. It indexes on the changerev and only
150 parses the manifest if linkrev != changerev.
154 parses the manifest if linkrev != changerev.
151 Returns rename info for fn at changerev rev.'''
155 Returns rename info for fn at changerev rev.'''
152 if fn not in rcache:
156 if fn not in rcache:
153 rcache[fn] = {}
157 rcache[fn] = {}
154 fl = repo.file(fn)
158 fl = repo.file(fn)
155 for i in fl:
159 for i in fl:
156 lr = fl.linkrev(i)
160 lr = fl.linkrev(i)
157 renamed = fl.renamed(fl.node(i))
161 renamed = fl.renamed(fl.node(i))
158 rcache[fn][lr] = renamed
162 rcache[fn][lr] = renamed
159 if lr >= endrev:
163 if lr >= endrev:
160 break
164 break
161 if rev in rcache[fn]:
165 if rev in rcache[fn]:
162 return rcache[fn][rev]
166 return rcache[fn][rev]
163
167
164 # If linkrev != rev (i.e. rev not found in rcache) fallback to
168 # If linkrev != rev (i.e. rev not found in rcache) fallback to
165 # filectx logic.
169 # filectx logic.
166 try:
170 try:
167 return repo[rev][fn].renamed()
171 return repo[rev][fn].renamed()
168 except error.LookupError:
172 except error.LookupError:
169 return None
173 return None
170
174
171 return getrenamed
175 return getrenamed
172
176
173
177
174 def showauthor(repo, ctx, templ, **args):
178 def showauthor(repo, ctx, templ, **args):
175 """:author: String. The unmodified author of the changeset."""
179 """:author: String. The unmodified author of the changeset."""
176 return ctx.user()
180 return ctx.user()
177
181
178 def showbisect(repo, ctx, templ, **args):
182 def showbisect(repo, ctx, templ, **args):
179 """:bisect: String. The changeset bisection status."""
183 """:bisect: String. The changeset bisection status."""
180 return hbisect.label(repo, ctx.node())
184 return hbisect.label(repo, ctx.node())
181
185
182 def showbranch(**args):
186 def showbranch(**args):
183 """:branch: String. The name of the branch on which the changeset was
187 """:branch: String. The name of the branch on which the changeset was
184 committed.
188 committed.
185 """
189 """
186 return args['ctx'].branch()
190 return args['ctx'].branch()
187
191
188 def showbranches(**args):
192 def showbranches(**args):
189 """:branches: List of strings. The name of the branch on which the
193 """:branches: List of strings. The name of the branch on which the
190 changeset was committed. Will be empty if the branch name was
194 changeset was committed. Will be empty if the branch name was
191 default.
195 default.
192 """
196 """
193 branch = args['ctx'].branch()
197 branch = args['ctx'].branch()
194 if branch != 'default':
198 if branch != 'default':
195 return showlist('branch', [branch], plural='branches', **args)
199 return showlist('branch', [branch], plural='branches', **args)
196 return showlist('branch', [], plural='branches', **args)
200 return showlist('branch', [], plural='branches', **args)
197
201
198 def showbookmarks(**args):
202 def showbookmarks(**args):
199 """:bookmarks: List of strings. Any bookmarks associated with the
203 """:bookmarks: List of strings. Any bookmarks associated with the
200 changeset.
204 changeset.
201 """
205 """
202 repo = args['ctx']._repo
206 repo = args['ctx']._repo
203 bookmarks = args['ctx'].bookmarks()
207 bookmarks = args['ctx'].bookmarks()
204 current = repo._bookmarkcurrent
208 current = repo._bookmarkcurrent
205 makemap = lambda v: {'bookmark': v, 'current': current}
209 makemap = lambda v: {'bookmark': v, 'current': current}
206 f = _showlist('bookmark', bookmarks, **args)
210 f = _showlist('bookmark', bookmarks, **args)
207 return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
211 return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
208
212
209 def showchildren(**args):
213 def showchildren(**args):
210 """:children: List of strings. The children of the changeset."""
214 """:children: List of strings. The children of the changeset."""
211 ctx = args['ctx']
215 ctx = args['ctx']
212 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
216 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
213 return showlist('children', childrevs, element='child', **args)
217 return showlist('children', childrevs, element='child', **args)
214
218
215 def showcurrentbookmark(**args):
219 def showcurrentbookmark(**args):
216 """:currentbookmark: String. The active bookmark, if it is
220 """:currentbookmark: String. The active bookmark, if it is
217 associated with the changeset"""
221 associated with the changeset"""
218 import bookmarks as bookmarks # to avoid circular import issues
222 import bookmarks as bookmarks # to avoid circular import issues
219 repo = args['repo']
223 repo = args['repo']
220 if bookmarks.iscurrent(repo):
224 if bookmarks.iscurrent(repo):
221 current = repo._bookmarkcurrent
225 current = repo._bookmarkcurrent
222 if current in args['ctx'].bookmarks():
226 if current in args['ctx'].bookmarks():
223 return current
227 return current
224 return ''
228 return ''
225
229
226 def showdate(repo, ctx, templ, **args):
230 def showdate(repo, ctx, templ, **args):
227 """:date: Date information. The date when the changeset was committed."""
231 """:date: Date information. The date when the changeset was committed."""
228 return ctx.date()
232 return ctx.date()
229
233
230 def showdescription(repo, ctx, templ, **args):
234 def showdescription(repo, ctx, templ, **args):
231 """:desc: String. The text of the changeset description."""
235 """:desc: String. The text of the changeset description."""
232 return ctx.description().strip()
236 return ctx.description().strip()
233
237
234 def showdiffstat(repo, ctx, templ, **args):
238 def showdiffstat(repo, ctx, templ, **args):
235 """:diffstat: String. Statistics of changes with the following format:
239 """:diffstat: String. Statistics of changes with the following format:
236 "modified files: +added/-removed lines"
240 "modified files: +added/-removed lines"
237 """
241 """
238 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
242 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
239 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
243 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
240 return '%s: +%s/-%s' % (len(stats), adds, removes)
244 return '%s: +%s/-%s' % (len(stats), adds, removes)
241
245
242 def showextras(**args):
246 def showextras(**args):
243 """:extras: List of dicts with key, value entries of the 'extras'
247 """:extras: List of dicts with key, value entries of the 'extras'
244 field of this changeset."""
248 field of this changeset."""
245 extras = args['ctx'].extra()
249 extras = args['ctx'].extra()
246 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
250 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
247 makemap = lambda k: {'key': k, 'value': extras[k]}
251 makemap = lambda k: {'key': k, 'value': extras[k]}
248 c = [makemap(k) for k in extras]
252 c = [makemap(k) for k in extras]
249 f = _showlist('extra', c, plural='extras', **args)
253 f = _showlist('extra', c, plural='extras', **args)
250 return _hybrid(f, extras, makemap,
254 return _hybrid(f, extras, makemap,
251 lambda x: '%s=%s' % (x['key'], x['value']))
255 lambda x: '%s=%s' % (x['key'], x['value']))
252
256
253 def showfileadds(**args):
257 def showfileadds(**args):
254 """:file_adds: List of strings. Files added by this changeset."""
258 """:file_adds: List of strings. Files added by this changeset."""
255 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
259 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
256 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
260 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
257 element='file', **args)
261 element='file', **args)
258
262
259 def showfilecopies(**args):
263 def showfilecopies(**args):
260 """:file_copies: List of strings. Files copied in this changeset with
264 """:file_copies: List of strings. Files copied in this changeset with
261 their sources.
265 their sources.
262 """
266 """
263 cache, ctx = args['cache'], args['ctx']
267 cache, ctx = args['cache'], args['ctx']
264 copies = args['revcache'].get('copies')
268 copies = args['revcache'].get('copies')
265 if copies is None:
269 if copies is None:
266 if 'getrenamed' not in cache:
270 if 'getrenamed' not in cache:
267 cache['getrenamed'] = getrenamedfn(args['repo'])
271 cache['getrenamed'] = getrenamedfn(args['repo'])
268 copies = []
272 copies = []
269 getrenamed = cache['getrenamed']
273 getrenamed = cache['getrenamed']
270 for fn in ctx.files():
274 for fn in ctx.files():
271 rename = getrenamed(fn, ctx.rev())
275 rename = getrenamed(fn, ctx.rev())
272 if rename:
276 if rename:
273 copies.append((fn, rename[0]))
277 copies.append((fn, rename[0]))
274
278
275 copies = util.sortdict(copies)
279 copies = util.sortdict(copies)
276 makemap = lambda k: {'name': k, 'source': copies[k]}
280 makemap = lambda k: {'name': k, 'source': copies[k]}
277 c = [makemap(k) for k in copies]
281 c = [makemap(k) for k in copies]
278 f = _showlist('file_copy', c, plural='file_copies', **args)
282 f = _showlist('file_copy', c, plural='file_copies', **args)
279 return _hybrid(f, copies, makemap,
283 return _hybrid(f, copies, makemap,
280 lambda x: '%s (%s)' % (x['name'], x['source']))
284 lambda x: '%s (%s)' % (x['name'], x['source']))
281
285
282 # showfilecopiesswitch() displays file copies only if copy records are
286 # showfilecopiesswitch() displays file copies only if copy records are
283 # provided before calling the templater, usually with a --copies
287 # provided before calling the templater, usually with a --copies
284 # command line switch.
288 # command line switch.
285 def showfilecopiesswitch(**args):
289 def showfilecopiesswitch(**args):
286 """:file_copies_switch: List of strings. Like "file_copies" but displayed
290 """:file_copies_switch: List of strings. Like "file_copies" but displayed
287 only if the --copied switch is set.
291 only if the --copied switch is set.
288 """
292 """
289 copies = args['revcache'].get('copies') or []
293 copies = args['revcache'].get('copies') or []
290 copies = util.sortdict(copies)
294 copies = util.sortdict(copies)
291 makemap = lambda k: {'name': k, 'source': copies[k]}
295 makemap = lambda k: {'name': k, 'source': copies[k]}
292 c = [makemap(k) for k in copies]
296 c = [makemap(k) for k in copies]
293 f = _showlist('file_copy', c, plural='file_copies', **args)
297 f = _showlist('file_copy', c, plural='file_copies', **args)
294 return _hybrid(f, copies, makemap,
298 return _hybrid(f, copies, makemap,
295 lambda x: '%s (%s)' % (x['name'], x['source']))
299 lambda x: '%s (%s)' % (x['name'], x['source']))
296
300
297 def showfiledels(**args):
301 def showfiledels(**args):
298 """:file_dels: List of strings. Files removed by this changeset."""
302 """:file_dels: List of strings. Files removed by this changeset."""
299 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
303 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
300 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
304 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
301 element='file', **args)
305 element='file', **args)
302
306
303 def showfilemods(**args):
307 def showfilemods(**args):
304 """:file_mods: List of strings. Files modified by this changeset."""
308 """:file_mods: List of strings. Files modified by this changeset."""
305 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
309 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
306 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
310 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
307 element='file', **args)
311 element='file', **args)
308
312
309 def showfiles(**args):
313 def showfiles(**args):
310 """:files: List of strings. All files modified, added, or removed by this
314 """:files: List of strings. All files modified, added, or removed by this
311 changeset.
315 changeset.
312 """
316 """
313 return showlist('file', args['ctx'].files(), **args)
317 return showlist('file', args['ctx'].files(), **args)
314
318
315 def showlatesttag(repo, ctx, templ, cache, **args):
319 def showlatesttag(repo, ctx, templ, cache, **args):
316 """:latesttag: String. Most recent global tag in the ancestors of this
320 """:latesttag: String. Most recent global tag in the ancestors of this
317 changeset.
321 changeset.
318 """
322 """
319 return getlatesttags(repo, ctx, cache)[2]
323 return getlatesttags(repo, ctx, cache)[2]
320
324
321 def showlatesttagdistance(repo, ctx, templ, cache, **args):
325 def showlatesttagdistance(repo, ctx, templ, cache, **args):
322 """:latesttagdistance: Integer. Longest path to the latest tag."""
326 """:latesttagdistance: Integer. Longest path to the latest tag."""
323 return getlatesttags(repo, ctx, cache)[1]
327 return getlatesttags(repo, ctx, cache)[1]
324
328
325 def showmanifest(**args):
329 def showmanifest(**args):
326 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
330 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
327 args = args.copy()
331 args = args.copy()
328 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
332 args.update({'rev': repo.manifest.rev(ctx.changeset()[0]),
329 'node': hex(ctx.changeset()[0])})
333 'node': hex(ctx.changeset()[0])})
330 return templ('manifest', **args)
334 return templ('manifest', **args)
331
335
332 def shownode(repo, ctx, templ, **args):
336 def shownode(repo, ctx, templ, **args):
333 """:node: String. The changeset identification hash, as a 40 hexadecimal
337 """:node: String. The changeset identification hash, as a 40 hexadecimal
334 digit string.
338 digit string.
335 """
339 """
336 return ctx.hex()
340 return ctx.hex()
337
341
338 def showp1rev(repo, ctx, templ, **args):
342 def showp1rev(repo, ctx, templ, **args):
339 """:p1rev: Integer. The repository-local revision number of the changeset's
343 """:p1rev: Integer. The repository-local revision number of the changeset's
340 first parent, or -1 if the changeset has no parents."""
344 first parent, or -1 if the changeset has no parents."""
341 return ctx.p1().rev()
345 return ctx.p1().rev()
342
346
343 def showp2rev(repo, ctx, templ, **args):
347 def showp2rev(repo, ctx, templ, **args):
344 """:p2rev: Integer. The repository-local revision number of the changeset's
348 """:p2rev: Integer. The repository-local revision number of the changeset's
345 second parent, or -1 if the changeset has no second parent."""
349 second parent, or -1 if the changeset has no second parent."""
346 return ctx.p2().rev()
350 return ctx.p2().rev()
347
351
348 def showp1node(repo, ctx, templ, **args):
352 def showp1node(repo, ctx, templ, **args):
349 """:p1node: String. The identification hash of the changeset's first parent,
353 """:p1node: String. The identification hash of the changeset's first parent,
350 as a 40 digit hexadecimal string. If the changeset has no parents, all
354 as a 40 digit hexadecimal string. If the changeset has no parents, all
351 digits are 0."""
355 digits are 0."""
352 return ctx.p1().hex()
356 return ctx.p1().hex()
353
357
354 def showp2node(repo, ctx, templ, **args):
358 def showp2node(repo, ctx, templ, **args):
355 """:p2node: String. The identification hash of the changeset's second
359 """:p2node: String. The identification hash of the changeset's second
356 parent, as a 40 digit hexadecimal string. If the changeset has no second
360 parent, as a 40 digit hexadecimal string. If the changeset has no second
357 parent, all digits are 0."""
361 parent, all digits are 0."""
358 return ctx.p2().hex()
362 return ctx.p2().hex()
359
363
360 def showphase(repo, ctx, templ, **args):
364 def showphase(repo, ctx, templ, **args):
361 """:phase: String. The changeset phase name."""
365 """:phase: String. The changeset phase name."""
362 return ctx.phasestr()
366 return ctx.phasestr()
363
367
364 def showphaseidx(repo, ctx, templ, **args):
368 def showphaseidx(repo, ctx, templ, **args):
365 """:phaseidx: Integer. The changeset phase index."""
369 """:phaseidx: Integer. The changeset phase index."""
366 return ctx.phase()
370 return ctx.phase()
367
371
368 def showrev(repo, ctx, templ, **args):
372 def showrev(repo, ctx, templ, **args):
369 """:rev: Integer. The repository-local changeset revision number."""
373 """:rev: Integer. The repository-local changeset revision number."""
370 return ctx.rev()
374 return ctx.rev()
371
375
372 def showsubrepos(**args):
376 def showsubrepos(**args):
373 """:subrepos: List of strings. Updated subrepositories in the changeset."""
377 """:subrepos: List of strings. Updated subrepositories in the changeset."""
374 ctx = args['ctx']
378 ctx = args['ctx']
375 substate = ctx.substate
379 substate = ctx.substate
376 if not substate:
380 if not substate:
377 return showlist('subrepo', [], **args)
381 return showlist('subrepo', [], **args)
378 psubstate = ctx.parents()[0].substate or {}
382 psubstate = ctx.parents()[0].substate or {}
379 subrepos = []
383 subrepos = []
380 for sub in substate:
384 for sub in substate:
381 if sub not in psubstate or substate[sub] != psubstate[sub]:
385 if sub not in psubstate or substate[sub] != psubstate[sub]:
382 subrepos.append(sub) # modified or newly added in ctx
386 subrepos.append(sub) # modified or newly added in ctx
383 for sub in psubstate:
387 for sub in psubstate:
384 if sub not in substate:
388 if sub not in substate:
385 subrepos.append(sub) # removed in ctx
389 subrepos.append(sub) # removed in ctx
386 return showlist('subrepo', sorted(subrepos), **args)
390 return showlist('subrepo', sorted(subrepos), **args)
387
391
388 def shownames(namespace, **args):
392 def shownames(namespace, **args):
389 """helper method to generate a template keyword for a namespace"""
393 """helper method to generate a template keyword for a namespace"""
390 ctx = args['ctx']
394 ctx = args['ctx']
391 repo = ctx._repo
395 repo = ctx._repo
392 ns = repo.names[namespace]
396 ns = repo.names[namespace]
393 names = ns.names(repo, ctx.node())
397 names = ns.names(repo, ctx.node())
394 return showlist(ns.templatename, names, plural=namespace, **args)
398 return showlist(ns.templatename, names, plural=namespace, **args)
395
399
396 # don't remove "showtags" definition, even though namespaces will put
400 # don't remove "showtags" definition, even though namespaces will put
397 # a helper function for "tags" keyword into "keywords" map automatically,
401 # a helper function for "tags" keyword into "keywords" map automatically,
398 # because online help text is built without namespaces initialization
402 # because online help text is built without namespaces initialization
399 def showtags(**args):
403 def showtags(**args):
400 """:tags: List of strings. Any tags associated with the changeset."""
404 """:tags: List of strings. Any tags associated with the changeset."""
401 return shownames('tags', **args)
405 return shownames('tags', **args)
402
406
403 # keywords are callables like:
407 # keywords are callables like:
404 # fn(repo, ctx, templ, cache, revcache, **args)
408 # fn(repo, ctx, templ, cache, revcache, **args)
405 # with:
409 # with:
406 # repo - current repository instance
410 # repo - current repository instance
407 # ctx - the changectx being displayed
411 # ctx - the changectx being displayed
408 # templ - the templater instance
412 # templ - the templater instance
409 # cache - a cache dictionary for the whole templater run
413 # cache - a cache dictionary for the whole templater run
410 # revcache - a cache dictionary for the current revision
414 # revcache - a cache dictionary for the current revision
411 keywords = {
415 keywords = {
412 'author': showauthor,
416 'author': showauthor,
413 'bisect': showbisect,
417 'bisect': showbisect,
414 'branch': showbranch,
418 'branch': showbranch,
415 'branches': showbranches,
419 'branches': showbranches,
416 'bookmarks': showbookmarks,
420 'bookmarks': showbookmarks,
417 'children': showchildren,
421 'children': showchildren,
418 'currentbookmark': showcurrentbookmark,
422 'currentbookmark': showcurrentbookmark,
419 'date': showdate,
423 'date': showdate,
420 'desc': showdescription,
424 'desc': showdescription,
421 'diffstat': showdiffstat,
425 'diffstat': showdiffstat,
422 'extras': showextras,
426 'extras': showextras,
423 'file_adds': showfileadds,
427 'file_adds': showfileadds,
424 'file_copies': showfilecopies,
428 'file_copies': showfilecopies,
425 'file_copies_switch': showfilecopiesswitch,
429 'file_copies_switch': showfilecopiesswitch,
426 'file_dels': showfiledels,
430 'file_dels': showfiledels,
427 'file_mods': showfilemods,
431 'file_mods': showfilemods,
428 'files': showfiles,
432 'files': showfiles,
429 'latesttag': showlatesttag,
433 'latesttag': showlatesttag,
430 'latesttagdistance': showlatesttagdistance,
434 'latesttagdistance': showlatesttagdistance,
431 'manifest': showmanifest,
435 'manifest': showmanifest,
432 'node': shownode,
436 'node': shownode,
433 'p1rev': showp1rev,
437 'p1rev': showp1rev,
434 'p1node': showp1node,
438 'p1node': showp1node,
435 'p2rev': showp2rev,
439 'p2rev': showp2rev,
436 'p2node': showp2node,
440 'p2node': showp2node,
437 'phase': showphase,
441 'phase': showphase,
438 'phaseidx': showphaseidx,
442 'phaseidx': showphaseidx,
439 'rev': showrev,
443 'rev': showrev,
440 'subrepos': showsubrepos,
444 'subrepos': showsubrepos,
441 'tags': showtags,
445 'tags': showtags,
442 }
446 }
443
447
444 def _showparents(**args):
448 def _showparents(**args):
445 """:parents: List of strings. The parents of the changeset in "rev:node"
449 """:parents: List of strings. The parents of the changeset in "rev:node"
446 format. If the changeset has only one "natural" parent (the predecessor
450 format. If the changeset has only one "natural" parent (the predecessor
447 revision) nothing is shown."""
451 revision) nothing is shown."""
448 pass
452 pass
449
453
450 dockeywords = {
454 dockeywords = {
451 'parents': _showparents,
455 'parents': _showparents,
452 }
456 }
453 dockeywords.update(keywords)
457 dockeywords.update(keywords)
454 del dockeywords['branches']
458 del dockeywords['branches']
455
459
456 # tell hggettext to extract docstrings from these functions:
460 # tell hggettext to extract docstrings from these functions:
457 i18nfunctions = dockeywords.values()
461 i18nfunctions = dockeywords.values()
@@ -1,761 +1,758 b''
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 "symbol": (0, ("symbol",), None),
23 "symbol": (0, ("symbol",), None),
24 "string": (0, ("string",), None),
24 "string": (0, ("string",), None),
25 "rawstring": (0, ("rawstring",), None),
25 "rawstring": (0, ("rawstring",), None),
26 "end": (0, None, None),
26 "end": (0, None, None),
27 }
27 }
28
28
29 def tokenizer(data):
29 def tokenizer(data):
30 program, start, end = data
30 program, start, end = data
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 decode and 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.isalnum() or c in '_':
62 elif c.isalnum() or c in '_':
63 s = pos
63 s = pos
64 pos += 1
64 pos += 1
65 while pos < end: # find end of symbol
65 while pos < end: # find end of symbol
66 d = program[pos]
66 d = program[pos]
67 if not (d.isalnum() or d == "_"):
67 if not (d.isalnum() or d == "_"):
68 break
68 break
69 pos += 1
69 pos += 1
70 sym = program[s:pos]
70 sym = program[s:pos]
71 yield ('symbol', sym, s)
71 yield ('symbol', sym, s)
72 pos -= 1
72 pos -= 1
73 elif c == '}':
73 elif c == '}':
74 pos += 1
74 pos += 1
75 break
75 break
76 else:
76 else:
77 raise error.ParseError(_("syntax error"), pos)
77 raise error.ParseError(_("syntax error"), pos)
78 pos += 1
78 pos += 1
79 yield ('end', None, pos)
79 yield ('end', None, pos)
80
80
81 def compiletemplate(tmpl, context, strtoken="string"):
81 def compiletemplate(tmpl, context, strtoken="string"):
82 parsed = []
82 parsed = []
83 pos, stop = 0, len(tmpl)
83 pos, stop = 0, len(tmpl)
84 p = parser.parser(tokenizer, elements)
84 p = parser.parser(tokenizer, elements)
85 while pos < stop:
85 while pos < stop:
86 n = tmpl.find('{', pos)
86 n = tmpl.find('{', pos)
87 if n < 0:
87 if n < 0:
88 parsed.append((strtoken, tmpl[pos:]))
88 parsed.append((strtoken, tmpl[pos:]))
89 break
89 break
90 if n > 0 and tmpl[n - 1] == '\\':
90 if n > 0 and tmpl[n - 1] == '\\':
91 # escaped
91 # escaped
92 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
92 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
93 pos = n + 1
93 pos = n + 1
94 continue
94 continue
95 if n > pos:
95 if n > pos:
96 parsed.append((strtoken, tmpl[pos:n]))
96 parsed.append((strtoken, tmpl[pos:n]))
97
97
98 pd = [tmpl, n + 1, stop]
98 pd = [tmpl, n + 1, stop]
99 parseres, pos = p.parse(pd)
99 parseres, pos = p.parse(pd)
100 parsed.append(parseres)
100 parsed.append(parseres)
101
101
102 return [compileexp(e, context) for e in parsed]
102 return [compileexp(e, context) for e in parsed]
103
103
104 def compileexp(exp, context):
104 def compileexp(exp, context):
105 t = exp[0]
105 t = exp[0]
106 if t in methods:
106 if t in methods:
107 return methods[t](exp, context)
107 return methods[t](exp, context)
108 raise error.ParseError(_("unknown method '%s'") % t)
108 raise error.ParseError(_("unknown method '%s'") % t)
109
109
110 # template evaluation
110 # template evaluation
111
111
112 def getsymbol(exp):
112 def getsymbol(exp):
113 if exp[0] == 'symbol':
113 if exp[0] == 'symbol':
114 return exp[1]
114 return exp[1]
115 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
115 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
116
116
117 def getlist(x):
117 def getlist(x):
118 if not x:
118 if not x:
119 return []
119 return []
120 if x[0] == 'list':
120 if x[0] == 'list':
121 return getlist(x[1]) + [x[2]]
121 return getlist(x[1]) + [x[2]]
122 return [x]
122 return [x]
123
123
124 def getfilter(exp, context):
124 def getfilter(exp, context):
125 f = getsymbol(exp)
125 f = getsymbol(exp)
126 if f not in context._filters:
126 if f not in context._filters:
127 raise error.ParseError(_("unknown function '%s'") % f)
127 raise error.ParseError(_("unknown function '%s'") % f)
128 return context._filters[f]
128 return context._filters[f]
129
129
130 def gettemplate(exp, context):
130 def gettemplate(exp, context):
131 if exp[0] == 'string' or exp[0] == 'rawstring':
131 if exp[0] == 'string' or exp[0] == 'rawstring':
132 return compiletemplate(exp[1], context, strtoken=exp[0])
132 return compiletemplate(exp[1], context, strtoken=exp[0])
133 if exp[0] == 'symbol':
133 if exp[0] == 'symbol':
134 return context._load(exp[1])
134 return context._load(exp[1])
135 raise error.ParseError(_("expected template specifier"))
135 raise error.ParseError(_("expected template specifier"))
136
136
137 def runstring(context, mapping, data):
137 def runstring(context, mapping, data):
138 return data.decode("string-escape")
138 return data.decode("string-escape")
139
139
140 def runrawstring(context, mapping, data):
140 def runrawstring(context, mapping, data):
141 return data
141 return data
142
142
143 def runsymbol(context, mapping, key):
143 def runsymbol(context, mapping, key):
144 v = mapping.get(key)
144 v = mapping.get(key)
145 if v is None:
145 if v is None:
146 v = context._defaults.get(key)
146 v = context._defaults.get(key)
147 if v is None:
147 if v is None:
148 try:
148 try:
149 v = context.process(key, mapping)
149 v = context.process(key, mapping)
150 except TemplateNotFound:
150 except TemplateNotFound:
151 v = ''
151 v = ''
152 if callable(v):
152 if callable(v):
153 return v(**mapping)
153 return v(**mapping)
154 if isinstance(v, types.GeneratorType):
154 if isinstance(v, types.GeneratorType):
155 v = list(v)
155 v = list(v)
156 return v
156 return v
157
157
158 def buildfilter(exp, context):
158 def buildfilter(exp, context):
159 func, data = compileexp(exp[1], context)
159 func, data = compileexp(exp[1], context)
160 filt = getfilter(exp[2], context)
160 filt = getfilter(exp[2], context)
161 return (runfilter, (func, data, filt))
161 return (runfilter, (func, data, filt))
162
162
163 def runfilter(context, mapping, data):
163 def runfilter(context, mapping, data):
164 func, data, filt = data
164 func, data, filt = data
165 try:
165 try:
166 return filt(func(context, mapping, data))
166 return filt(func(context, mapping, data))
167 except (ValueError, AttributeError, TypeError):
167 except (ValueError, AttributeError, TypeError):
168 if isinstance(data, tuple):
168 if isinstance(data, tuple):
169 dt = data[1]
169 dt = data[1]
170 else:
170 else:
171 dt = data
171 dt = data
172 raise util.Abort(_("template filter '%s' is not compatible with "
172 raise util.Abort(_("template filter '%s' is not compatible with "
173 "keyword '%s'") % (filt.func_name, dt))
173 "keyword '%s'") % (filt.func_name, dt))
174
174
175 def buildmap(exp, context):
175 def buildmap(exp, context):
176 func, data = compileexp(exp[1], context)
176 func, data = compileexp(exp[1], context)
177 ctmpl = gettemplate(exp[2], context)
177 ctmpl = gettemplate(exp[2], context)
178 return (runmap, (func, data, ctmpl))
178 return (runmap, (func, data, ctmpl))
179
179
180 def runtemplate(context, mapping, template):
180 def runtemplate(context, mapping, template):
181 for func, data in template:
181 for func, data in template:
182 yield func(context, mapping, data)
182 yield func(context, mapping, data)
183
183
184 def runmap(context, mapping, data):
184 def runmap(context, mapping, data):
185 func, data, ctmpl = data
185 func, data, ctmpl = data
186 d = func(context, mapping, data)
186 d = func(context, mapping, data)
187 if callable(d):
187 if callable(d):
188 d = d()
188 d = d()
189
189
190 lm = mapping.copy()
190 lm = mapping.copy()
191
191
192 for i in d:
192 for i in d:
193 if isinstance(i, dict):
193 if isinstance(i, dict):
194 lm.update(i)
194 lm.update(i)
195 lm['originalnode'] = mapping.get('node')
195 lm['originalnode'] = mapping.get('node')
196 yield runtemplate(context, lm, ctmpl)
196 yield runtemplate(context, lm, ctmpl)
197 else:
197 else:
198 # v is not an iterable of dicts, this happen when 'key'
198 # v is not an iterable of dicts, this happen when 'key'
199 # has been fully expanded already and format is useless.
199 # has been fully expanded already and format is useless.
200 # If so, return the expanded value.
200 # If so, return the expanded value.
201 yield i
201 yield i
202
202
203 def buildfunc(exp, context):
203 def buildfunc(exp, context):
204 n = getsymbol(exp[1])
204 n = getsymbol(exp[1])
205 args = [compileexp(x, context) for x in getlist(exp[2])]
205 args = [compileexp(x, context) for x in getlist(exp[2])]
206 if n in funcs:
206 if n in funcs:
207 f = funcs[n]
207 f = funcs[n]
208 return (f, args)
208 return (f, args)
209 if n in context._filters:
209 if n in context._filters:
210 if len(args) != 1:
210 if len(args) != 1:
211 raise error.ParseError(_("filter %s expects one argument") % n)
211 raise error.ParseError(_("filter %s expects one argument") % n)
212 f = context._filters[n]
212 f = context._filters[n]
213 return (runfilter, (args[0][0], args[0][1], f))
213 return (runfilter, (args[0][0], args[0][1], f))
214 raise error.ParseError(_("unknown function '%s'") % n)
214 raise error.ParseError(_("unknown function '%s'") % n)
215
215
216 def date(context, mapping, args):
216 def date(context, mapping, args):
217 if not (1 <= len(args) <= 2):
217 if not (1 <= len(args) <= 2):
218 # i18n: "date" is a keyword
218 # i18n: "date" is a keyword
219 raise error.ParseError(_("date expects one or two arguments"))
219 raise error.ParseError(_("date expects one or two arguments"))
220
220
221 date = args[0][0](context, mapping, args[0][1])
221 date = args[0][0](context, mapping, args[0][1])
222 if len(args) == 2:
222 if len(args) == 2:
223 fmt = stringify(args[1][0](context, mapping, args[1][1]))
223 fmt = stringify(args[1][0](context, mapping, args[1][1]))
224 return util.datestr(date, fmt)
224 return util.datestr(date, fmt)
225 return util.datestr(date)
225 return util.datestr(date)
226
226
227 def diff(context, mapping, args):
227 def diff(context, mapping, args):
228 if len(args) > 2:
228 if len(args) > 2:
229 # i18n: "diff" is a keyword
229 # i18n: "diff" is a keyword
230 raise error.ParseError(_("diff expects one, two or no arguments"))
230 raise error.ParseError(_("diff expects one, two or no arguments"))
231
231
232 def getpatterns(i):
232 def getpatterns(i):
233 if i < len(args):
233 if i < len(args):
234 s = args[i][1].strip()
234 s = args[i][1].strip()
235 if s:
235 if s:
236 return [s]
236 return [s]
237 return []
237 return []
238
238
239 ctx = mapping['ctx']
239 ctx = mapping['ctx']
240 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
240 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
241
241
242 return ''.join(chunks)
242 return ''.join(chunks)
243
243
244 def fill(context, mapping, args):
244 def fill(context, mapping, args):
245 if not (1 <= len(args) <= 4):
245 if not (1 <= len(args) <= 4):
246 # i18n: "fill" is a keyword
246 # i18n: "fill" is a keyword
247 raise error.ParseError(_("fill expects one to four arguments"))
247 raise error.ParseError(_("fill expects one to four arguments"))
248
248
249 text = stringify(args[0][0](context, mapping, args[0][1]))
249 text = stringify(args[0][0](context, mapping, args[0][1]))
250 width = 76
250 width = 76
251 initindent = ''
251 initindent = ''
252 hangindent = ''
252 hangindent = ''
253 if 2 <= len(args) <= 4:
253 if 2 <= len(args) <= 4:
254 try:
254 try:
255 width = int(stringify(args[1][0](context, mapping, args[1][1])))
255 width = int(stringify(args[1][0](context, mapping, args[1][1])))
256 except ValueError:
256 except ValueError:
257 # i18n: "fill" is a keyword
257 # i18n: "fill" is a keyword
258 raise error.ParseError(_("fill expects an integer width"))
258 raise error.ParseError(_("fill expects an integer width"))
259 try:
259 try:
260 initindent = stringify(_evalifliteral(args[2], context, mapping))
260 initindent = stringify(_evalifliteral(args[2], context, mapping))
261 hangindent = stringify(_evalifliteral(args[3], context, mapping))
261 hangindent = stringify(_evalifliteral(args[3], context, mapping))
262 except IndexError:
262 except IndexError:
263 pass
263 pass
264
264
265 return templatefilters.fill(text, width, initindent, hangindent)
265 return templatefilters.fill(text, width, initindent, hangindent)
266
266
267 def pad(context, mapping, args):
267 def pad(context, mapping, args):
268 """usage: pad(text, width, fillchar=' ', right=False)
268 """usage: pad(text, width, fillchar=' ', right=False)
269 """
269 """
270 if not (2 <= len(args) <= 4):
270 if not (2 <= len(args) <= 4):
271 # i18n: "pad" is a keyword
271 # i18n: "pad" is a keyword
272 raise error.ParseError(_("pad() expects two to four arguments"))
272 raise error.ParseError(_("pad() expects two to four arguments"))
273
273
274 width = int(args[1][1])
274 width = int(args[1][1])
275
275
276 text = stringify(args[0][0](context, mapping, args[0][1]))
276 text = stringify(args[0][0](context, mapping, args[0][1]))
277 if args[0][0] == runstring:
277 if args[0][0] == runstring:
278 text = stringify(runtemplate(context, mapping,
278 text = stringify(runtemplate(context, mapping,
279 compiletemplate(text, context)))
279 compiletemplate(text, context)))
280
280
281 right = False
281 right = False
282 fillchar = ' '
282 fillchar = ' '
283 if len(args) > 2:
283 if len(args) > 2:
284 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
284 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
285 if len(args) > 3:
285 if len(args) > 3:
286 right = util.parsebool(args[3][1])
286 right = util.parsebool(args[3][1])
287
287
288 if right:
288 if right:
289 return text.rjust(width, fillchar)
289 return text.rjust(width, fillchar)
290 else:
290 else:
291 return text.ljust(width, fillchar)
291 return text.ljust(width, fillchar)
292
292
293 def get(context, mapping, args):
293 def get(context, mapping, args):
294 if len(args) != 2:
294 if len(args) != 2:
295 # i18n: "get" is a keyword
295 # i18n: "get" is a keyword
296 raise error.ParseError(_("get() expects two arguments"))
296 raise error.ParseError(_("get() expects two arguments"))
297
297
298 dictarg = args[0][0](context, mapping, args[0][1])
298 dictarg = args[0][0](context, mapping, args[0][1])
299 if not util.safehasattr(dictarg, 'get'):
299 if not util.safehasattr(dictarg, 'get'):
300 # i18n: "get" is a keyword
300 # i18n: "get" is a keyword
301 raise error.ParseError(_("get() expects a dict as first argument"))
301 raise error.ParseError(_("get() expects a dict as first argument"))
302
302
303 key = args[1][0](context, mapping, args[1][1])
303 key = args[1][0](context, mapping, args[1][1])
304 yield dictarg.get(key)
304 yield dictarg.get(key)
305
305
306 def _evalifliteral(arg, context, mapping):
306 def _evalifliteral(arg, context, mapping):
307 t = stringify(arg[0](context, mapping, arg[1]))
307 t = stringify(arg[0](context, mapping, arg[1]))
308 if arg[0] == runstring or arg[0] == runrawstring:
308 if arg[0] == runstring or arg[0] == runrawstring:
309 yield runtemplate(context, mapping,
309 yield runtemplate(context, mapping,
310 compiletemplate(t, context, strtoken='rawstring'))
310 compiletemplate(t, context, strtoken='rawstring'))
311 else:
311 else:
312 yield t
312 yield t
313
313
314 def if_(context, mapping, args):
314 def if_(context, mapping, args):
315 if not (2 <= len(args) <= 3):
315 if not (2 <= len(args) <= 3):
316 # i18n: "if" is a keyword
316 # i18n: "if" is a keyword
317 raise error.ParseError(_("if expects two or three arguments"))
317 raise error.ParseError(_("if expects two or three arguments"))
318
318
319 test = stringify(args[0][0](context, mapping, args[0][1]))
319 test = stringify(args[0][0](context, mapping, args[0][1]))
320 if test:
320 if test:
321 yield _evalifliteral(args[1], context, mapping)
321 yield _evalifliteral(args[1], context, mapping)
322 elif len(args) == 3:
322 elif len(args) == 3:
323 yield _evalifliteral(args[2], context, mapping)
323 yield _evalifliteral(args[2], context, mapping)
324
324
325 def ifcontains(context, mapping, args):
325 def ifcontains(context, mapping, args):
326 if not (3 <= len(args) <= 4):
326 if not (3 <= len(args) <= 4):
327 # i18n: "ifcontains" is a keyword
327 # i18n: "ifcontains" is a keyword
328 raise error.ParseError(_("ifcontains expects three or four arguments"))
328 raise error.ParseError(_("ifcontains expects three or four arguments"))
329
329
330 item = stringify(args[0][0](context, mapping, args[0][1]))
330 item = stringify(args[0][0](context, mapping, args[0][1]))
331 items = args[1][0](context, mapping, args[1][1])
331 items = args[1][0](context, mapping, args[1][1])
332
332
333 # Iterating over items gives a formatted string, so we iterate
333 if item in items:
334 # directly over the raw values.
335 if ((callable(items) and item in [i.values()[0] for i in items()]) or
336 (isinstance(items, str) and item in items)):
337 yield _evalifliteral(args[2], context, mapping)
334 yield _evalifliteral(args[2], context, mapping)
338 elif len(args) == 4:
335 elif len(args) == 4:
339 yield _evalifliteral(args[3], context, mapping)
336 yield _evalifliteral(args[3], context, mapping)
340
337
341 def ifeq(context, mapping, args):
338 def ifeq(context, mapping, args):
342 if not (3 <= len(args) <= 4):
339 if not (3 <= len(args) <= 4):
343 # i18n: "ifeq" is a keyword
340 # i18n: "ifeq" is a keyword
344 raise error.ParseError(_("ifeq expects three or four arguments"))
341 raise error.ParseError(_("ifeq expects three or four arguments"))
345
342
346 test = stringify(args[0][0](context, mapping, args[0][1]))
343 test = stringify(args[0][0](context, mapping, args[0][1]))
347 match = stringify(args[1][0](context, mapping, args[1][1]))
344 match = stringify(args[1][0](context, mapping, args[1][1]))
348 if test == match:
345 if test == match:
349 yield _evalifliteral(args[2], context, mapping)
346 yield _evalifliteral(args[2], context, mapping)
350 elif len(args) == 4:
347 elif len(args) == 4:
351 yield _evalifliteral(args[3], context, mapping)
348 yield _evalifliteral(args[3], context, mapping)
352
349
353 def join(context, mapping, args):
350 def join(context, mapping, args):
354 if not (1 <= len(args) <= 2):
351 if not (1 <= len(args) <= 2):
355 # i18n: "join" is a keyword
352 # i18n: "join" is a keyword
356 raise error.ParseError(_("join expects one or two arguments"))
353 raise error.ParseError(_("join expects one or two arguments"))
357
354
358 joinset = args[0][0](context, mapping, args[0][1])
355 joinset = args[0][0](context, mapping, args[0][1])
359 if callable(joinset):
356 if callable(joinset):
360 jf = joinset.joinfmt
357 jf = joinset.joinfmt
361 joinset = [jf(x) for x in joinset()]
358 joinset = [jf(x) for x in joinset()]
362
359
363 joiner = " "
360 joiner = " "
364 if len(args) > 1:
361 if len(args) > 1:
365 joiner = stringify(args[1][0](context, mapping, args[1][1]))
362 joiner = stringify(args[1][0](context, mapping, args[1][1]))
366
363
367 first = True
364 first = True
368 for x in joinset:
365 for x in joinset:
369 if first:
366 if first:
370 first = False
367 first = False
371 else:
368 else:
372 yield joiner
369 yield joiner
373 yield x
370 yield x
374
371
375 def label(context, mapping, args):
372 def label(context, mapping, args):
376 if len(args) != 2:
373 if len(args) != 2:
377 # i18n: "label" is a keyword
374 # i18n: "label" is a keyword
378 raise error.ParseError(_("label expects two arguments"))
375 raise error.ParseError(_("label expects two arguments"))
379
376
380 # ignore args[0] (the label string) since this is supposed to be a a no-op
377 # ignore args[0] (the label string) since this is supposed to be a a no-op
381 yield _evalifliteral(args[1], context, mapping)
378 yield _evalifliteral(args[1], context, mapping)
382
379
383 def revset(context, mapping, args):
380 def revset(context, mapping, args):
384 """usage: revset(query[, formatargs...])
381 """usage: revset(query[, formatargs...])
385 """
382 """
386 if not len(args) > 0:
383 if not len(args) > 0:
387 # i18n: "revset" is a keyword
384 # i18n: "revset" is a keyword
388 raise error.ParseError(_("revset expects one or more arguments"))
385 raise error.ParseError(_("revset expects one or more arguments"))
389
386
390 raw = args[0][1]
387 raw = args[0][1]
391 ctx = mapping['ctx']
388 ctx = mapping['ctx']
392 repo = ctx._repo
389 repo = ctx._repo
393
390
394 def query(expr):
391 def query(expr):
395 m = revsetmod.match(repo.ui, expr)
392 m = revsetmod.match(repo.ui, expr)
396 return m(repo)
393 return m(repo)
397
394
398 if len(args) > 1:
395 if len(args) > 1:
399 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
396 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
400 revs = query(revsetmod.formatspec(raw, *formatargs))
397 revs = query(revsetmod.formatspec(raw, *formatargs))
401 revs = list([str(r) for r in revs])
398 revs = list([str(r) for r in revs])
402 else:
399 else:
403 revsetcache = mapping['cache'].setdefault("revsetcache", {})
400 revsetcache = mapping['cache'].setdefault("revsetcache", {})
404 if raw in revsetcache:
401 if raw in revsetcache:
405 revs = revsetcache[raw]
402 revs = revsetcache[raw]
406 else:
403 else:
407 revs = query(raw)
404 revs = query(raw)
408 revs = list([str(r) for r in revs])
405 revs = list([str(r) for r in revs])
409 revsetcache[raw] = revs
406 revsetcache[raw] = revs
410
407
411 return templatekw.showlist("revision", revs, **mapping)
408 return templatekw.showlist("revision", revs, **mapping)
412
409
413 def rstdoc(context, mapping, args):
410 def rstdoc(context, mapping, args):
414 if len(args) != 2:
411 if len(args) != 2:
415 # i18n: "rstdoc" is a keyword
412 # i18n: "rstdoc" is a keyword
416 raise error.ParseError(_("rstdoc expects two arguments"))
413 raise error.ParseError(_("rstdoc expects two arguments"))
417
414
418 text = stringify(args[0][0](context, mapping, args[0][1]))
415 text = stringify(args[0][0](context, mapping, args[0][1]))
419 style = stringify(args[1][0](context, mapping, args[1][1]))
416 style = stringify(args[1][0](context, mapping, args[1][1]))
420
417
421 return minirst.format(text, style=style, keep=['verbose'])
418 return minirst.format(text, style=style, keep=['verbose'])
422
419
423 def shortest(context, mapping, args):
420 def shortest(context, mapping, args):
424 """usage: shortest(node, minlength=4)
421 """usage: shortest(node, minlength=4)
425 """
422 """
426 if not (1 <= len(args) <= 2):
423 if not (1 <= len(args) <= 2):
427 # i18n: "shortest" is a keyword
424 # i18n: "shortest" is a keyword
428 raise error.ParseError(_("shortest() expects one or two arguments"))
425 raise error.ParseError(_("shortest() expects one or two arguments"))
429
426
430 node = stringify(args[0][0](context, mapping, args[0][1]))
427 node = stringify(args[0][0](context, mapping, args[0][1]))
431
428
432 minlength = 4
429 minlength = 4
433 if len(args) > 1:
430 if len(args) > 1:
434 minlength = int(args[1][1])
431 minlength = int(args[1][1])
435
432
436 cl = mapping['ctx']._repo.changelog
433 cl = mapping['ctx']._repo.changelog
437 def isvalid(test):
434 def isvalid(test):
438 try:
435 try:
439 try:
436 try:
440 cl.index.partialmatch(test)
437 cl.index.partialmatch(test)
441 except AttributeError:
438 except AttributeError:
442 # Pure mercurial doesn't support partialmatch on the index.
439 # Pure mercurial doesn't support partialmatch on the index.
443 # Fallback to the slow way.
440 # Fallback to the slow way.
444 if cl._partialmatch(test) is None:
441 if cl._partialmatch(test) is None:
445 return False
442 return False
446
443
447 try:
444 try:
448 i = int(test)
445 i = int(test)
449 # if we are a pure int, then starting with zero will not be
446 # if we are a pure int, then starting with zero will not be
450 # confused as a rev; or, obviously, if the int is larger than
447 # confused as a rev; or, obviously, if the int is larger than
451 # the value of the tip rev
448 # the value of the tip rev
452 if test[0] == '0' or i > len(cl):
449 if test[0] == '0' or i > len(cl):
453 return True
450 return True
454 return False
451 return False
455 except ValueError:
452 except ValueError:
456 return True
453 return True
457 except error.RevlogError:
454 except error.RevlogError:
458 return False
455 return False
459
456
460 shortest = node
457 shortest = node
461 startlength = max(6, minlength)
458 startlength = max(6, minlength)
462 length = startlength
459 length = startlength
463 while True:
460 while True:
464 test = node[:length]
461 test = node[:length]
465 if isvalid(test):
462 if isvalid(test):
466 shortest = test
463 shortest = test
467 if length == minlength or length > startlength:
464 if length == minlength or length > startlength:
468 return shortest
465 return shortest
469 length -= 1
466 length -= 1
470 else:
467 else:
471 length += 1
468 length += 1
472 if len(shortest) <= length:
469 if len(shortest) <= length:
473 return shortest
470 return shortest
474
471
475 def strip(context, mapping, args):
472 def strip(context, mapping, args):
476 if not (1 <= len(args) <= 2):
473 if not (1 <= len(args) <= 2):
477 # i18n: "strip" is a keyword
474 # i18n: "strip" is a keyword
478 raise error.ParseError(_("strip expects one or two arguments"))
475 raise error.ParseError(_("strip expects one or two arguments"))
479
476
480 text = stringify(args[0][0](context, mapping, args[0][1]))
477 text = stringify(args[0][0](context, mapping, args[0][1]))
481 if len(args) == 2:
478 if len(args) == 2:
482 chars = stringify(args[1][0](context, mapping, args[1][1]))
479 chars = stringify(args[1][0](context, mapping, args[1][1]))
483 return text.strip(chars)
480 return text.strip(chars)
484 return text.strip()
481 return text.strip()
485
482
486 def sub(context, mapping, args):
483 def sub(context, mapping, args):
487 if len(args) != 3:
484 if len(args) != 3:
488 # i18n: "sub" is a keyword
485 # i18n: "sub" is a keyword
489 raise error.ParseError(_("sub expects three arguments"))
486 raise error.ParseError(_("sub expects three arguments"))
490
487
491 pat = stringify(args[0][0](context, mapping, args[0][1]))
488 pat = stringify(args[0][0](context, mapping, args[0][1]))
492 rpl = stringify(args[1][0](context, mapping, args[1][1]))
489 rpl = stringify(args[1][0](context, mapping, args[1][1]))
493 src = stringify(_evalifliteral(args[2], context, mapping))
490 src = stringify(_evalifliteral(args[2], context, mapping))
494 yield re.sub(pat, rpl, src)
491 yield re.sub(pat, rpl, src)
495
492
496 def startswith(context, mapping, args):
493 def startswith(context, mapping, args):
497 if len(args) != 2:
494 if len(args) != 2:
498 # i18n: "startswith" is a keyword
495 # i18n: "startswith" is a keyword
499 raise error.ParseError(_("startswith expects two arguments"))
496 raise error.ParseError(_("startswith expects two arguments"))
500
497
501 patn = stringify(args[0][0](context, mapping, args[0][1]))
498 patn = stringify(args[0][0](context, mapping, args[0][1]))
502 text = stringify(args[1][0](context, mapping, args[1][1]))
499 text = stringify(args[1][0](context, mapping, args[1][1]))
503 if text.startswith(patn):
500 if text.startswith(patn):
504 return text
501 return text
505 return ''
502 return ''
506
503
507
504
508 def word(context, mapping, args):
505 def word(context, mapping, args):
509 """return nth word from a string"""
506 """return nth word from a string"""
510 if not (2 <= len(args) <= 3):
507 if not (2 <= len(args) <= 3):
511 # i18n: "word" is a keyword
508 # i18n: "word" is a keyword
512 raise error.ParseError(_("word expects two or three arguments, got %d")
509 raise error.ParseError(_("word expects two or three arguments, got %d")
513 % len(args))
510 % len(args))
514
511
515 num = int(stringify(args[0][0](context, mapping, args[0][1])))
512 num = int(stringify(args[0][0](context, mapping, args[0][1])))
516 text = stringify(args[1][0](context, mapping, args[1][1]))
513 text = stringify(args[1][0](context, mapping, args[1][1]))
517 if len(args) == 3:
514 if len(args) == 3:
518 splitter = stringify(args[2][0](context, mapping, args[2][1]))
515 splitter = stringify(args[2][0](context, mapping, args[2][1]))
519 else:
516 else:
520 splitter = None
517 splitter = None
521
518
522 tokens = text.split(splitter)
519 tokens = text.split(splitter)
523 if num >= len(tokens):
520 if num >= len(tokens):
524 return ''
521 return ''
525 else:
522 else:
526 return tokens[num]
523 return tokens[num]
527
524
528 methods = {
525 methods = {
529 "string": lambda e, c: (runstring, e[1]),
526 "string": lambda e, c: (runstring, e[1]),
530 "rawstring": lambda e, c: (runrawstring, e[1]),
527 "rawstring": lambda e, c: (runrawstring, e[1]),
531 "symbol": lambda e, c: (runsymbol, e[1]),
528 "symbol": lambda e, c: (runsymbol, e[1]),
532 "group": lambda e, c: compileexp(e[1], c),
529 "group": lambda e, c: compileexp(e[1], c),
533 # ".": buildmember,
530 # ".": buildmember,
534 "|": buildfilter,
531 "|": buildfilter,
535 "%": buildmap,
532 "%": buildmap,
536 "func": buildfunc,
533 "func": buildfunc,
537 }
534 }
538
535
539 funcs = {
536 funcs = {
540 "date": date,
537 "date": date,
541 "diff": diff,
538 "diff": diff,
542 "fill": fill,
539 "fill": fill,
543 "get": get,
540 "get": get,
544 "if": if_,
541 "if": if_,
545 "ifcontains": ifcontains,
542 "ifcontains": ifcontains,
546 "ifeq": ifeq,
543 "ifeq": ifeq,
547 "join": join,
544 "join": join,
548 "label": label,
545 "label": label,
549 "pad": pad,
546 "pad": pad,
550 "revset": revset,
547 "revset": revset,
551 "rstdoc": rstdoc,
548 "rstdoc": rstdoc,
552 "shortest": shortest,
549 "shortest": shortest,
553 "startswith": startswith,
550 "startswith": startswith,
554 "strip": strip,
551 "strip": strip,
555 "sub": sub,
552 "sub": sub,
556 "word": word,
553 "word": word,
557 }
554 }
558
555
559 # template engine
556 # template engine
560
557
561 stringify = templatefilters.stringify
558 stringify = templatefilters.stringify
562
559
563 def _flatten(thing):
560 def _flatten(thing):
564 '''yield a single stream from a possibly nested set of iterators'''
561 '''yield a single stream from a possibly nested set of iterators'''
565 if isinstance(thing, str):
562 if isinstance(thing, str):
566 yield thing
563 yield thing
567 elif not util.safehasattr(thing, '__iter__'):
564 elif not util.safehasattr(thing, '__iter__'):
568 if thing is not None:
565 if thing is not None:
569 yield str(thing)
566 yield str(thing)
570 else:
567 else:
571 for i in thing:
568 for i in thing:
572 if isinstance(i, str):
569 if isinstance(i, str):
573 yield i
570 yield i
574 elif not util.safehasattr(i, '__iter__'):
571 elif not util.safehasattr(i, '__iter__'):
575 if i is not None:
572 if i is not None:
576 yield str(i)
573 yield str(i)
577 elif i is not None:
574 elif i is not None:
578 for j in _flatten(i):
575 for j in _flatten(i):
579 yield j
576 yield j
580
577
581 def parsestring(s, quoted=True):
578 def parsestring(s, quoted=True):
582 '''parse a string using simple c-like syntax.
579 '''parse a string using simple c-like syntax.
583 string must be in quotes if quoted is True.'''
580 string must be in quotes if quoted is True.'''
584 if quoted:
581 if quoted:
585 if len(s) < 2 or s[0] != s[-1]:
582 if len(s) < 2 or s[0] != s[-1]:
586 raise SyntaxError(_('unmatched quotes'))
583 raise SyntaxError(_('unmatched quotes'))
587 return s[1:-1].decode('string_escape')
584 return s[1:-1].decode('string_escape')
588
585
589 return s.decode('string_escape')
586 return s.decode('string_escape')
590
587
591 class engine(object):
588 class engine(object):
592 '''template expansion engine.
589 '''template expansion engine.
593
590
594 template expansion works like this. a map file contains key=value
591 template expansion works like this. a map file contains key=value
595 pairs. if value is quoted, it is treated as string. otherwise, it
592 pairs. if value is quoted, it is treated as string. otherwise, it
596 is treated as name of template file.
593 is treated as name of template file.
597
594
598 templater is asked to expand a key in map. it looks up key, and
595 templater is asked to expand a key in map. it looks up key, and
599 looks for strings like this: {foo}. it expands {foo} by looking up
596 looks for strings like this: {foo}. it expands {foo} by looking up
600 foo in map, and substituting it. expansion is recursive: it stops
597 foo in map, and substituting it. expansion is recursive: it stops
601 when there is no more {foo} to replace.
598 when there is no more {foo} to replace.
602
599
603 expansion also allows formatting and filtering.
600 expansion also allows formatting and filtering.
604
601
605 format uses key to expand each item in list. syntax is
602 format uses key to expand each item in list. syntax is
606 {key%format}.
603 {key%format}.
607
604
608 filter uses function to transform value. syntax is
605 filter uses function to transform value. syntax is
609 {key|filter1|filter2|...}.'''
606 {key|filter1|filter2|...}.'''
610
607
611 def __init__(self, loader, filters={}, defaults={}):
608 def __init__(self, loader, filters={}, defaults={}):
612 self._loader = loader
609 self._loader = loader
613 self._filters = filters
610 self._filters = filters
614 self._defaults = defaults
611 self._defaults = defaults
615 self._cache = {}
612 self._cache = {}
616
613
617 def _load(self, t):
614 def _load(self, t):
618 '''load, parse, and cache a template'''
615 '''load, parse, and cache a template'''
619 if t not in self._cache:
616 if t not in self._cache:
620 self._cache[t] = compiletemplate(self._loader(t), self)
617 self._cache[t] = compiletemplate(self._loader(t), self)
621 return self._cache[t]
618 return self._cache[t]
622
619
623 def process(self, t, mapping):
620 def process(self, t, mapping):
624 '''Perform expansion. t is name of map element to expand.
621 '''Perform expansion. t is name of map element to expand.
625 mapping contains added elements for use during expansion. Is a
622 mapping contains added elements for use during expansion. Is a
626 generator.'''
623 generator.'''
627 return _flatten(runtemplate(self, mapping, self._load(t)))
624 return _flatten(runtemplate(self, mapping, self._load(t)))
628
625
629 engines = {'default': engine}
626 engines = {'default': engine}
630
627
631 def stylelist():
628 def stylelist():
632 paths = templatepaths()
629 paths = templatepaths()
633 if not paths:
630 if not paths:
634 return _('no templates found, try `hg debuginstall` for more info')
631 return _('no templates found, try `hg debuginstall` for more info')
635 dirlist = os.listdir(paths[0])
632 dirlist = os.listdir(paths[0])
636 stylelist = []
633 stylelist = []
637 for file in dirlist:
634 for file in dirlist:
638 split = file.split(".")
635 split = file.split(".")
639 if split[0] == "map-cmdline":
636 if split[0] == "map-cmdline":
640 stylelist.append(split[1])
637 stylelist.append(split[1])
641 return ", ".join(sorted(stylelist))
638 return ", ".join(sorted(stylelist))
642
639
643 class TemplateNotFound(util.Abort):
640 class TemplateNotFound(util.Abort):
644 pass
641 pass
645
642
646 class templater(object):
643 class templater(object):
647
644
648 def __init__(self, mapfile, filters={}, defaults={}, cache={},
645 def __init__(self, mapfile, filters={}, defaults={}, cache={},
649 minchunk=1024, maxchunk=65536):
646 minchunk=1024, maxchunk=65536):
650 '''set up template engine.
647 '''set up template engine.
651 mapfile is name of file to read map definitions from.
648 mapfile is name of file to read map definitions from.
652 filters is dict of functions. each transforms a value into another.
649 filters is dict of functions. each transforms a value into another.
653 defaults is dict of default map definitions.'''
650 defaults is dict of default map definitions.'''
654 self.mapfile = mapfile or 'template'
651 self.mapfile = mapfile or 'template'
655 self.cache = cache.copy()
652 self.cache = cache.copy()
656 self.map = {}
653 self.map = {}
657 self.base = (mapfile and os.path.dirname(mapfile)) or ''
654 self.base = (mapfile and os.path.dirname(mapfile)) or ''
658 self.filters = templatefilters.filters.copy()
655 self.filters = templatefilters.filters.copy()
659 self.filters.update(filters)
656 self.filters.update(filters)
660 self.defaults = defaults
657 self.defaults = defaults
661 self.minchunk, self.maxchunk = minchunk, maxchunk
658 self.minchunk, self.maxchunk = minchunk, maxchunk
662 self.ecache = {}
659 self.ecache = {}
663
660
664 if not mapfile:
661 if not mapfile:
665 return
662 return
666 if not os.path.exists(mapfile):
663 if not os.path.exists(mapfile):
667 raise util.Abort(_("style '%s' not found") % mapfile,
664 raise util.Abort(_("style '%s' not found") % mapfile,
668 hint=_("available styles: %s") % stylelist())
665 hint=_("available styles: %s") % stylelist())
669
666
670 conf = config.config()
667 conf = config.config()
671 conf.read(mapfile)
668 conf.read(mapfile)
672
669
673 for key, val in conf[''].items():
670 for key, val in conf[''].items():
674 if not val:
671 if not val:
675 raise SyntaxError(_('%s: missing value') % conf.source('', key))
672 raise SyntaxError(_('%s: missing value') % conf.source('', key))
676 if val[0] in "'\"":
673 if val[0] in "'\"":
677 try:
674 try:
678 self.cache[key] = parsestring(val)
675 self.cache[key] = parsestring(val)
679 except SyntaxError, inst:
676 except SyntaxError, inst:
680 raise SyntaxError('%s: %s' %
677 raise SyntaxError('%s: %s' %
681 (conf.source('', key), inst.args[0]))
678 (conf.source('', key), inst.args[0]))
682 else:
679 else:
683 val = 'default', val
680 val = 'default', val
684 if ':' in val[1]:
681 if ':' in val[1]:
685 val = val[1].split(':', 1)
682 val = val[1].split(':', 1)
686 self.map[key] = val[0], os.path.join(self.base, val[1])
683 self.map[key] = val[0], os.path.join(self.base, val[1])
687
684
688 def __contains__(self, key):
685 def __contains__(self, key):
689 return key in self.cache or key in self.map
686 return key in self.cache or key in self.map
690
687
691 def load(self, t):
688 def load(self, t):
692 '''Get the template for the given template name. Use a local cache.'''
689 '''Get the template for the given template name. Use a local cache.'''
693 if t not in self.cache:
690 if t not in self.cache:
694 try:
691 try:
695 self.cache[t] = util.readfile(self.map[t][1])
692 self.cache[t] = util.readfile(self.map[t][1])
696 except KeyError, inst:
693 except KeyError, inst:
697 raise TemplateNotFound(_('"%s" not in template map') %
694 raise TemplateNotFound(_('"%s" not in template map') %
698 inst.args[0])
695 inst.args[0])
699 except IOError, inst:
696 except IOError, inst:
700 raise IOError(inst.args[0], _('template file %s: %s') %
697 raise IOError(inst.args[0], _('template file %s: %s') %
701 (self.map[t][1], inst.args[1]))
698 (self.map[t][1], inst.args[1]))
702 return self.cache[t]
699 return self.cache[t]
703
700
704 def __call__(self, t, **mapping):
701 def __call__(self, t, **mapping):
705 ttype = t in self.map and self.map[t][0] or 'default'
702 ttype = t in self.map and self.map[t][0] or 'default'
706 if ttype not in self.ecache:
703 if ttype not in self.ecache:
707 self.ecache[ttype] = engines[ttype](self.load,
704 self.ecache[ttype] = engines[ttype](self.load,
708 self.filters, self.defaults)
705 self.filters, self.defaults)
709 proc = self.ecache[ttype]
706 proc = self.ecache[ttype]
710
707
711 stream = proc.process(t, mapping)
708 stream = proc.process(t, mapping)
712 if self.minchunk:
709 if self.minchunk:
713 stream = util.increasingchunks(stream, min=self.minchunk,
710 stream = util.increasingchunks(stream, min=self.minchunk,
714 max=self.maxchunk)
711 max=self.maxchunk)
715 return stream
712 return stream
716
713
717 def templatepaths():
714 def templatepaths():
718 '''return locations used for template files.'''
715 '''return locations used for template files.'''
719 pathsrel = ['templates']
716 pathsrel = ['templates']
720 paths = [os.path.normpath(os.path.join(util.datapath, f))
717 paths = [os.path.normpath(os.path.join(util.datapath, f))
721 for f in pathsrel]
718 for f in pathsrel]
722 return [p for p in paths if os.path.isdir(p)]
719 return [p for p in paths if os.path.isdir(p)]
723
720
724 def templatepath(name):
721 def templatepath(name):
725 '''return location of template file. returns None if not found.'''
722 '''return location of template file. returns None if not found.'''
726 for p in templatepaths():
723 for p in templatepaths():
727 f = os.path.join(p, name)
724 f = os.path.join(p, name)
728 if os.path.exists(f):
725 if os.path.exists(f):
729 return f
726 return f
730 return None
727 return None
731
728
732 def stylemap(styles, paths=None):
729 def stylemap(styles, paths=None):
733 """Return path to mapfile for a given style.
730 """Return path to mapfile for a given style.
734
731
735 Searches mapfile in the following locations:
732 Searches mapfile in the following locations:
736 1. templatepath/style/map
733 1. templatepath/style/map
737 2. templatepath/map-style
734 2. templatepath/map-style
738 3. templatepath/map
735 3. templatepath/map
739 """
736 """
740
737
741 if paths is None:
738 if paths is None:
742 paths = templatepaths()
739 paths = templatepaths()
743 elif isinstance(paths, str):
740 elif isinstance(paths, str):
744 paths = [paths]
741 paths = [paths]
745
742
746 if isinstance(styles, str):
743 if isinstance(styles, str):
747 styles = [styles]
744 styles = [styles]
748
745
749 for style in styles:
746 for style in styles:
750 if not style:
747 if not style:
751 continue
748 continue
752 locations = [os.path.join(style, 'map'), 'map-' + style]
749 locations = [os.path.join(style, 'map'), 'map-' + style]
753 locations.append('map')
750 locations.append('map')
754
751
755 for path in paths:
752 for path in paths:
756 for location in locations:
753 for location in locations:
757 mapfile = os.path.join(path, location)
754 mapfile = os.path.join(path, location)
758 if os.path.isfile(mapfile):
755 if os.path.isfile(mapfile):
759 return style, mapfile
756 return style, mapfile
760
757
761 raise RuntimeError("No hgweb templates found in %r" % paths)
758 raise RuntimeError("No hgweb templates found in %r" % paths)
@@ -1,2513 +1,2520 b''
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
51 8 t
52 7 f
50
53
51 Quoting for ui.logtemplate
54 Quoting for ui.logtemplate
52
55
53 $ hg tip --config "ui.logtemplate={rev}\n"
56 $ hg tip --config "ui.logtemplate={rev}\n"
54 8
57 8
55 $ hg tip --config "ui.logtemplate='{rev}\n'"
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
56 8
59 8
57 $ hg tip --config 'ui.logtemplate="{rev}\n"'
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
58 8
61 8
59
62
60 Make sure user/global hgrc does not affect tests
63 Make sure user/global hgrc does not affect tests
61
64
62 $ echo '[ui]' > .hg/hgrc
65 $ echo '[ui]' > .hg/hgrc
63 $ echo 'logtemplate =' >> .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
64 $ echo 'style =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
65
68
66 Add some simple styles to settings
69 Add some simple styles to settings
67
70
68 $ echo '[templates]' >> .hg/hgrc
71 $ echo '[templates]' >> .hg/hgrc
69 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
70 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
71
74
72 $ hg log -l1 -Tsimple
75 $ hg log -l1 -Tsimple
73 8
76 8
74 $ hg log -l1 -Tsimple2
77 $ hg log -l1 -Tsimple2
75 8
78 8
76
79
77 Test templates and style maps in files:
80 Test templates and style maps in files:
78
81
79 $ echo "{rev}" > tmpl
82 $ echo "{rev}" > tmpl
80 $ hg log -l1 -T./tmpl
83 $ hg log -l1 -T./tmpl
81 8
84 8
82 $ hg log -l1 -Tblah/blah
85 $ hg log -l1 -Tblah/blah
83 blah/blah (no-eol)
86 blah/blah (no-eol)
84
87
85 $ printf 'changeset = "{rev}\\n"\n' > map-simple
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
86 $ hg log -l1 -T./map-simple
89 $ hg log -l1 -T./map-simple
87 8
90 8
88
91
89 Template should precede style option
92 Template should precede style option
90
93
91 $ hg log -l1 --style default -T '{rev}\n'
94 $ hg log -l1 --style default -T '{rev}\n'
92 8
95 8
93
96
94 Default style is like normal output:
97 Default style is like normal output:
95
98
96 $ hg log > log.out
99 $ hg log > log.out
97 $ hg log --style default > style.out
100 $ hg log --style default > style.out
98 $ cmp log.out style.out || diff -u log.out style.out
101 $ cmp log.out style.out || diff -u log.out style.out
99
102
100 $ hg log -v > log.out
103 $ hg log -v > log.out
101 $ hg log -v --style default > style.out
104 $ hg log -v --style default > style.out
102 $ cmp log.out style.out || diff -u log.out style.out
105 $ cmp log.out style.out || diff -u log.out style.out
103
106
104 $ hg log --debug > log.out
107 $ hg log --debug > log.out
105 $ hg log --debug --style default > style.out
108 $ hg log --debug --style default > style.out
106 $ cmp log.out style.out || diff -u log.out style.out
109 $ cmp log.out style.out || diff -u log.out style.out
107
110
108 Default style should also preserve color information (issue2866):
111 Default style should also preserve color information (issue2866):
109
112
110 $ cp $HGRCPATH $HGRCPATH-bak
113 $ cp $HGRCPATH $HGRCPATH-bak
111 $ cat <<EOF >> $HGRCPATH
114 $ cat <<EOF >> $HGRCPATH
112 > [extensions]
115 > [extensions]
113 > color=
116 > color=
114 > EOF
117 > EOF
115
118
116 $ hg --color=debug log > log.out
119 $ hg --color=debug log > log.out
117 $ hg --color=debug log --style default > style.out
120 $ hg --color=debug log --style default > style.out
118 $ cmp log.out style.out || diff -u log.out style.out
121 $ cmp log.out style.out || diff -u log.out style.out
119 $ hg --color=debug -v log > log.out
122 $ hg --color=debug -v log > log.out
120 $ hg --color=debug -v log --style default > style.out
123 $ hg --color=debug -v log --style default > style.out
121 $ cmp log.out style.out || diff -u log.out style.out
124 $ cmp log.out style.out || diff -u log.out style.out
122 $ hg --color=debug --debug log > log.out
125 $ hg --color=debug --debug log > log.out
123 $ hg --color=debug --debug log --style default > style.out
126 $ hg --color=debug --debug log --style default > style.out
124 $ cmp log.out style.out || diff -u log.out style.out
127 $ cmp log.out style.out || diff -u log.out style.out
125
128
126 $ mv $HGRCPATH-bak $HGRCPATH
129 $ mv $HGRCPATH-bak $HGRCPATH
127
130
128 Revision with no copies (used to print a traceback):
131 Revision with no copies (used to print a traceback):
129
132
130 $ hg tip -v --template '\n'
133 $ hg tip -v --template '\n'
131
134
132
135
133 Compact style works:
136 Compact style works:
134
137
135 $ hg log -Tcompact
138 $ hg log -Tcompact
136 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
139 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
137 third
140 third
138
141
139 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
142 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
140 second
143 second
141
144
142 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
145 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
143 merge
146 merge
144
147
145 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
148 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
146 new head
149 new head
147
150
148 4 bbe44766e73d 1970-01-17 04:53 +0000 person
151 4 bbe44766e73d 1970-01-17 04:53 +0000 person
149 new branch
152 new branch
150
153
151 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
154 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
152 no user, no domain
155 no user, no domain
153
156
154 2 97054abb4ab8 1970-01-14 21:20 +0000 other
157 2 97054abb4ab8 1970-01-14 21:20 +0000 other
155 no person
158 no person
156
159
157 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
160 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
158 other 1
161 other 1
159
162
160 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
163 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
161 line 1
164 line 1
162
165
163
166
164 $ hg log -v --style compact
167 $ hg log -v --style compact
165 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
168 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
166 third
169 third
167
170
168 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
171 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
169 second
172 second
170
173
171 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
174 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
172 merge
175 merge
173
176
174 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
177 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
175 new head
178 new head
176
179
177 4 bbe44766e73d 1970-01-17 04:53 +0000 person
180 4 bbe44766e73d 1970-01-17 04:53 +0000 person
178 new branch
181 new branch
179
182
180 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
183 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
181 no user, no domain
184 no user, no domain
182
185
183 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
186 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
184 no person
187 no person
185
188
186 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
189 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
187 other 1
190 other 1
188 other 2
191 other 2
189
192
190 other 3
193 other 3
191
194
192 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
195 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
193 line 1
196 line 1
194 line 2
197 line 2
195
198
196
199
197 $ hg log --debug --style compact
200 $ hg log --debug --style compact
198 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
201 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
199 third
202 third
200
203
201 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
204 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
202 second
205 second
203
206
204 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
207 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
205 merge
208 merge
206
209
207 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
210 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
208 new head
211 new head
209
212
210 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
213 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
211 new branch
214 new branch
212
215
213 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
216 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
214 no user, no domain
217 no user, no domain
215
218
216 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
219 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
217 no person
220 no person
218
221
219 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
222 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
220 other 1
223 other 1
221 other 2
224 other 2
222
225
223 other 3
226 other 3
224
227
225 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
228 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
226 line 1
229 line 1
227 line 2
230 line 2
228
231
229
232
230 Test xml styles:
233 Test xml styles:
231
234
232 $ hg log --style xml
235 $ hg log --style xml
233 <?xml version="1.0"?>
236 <?xml version="1.0"?>
234 <log>
237 <log>
235 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
238 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
236 <tag>tip</tag>
239 <tag>tip</tag>
237 <author email="test">test</author>
240 <author email="test">test</author>
238 <date>2020-01-01T10:01:00+00:00</date>
241 <date>2020-01-01T10:01:00+00:00</date>
239 <msg xml:space="preserve">third</msg>
242 <msg xml:space="preserve">third</msg>
240 </logentry>
243 </logentry>
241 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
244 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
242 <parent revision="-1" node="0000000000000000000000000000000000000000" />
245 <parent revision="-1" node="0000000000000000000000000000000000000000" />
243 <author email="user@hostname">User Name</author>
246 <author email="user@hostname">User Name</author>
244 <date>1970-01-12T13:46:40+00:00</date>
247 <date>1970-01-12T13:46:40+00:00</date>
245 <msg xml:space="preserve">second</msg>
248 <msg xml:space="preserve">second</msg>
246 </logentry>
249 </logentry>
247 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
250 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
248 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
251 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
249 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
252 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
250 <author email="person">person</author>
253 <author email="person">person</author>
251 <date>1970-01-18T08:40:01+00:00</date>
254 <date>1970-01-18T08:40:01+00:00</date>
252 <msg xml:space="preserve">merge</msg>
255 <msg xml:space="preserve">merge</msg>
253 </logentry>
256 </logentry>
254 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
257 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
255 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
258 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
256 <author email="person">person</author>
259 <author email="person">person</author>
257 <date>1970-01-18T08:40:00+00:00</date>
260 <date>1970-01-18T08:40:00+00:00</date>
258 <msg xml:space="preserve">new head</msg>
261 <msg xml:space="preserve">new head</msg>
259 </logentry>
262 </logentry>
260 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
263 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
261 <branch>foo</branch>
264 <branch>foo</branch>
262 <author email="person">person</author>
265 <author email="person">person</author>
263 <date>1970-01-17T04:53:20+00:00</date>
266 <date>1970-01-17T04:53:20+00:00</date>
264 <msg xml:space="preserve">new branch</msg>
267 <msg xml:space="preserve">new branch</msg>
265 </logentry>
268 </logentry>
266 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
269 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
267 <author email="person">person</author>
270 <author email="person">person</author>
268 <date>1970-01-16T01:06:40+00:00</date>
271 <date>1970-01-16T01:06:40+00:00</date>
269 <msg xml:space="preserve">no user, no domain</msg>
272 <msg xml:space="preserve">no user, no domain</msg>
270 </logentry>
273 </logentry>
271 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
274 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
272 <author email="other@place">other</author>
275 <author email="other@place">other</author>
273 <date>1970-01-14T21:20:00+00:00</date>
276 <date>1970-01-14T21:20:00+00:00</date>
274 <msg xml:space="preserve">no person</msg>
277 <msg xml:space="preserve">no person</msg>
275 </logentry>
278 </logentry>
276 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
279 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
277 <author email="other@place">A. N. Other</author>
280 <author email="other@place">A. N. Other</author>
278 <date>1970-01-13T17:33:20+00:00</date>
281 <date>1970-01-13T17:33:20+00:00</date>
279 <msg xml:space="preserve">other 1
282 <msg xml:space="preserve">other 1
280 other 2
283 other 2
281
284
282 other 3</msg>
285 other 3</msg>
283 </logentry>
286 </logentry>
284 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
287 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
285 <author email="user@hostname">User Name</author>
288 <author email="user@hostname">User Name</author>
286 <date>1970-01-12T13:46:40+00:00</date>
289 <date>1970-01-12T13:46:40+00:00</date>
287 <msg xml:space="preserve">line 1
290 <msg xml:space="preserve">line 1
288 line 2</msg>
291 line 2</msg>
289 </logentry>
292 </logentry>
290 </log>
293 </log>
291
294
292 $ hg log -v --style xml
295 $ hg log -v --style xml
293 <?xml version="1.0"?>
296 <?xml version="1.0"?>
294 <log>
297 <log>
295 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
298 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
296 <tag>tip</tag>
299 <tag>tip</tag>
297 <author email="test">test</author>
300 <author email="test">test</author>
298 <date>2020-01-01T10:01:00+00:00</date>
301 <date>2020-01-01T10:01:00+00:00</date>
299 <msg xml:space="preserve">third</msg>
302 <msg xml:space="preserve">third</msg>
300 <paths>
303 <paths>
301 <path action="A">fourth</path>
304 <path action="A">fourth</path>
302 <path action="A">third</path>
305 <path action="A">third</path>
303 <path action="R">second</path>
306 <path action="R">second</path>
304 </paths>
307 </paths>
305 <copies>
308 <copies>
306 <copy source="second">fourth</copy>
309 <copy source="second">fourth</copy>
307 </copies>
310 </copies>
308 </logentry>
311 </logentry>
309 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
312 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
310 <parent revision="-1" node="0000000000000000000000000000000000000000" />
313 <parent revision="-1" node="0000000000000000000000000000000000000000" />
311 <author email="user@hostname">User Name</author>
314 <author email="user@hostname">User Name</author>
312 <date>1970-01-12T13:46:40+00:00</date>
315 <date>1970-01-12T13:46:40+00:00</date>
313 <msg xml:space="preserve">second</msg>
316 <msg xml:space="preserve">second</msg>
314 <paths>
317 <paths>
315 <path action="A">second</path>
318 <path action="A">second</path>
316 </paths>
319 </paths>
317 </logentry>
320 </logentry>
318 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
321 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
319 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
322 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
320 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
323 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
321 <author email="person">person</author>
324 <author email="person">person</author>
322 <date>1970-01-18T08:40:01+00:00</date>
325 <date>1970-01-18T08:40:01+00:00</date>
323 <msg xml:space="preserve">merge</msg>
326 <msg xml:space="preserve">merge</msg>
324 <paths>
327 <paths>
325 </paths>
328 </paths>
326 </logentry>
329 </logentry>
327 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
330 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
328 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
331 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
329 <author email="person">person</author>
332 <author email="person">person</author>
330 <date>1970-01-18T08:40:00+00:00</date>
333 <date>1970-01-18T08:40:00+00:00</date>
331 <msg xml:space="preserve">new head</msg>
334 <msg xml:space="preserve">new head</msg>
332 <paths>
335 <paths>
333 <path action="A">d</path>
336 <path action="A">d</path>
334 </paths>
337 </paths>
335 </logentry>
338 </logentry>
336 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
339 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
337 <branch>foo</branch>
340 <branch>foo</branch>
338 <author email="person">person</author>
341 <author email="person">person</author>
339 <date>1970-01-17T04:53:20+00:00</date>
342 <date>1970-01-17T04:53:20+00:00</date>
340 <msg xml:space="preserve">new branch</msg>
343 <msg xml:space="preserve">new branch</msg>
341 <paths>
344 <paths>
342 </paths>
345 </paths>
343 </logentry>
346 </logentry>
344 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
347 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
345 <author email="person">person</author>
348 <author email="person">person</author>
346 <date>1970-01-16T01:06:40+00:00</date>
349 <date>1970-01-16T01:06:40+00:00</date>
347 <msg xml:space="preserve">no user, no domain</msg>
350 <msg xml:space="preserve">no user, no domain</msg>
348 <paths>
351 <paths>
349 <path action="M">c</path>
352 <path action="M">c</path>
350 </paths>
353 </paths>
351 </logentry>
354 </logentry>
352 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
355 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
353 <author email="other@place">other</author>
356 <author email="other@place">other</author>
354 <date>1970-01-14T21:20:00+00:00</date>
357 <date>1970-01-14T21:20:00+00:00</date>
355 <msg xml:space="preserve">no person</msg>
358 <msg xml:space="preserve">no person</msg>
356 <paths>
359 <paths>
357 <path action="A">c</path>
360 <path action="A">c</path>
358 </paths>
361 </paths>
359 </logentry>
362 </logentry>
360 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
363 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
361 <author email="other@place">A. N. Other</author>
364 <author email="other@place">A. N. Other</author>
362 <date>1970-01-13T17:33:20+00:00</date>
365 <date>1970-01-13T17:33:20+00:00</date>
363 <msg xml:space="preserve">other 1
366 <msg xml:space="preserve">other 1
364 other 2
367 other 2
365
368
366 other 3</msg>
369 other 3</msg>
367 <paths>
370 <paths>
368 <path action="A">b</path>
371 <path action="A">b</path>
369 </paths>
372 </paths>
370 </logentry>
373 </logentry>
371 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
374 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
372 <author email="user@hostname">User Name</author>
375 <author email="user@hostname">User Name</author>
373 <date>1970-01-12T13:46:40+00:00</date>
376 <date>1970-01-12T13:46:40+00:00</date>
374 <msg xml:space="preserve">line 1
377 <msg xml:space="preserve">line 1
375 line 2</msg>
378 line 2</msg>
376 <paths>
379 <paths>
377 <path action="A">a</path>
380 <path action="A">a</path>
378 </paths>
381 </paths>
379 </logentry>
382 </logentry>
380 </log>
383 </log>
381
384
382 $ hg log --debug --style xml
385 $ hg log --debug --style xml
383 <?xml version="1.0"?>
386 <?xml version="1.0"?>
384 <log>
387 <log>
385 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
388 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
386 <tag>tip</tag>
389 <tag>tip</tag>
387 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
390 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
388 <parent revision="-1" node="0000000000000000000000000000000000000000" />
391 <parent revision="-1" node="0000000000000000000000000000000000000000" />
389 <author email="test">test</author>
392 <author email="test">test</author>
390 <date>2020-01-01T10:01:00+00:00</date>
393 <date>2020-01-01T10:01:00+00:00</date>
391 <msg xml:space="preserve">third</msg>
394 <msg xml:space="preserve">third</msg>
392 <paths>
395 <paths>
393 <path action="A">fourth</path>
396 <path action="A">fourth</path>
394 <path action="A">third</path>
397 <path action="A">third</path>
395 <path action="R">second</path>
398 <path action="R">second</path>
396 </paths>
399 </paths>
397 <copies>
400 <copies>
398 <copy source="second">fourth</copy>
401 <copy source="second">fourth</copy>
399 </copies>
402 </copies>
400 <extra key="branch">default</extra>
403 <extra key="branch">default</extra>
401 </logentry>
404 </logentry>
402 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
405 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
403 <parent revision="-1" node="0000000000000000000000000000000000000000" />
406 <parent revision="-1" node="0000000000000000000000000000000000000000" />
404 <parent revision="-1" node="0000000000000000000000000000000000000000" />
407 <parent revision="-1" node="0000000000000000000000000000000000000000" />
405 <author email="user@hostname">User Name</author>
408 <author email="user@hostname">User Name</author>
406 <date>1970-01-12T13:46:40+00:00</date>
409 <date>1970-01-12T13:46:40+00:00</date>
407 <msg xml:space="preserve">second</msg>
410 <msg xml:space="preserve">second</msg>
408 <paths>
411 <paths>
409 <path action="A">second</path>
412 <path action="A">second</path>
410 </paths>
413 </paths>
411 <extra key="branch">default</extra>
414 <extra key="branch">default</extra>
412 </logentry>
415 </logentry>
413 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
416 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
414 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
417 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
415 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
418 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
416 <author email="person">person</author>
419 <author email="person">person</author>
417 <date>1970-01-18T08:40:01+00:00</date>
420 <date>1970-01-18T08:40:01+00:00</date>
418 <msg xml:space="preserve">merge</msg>
421 <msg xml:space="preserve">merge</msg>
419 <paths>
422 <paths>
420 </paths>
423 </paths>
421 <extra key="branch">default</extra>
424 <extra key="branch">default</extra>
422 </logentry>
425 </logentry>
423 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
426 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
424 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
427 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
425 <parent revision="-1" node="0000000000000000000000000000000000000000" />
428 <parent revision="-1" node="0000000000000000000000000000000000000000" />
426 <author email="person">person</author>
429 <author email="person">person</author>
427 <date>1970-01-18T08:40:00+00:00</date>
430 <date>1970-01-18T08:40:00+00:00</date>
428 <msg xml:space="preserve">new head</msg>
431 <msg xml:space="preserve">new head</msg>
429 <paths>
432 <paths>
430 <path action="A">d</path>
433 <path action="A">d</path>
431 </paths>
434 </paths>
432 <extra key="branch">default</extra>
435 <extra key="branch">default</extra>
433 </logentry>
436 </logentry>
434 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
437 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
435 <branch>foo</branch>
438 <branch>foo</branch>
436 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
439 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
437 <parent revision="-1" node="0000000000000000000000000000000000000000" />
440 <parent revision="-1" node="0000000000000000000000000000000000000000" />
438 <author email="person">person</author>
441 <author email="person">person</author>
439 <date>1970-01-17T04:53:20+00:00</date>
442 <date>1970-01-17T04:53:20+00:00</date>
440 <msg xml:space="preserve">new branch</msg>
443 <msg xml:space="preserve">new branch</msg>
441 <paths>
444 <paths>
442 </paths>
445 </paths>
443 <extra key="branch">foo</extra>
446 <extra key="branch">foo</extra>
444 </logentry>
447 </logentry>
445 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
448 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
446 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
449 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
447 <parent revision="-1" node="0000000000000000000000000000000000000000" />
450 <parent revision="-1" node="0000000000000000000000000000000000000000" />
448 <author email="person">person</author>
451 <author email="person">person</author>
449 <date>1970-01-16T01:06:40+00:00</date>
452 <date>1970-01-16T01:06:40+00:00</date>
450 <msg xml:space="preserve">no user, no domain</msg>
453 <msg xml:space="preserve">no user, no domain</msg>
451 <paths>
454 <paths>
452 <path action="M">c</path>
455 <path action="M">c</path>
453 </paths>
456 </paths>
454 <extra key="branch">default</extra>
457 <extra key="branch">default</extra>
455 </logentry>
458 </logentry>
456 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
459 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
457 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
460 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
458 <parent revision="-1" node="0000000000000000000000000000000000000000" />
461 <parent revision="-1" node="0000000000000000000000000000000000000000" />
459 <author email="other@place">other</author>
462 <author email="other@place">other</author>
460 <date>1970-01-14T21:20:00+00:00</date>
463 <date>1970-01-14T21:20:00+00:00</date>
461 <msg xml:space="preserve">no person</msg>
464 <msg xml:space="preserve">no person</msg>
462 <paths>
465 <paths>
463 <path action="A">c</path>
466 <path action="A">c</path>
464 </paths>
467 </paths>
465 <extra key="branch">default</extra>
468 <extra key="branch">default</extra>
466 </logentry>
469 </logentry>
467 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
470 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
468 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
471 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
469 <parent revision="-1" node="0000000000000000000000000000000000000000" />
472 <parent revision="-1" node="0000000000000000000000000000000000000000" />
470 <author email="other@place">A. N. Other</author>
473 <author email="other@place">A. N. Other</author>
471 <date>1970-01-13T17:33:20+00:00</date>
474 <date>1970-01-13T17:33:20+00:00</date>
472 <msg xml:space="preserve">other 1
475 <msg xml:space="preserve">other 1
473 other 2
476 other 2
474
477
475 other 3</msg>
478 other 3</msg>
476 <paths>
479 <paths>
477 <path action="A">b</path>
480 <path action="A">b</path>
478 </paths>
481 </paths>
479 <extra key="branch">default</extra>
482 <extra key="branch">default</extra>
480 </logentry>
483 </logentry>
481 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
484 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
482 <parent revision="-1" node="0000000000000000000000000000000000000000" />
485 <parent revision="-1" node="0000000000000000000000000000000000000000" />
483 <parent revision="-1" node="0000000000000000000000000000000000000000" />
486 <parent revision="-1" node="0000000000000000000000000000000000000000" />
484 <author email="user@hostname">User Name</author>
487 <author email="user@hostname">User Name</author>
485 <date>1970-01-12T13:46:40+00:00</date>
488 <date>1970-01-12T13:46:40+00:00</date>
486 <msg xml:space="preserve">line 1
489 <msg xml:space="preserve">line 1
487 line 2</msg>
490 line 2</msg>
488 <paths>
491 <paths>
489 <path action="A">a</path>
492 <path action="A">a</path>
490 </paths>
493 </paths>
491 <extra key="branch">default</extra>
494 <extra key="branch">default</extra>
492 </logentry>
495 </logentry>
493 </log>
496 </log>
494
497
495
498
496 Test JSON style:
499 Test JSON style:
497
500
498 $ hg log -k nosuch -Tjson
501 $ hg log -k nosuch -Tjson
499 []
502 []
500
503
501 $ hg log -qr . -Tjson
504 $ hg log -qr . -Tjson
502 [
505 [
503 {
506 {
504 "rev": 8,
507 "rev": 8,
505 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
508 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
506 }
509 }
507 ]
510 ]
508
511
509 $ hg log -vpr . -Tjson --stat
512 $ hg log -vpr . -Tjson --stat
510 [
513 [
511 {
514 {
512 "rev": 8,
515 "rev": 8,
513 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
516 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
514 "branch": "default",
517 "branch": "default",
515 "phase": "draft",
518 "phase": "draft",
516 "user": "test",
519 "user": "test",
517 "date": [1577872860, 0],
520 "date": [1577872860, 0],
518 "desc": "third",
521 "desc": "third",
519 "bookmarks": [],
522 "bookmarks": [],
520 "tags": ["tip"],
523 "tags": ["tip"],
521 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
524 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
522 "files": ["fourth", "second", "third"],
525 "files": ["fourth", "second", "third"],
523 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
526 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
524 "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"
527 "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"
525 }
528 }
526 ]
529 ]
527
530
528 honor --git but not format-breaking diffopts
531 honor --git but not format-breaking diffopts
529 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
532 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
530 [
533 [
531 {
534 {
532 "rev": 8,
535 "rev": 8,
533 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
536 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
534 "branch": "default",
537 "branch": "default",
535 "phase": "draft",
538 "phase": "draft",
536 "user": "test",
539 "user": "test",
537 "date": [1577872860, 0],
540 "date": [1577872860, 0],
538 "desc": "third",
541 "desc": "third",
539 "bookmarks": [],
542 "bookmarks": [],
540 "tags": ["tip"],
543 "tags": ["tip"],
541 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
544 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
542 "files": ["fourth", "second", "third"],
545 "files": ["fourth", "second", "third"],
543 "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"
546 "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"
544 }
547 }
545 ]
548 ]
546
549
547 $ hg log -T json
550 $ hg log -T json
548 [
551 [
549 {
552 {
550 "rev": 8,
553 "rev": 8,
551 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
554 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
552 "branch": "default",
555 "branch": "default",
553 "phase": "draft",
556 "phase": "draft",
554 "user": "test",
557 "user": "test",
555 "date": [1577872860, 0],
558 "date": [1577872860, 0],
556 "desc": "third",
559 "desc": "third",
557 "bookmarks": [],
560 "bookmarks": [],
558 "tags": ["tip"],
561 "tags": ["tip"],
559 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
562 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
560 },
563 },
561 {
564 {
562 "rev": 7,
565 "rev": 7,
563 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
566 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
564 "branch": "default",
567 "branch": "default",
565 "phase": "draft",
568 "phase": "draft",
566 "user": "User Name <user@hostname>",
569 "user": "User Name <user@hostname>",
567 "date": [1000000, 0],
570 "date": [1000000, 0],
568 "desc": "second",
571 "desc": "second",
569 "bookmarks": [],
572 "bookmarks": [],
570 "tags": [],
573 "tags": [],
571 "parents": ["0000000000000000000000000000000000000000"]
574 "parents": ["0000000000000000000000000000000000000000"]
572 },
575 },
573 {
576 {
574 "rev": 6,
577 "rev": 6,
575 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
578 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
576 "branch": "default",
579 "branch": "default",
577 "phase": "draft",
580 "phase": "draft",
578 "user": "person",
581 "user": "person",
579 "date": [1500001, 0],
582 "date": [1500001, 0],
580 "desc": "merge",
583 "desc": "merge",
581 "bookmarks": [],
584 "bookmarks": [],
582 "tags": [],
585 "tags": [],
583 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
586 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
584 },
587 },
585 {
588 {
586 "rev": 5,
589 "rev": 5,
587 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
590 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
588 "branch": "default",
591 "branch": "default",
589 "phase": "draft",
592 "phase": "draft",
590 "user": "person",
593 "user": "person",
591 "date": [1500000, 0],
594 "date": [1500000, 0],
592 "desc": "new head",
595 "desc": "new head",
593 "bookmarks": [],
596 "bookmarks": [],
594 "tags": [],
597 "tags": [],
595 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
598 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
596 },
599 },
597 {
600 {
598 "rev": 4,
601 "rev": 4,
599 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
602 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
600 "branch": "foo",
603 "branch": "foo",
601 "phase": "draft",
604 "phase": "draft",
602 "user": "person",
605 "user": "person",
603 "date": [1400000, 0],
606 "date": [1400000, 0],
604 "desc": "new branch",
607 "desc": "new branch",
605 "bookmarks": [],
608 "bookmarks": [],
606 "tags": [],
609 "tags": [],
607 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
610 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
608 },
611 },
609 {
612 {
610 "rev": 3,
613 "rev": 3,
611 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
614 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
612 "branch": "default",
615 "branch": "default",
613 "phase": "draft",
616 "phase": "draft",
614 "user": "person",
617 "user": "person",
615 "date": [1300000, 0],
618 "date": [1300000, 0],
616 "desc": "no user, no domain",
619 "desc": "no user, no domain",
617 "bookmarks": [],
620 "bookmarks": [],
618 "tags": [],
621 "tags": [],
619 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
622 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
620 },
623 },
621 {
624 {
622 "rev": 2,
625 "rev": 2,
623 "node": "97054abb4ab824450e9164180baf491ae0078465",
626 "node": "97054abb4ab824450e9164180baf491ae0078465",
624 "branch": "default",
627 "branch": "default",
625 "phase": "draft",
628 "phase": "draft",
626 "user": "other@place",
629 "user": "other@place",
627 "date": [1200000, 0],
630 "date": [1200000, 0],
628 "desc": "no person",
631 "desc": "no person",
629 "bookmarks": [],
632 "bookmarks": [],
630 "tags": [],
633 "tags": [],
631 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
634 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
632 },
635 },
633 {
636 {
634 "rev": 1,
637 "rev": 1,
635 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
638 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
636 "branch": "default",
639 "branch": "default",
637 "phase": "draft",
640 "phase": "draft",
638 "user": "A. N. Other <other@place>",
641 "user": "A. N. Other <other@place>",
639 "date": [1100000, 0],
642 "date": [1100000, 0],
640 "desc": "other 1\nother 2\n\nother 3",
643 "desc": "other 1\nother 2\n\nother 3",
641 "bookmarks": [],
644 "bookmarks": [],
642 "tags": [],
645 "tags": [],
643 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
646 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
644 },
647 },
645 {
648 {
646 "rev": 0,
649 "rev": 0,
647 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
650 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
648 "branch": "default",
651 "branch": "default",
649 "phase": "draft",
652 "phase": "draft",
650 "user": "User Name <user@hostname>",
653 "user": "User Name <user@hostname>",
651 "date": [1000000, 0],
654 "date": [1000000, 0],
652 "desc": "line 1\nline 2",
655 "desc": "line 1\nline 2",
653 "bookmarks": [],
656 "bookmarks": [],
654 "tags": [],
657 "tags": [],
655 "parents": ["0000000000000000000000000000000000000000"]
658 "parents": ["0000000000000000000000000000000000000000"]
656 }
659 }
657 ]
660 ]
658
661
659 $ hg heads -v -Tjson
662 $ hg heads -v -Tjson
660 [
663 [
661 {
664 {
662 "rev": 8,
665 "rev": 8,
663 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
666 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
664 "branch": "default",
667 "branch": "default",
665 "phase": "draft",
668 "phase": "draft",
666 "user": "test",
669 "user": "test",
667 "date": [1577872860, 0],
670 "date": [1577872860, 0],
668 "desc": "third",
671 "desc": "third",
669 "bookmarks": [],
672 "bookmarks": [],
670 "tags": ["tip"],
673 "tags": ["tip"],
671 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
674 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
672 "files": ["fourth", "second", "third"]
675 "files": ["fourth", "second", "third"]
673 },
676 },
674 {
677 {
675 "rev": 6,
678 "rev": 6,
676 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
679 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
677 "branch": "default",
680 "branch": "default",
678 "phase": "draft",
681 "phase": "draft",
679 "user": "person",
682 "user": "person",
680 "date": [1500001, 0],
683 "date": [1500001, 0],
681 "desc": "merge",
684 "desc": "merge",
682 "bookmarks": [],
685 "bookmarks": [],
683 "tags": [],
686 "tags": [],
684 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
687 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
685 "files": []
688 "files": []
686 },
689 },
687 {
690 {
688 "rev": 4,
691 "rev": 4,
689 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
692 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
690 "branch": "foo",
693 "branch": "foo",
691 "phase": "draft",
694 "phase": "draft",
692 "user": "person",
695 "user": "person",
693 "date": [1400000, 0],
696 "date": [1400000, 0],
694 "desc": "new branch",
697 "desc": "new branch",
695 "bookmarks": [],
698 "bookmarks": [],
696 "tags": [],
699 "tags": [],
697 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
700 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
698 "files": []
701 "files": []
699 }
702 }
700 ]
703 ]
701
704
702 $ hg log --debug -Tjson
705 $ hg log --debug -Tjson
703 [
706 [
704 {
707 {
705 "rev": 8,
708 "rev": 8,
706 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
709 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
707 "branch": "default",
710 "branch": "default",
708 "phase": "draft",
711 "phase": "draft",
709 "user": "test",
712 "user": "test",
710 "date": [1577872860, 0],
713 "date": [1577872860, 0],
711 "desc": "third",
714 "desc": "third",
712 "bookmarks": [],
715 "bookmarks": [],
713 "tags": ["tip"],
716 "tags": ["tip"],
714 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
717 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
715 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
718 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
716 "extra": {"branch": "default"},
719 "extra": {"branch": "default"},
717 "modified": [],
720 "modified": [],
718 "added": ["fourth", "third"],
721 "added": ["fourth", "third"],
719 "removed": ["second"]
722 "removed": ["second"]
720 },
723 },
721 {
724 {
722 "rev": 7,
725 "rev": 7,
723 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
726 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
724 "branch": "default",
727 "branch": "default",
725 "phase": "draft",
728 "phase": "draft",
726 "user": "User Name <user@hostname>",
729 "user": "User Name <user@hostname>",
727 "date": [1000000, 0],
730 "date": [1000000, 0],
728 "desc": "second",
731 "desc": "second",
729 "bookmarks": [],
732 "bookmarks": [],
730 "tags": [],
733 "tags": [],
731 "parents": ["0000000000000000000000000000000000000000"],
734 "parents": ["0000000000000000000000000000000000000000"],
732 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
735 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
733 "extra": {"branch": "default"},
736 "extra": {"branch": "default"},
734 "modified": [],
737 "modified": [],
735 "added": ["second"],
738 "added": ["second"],
736 "removed": []
739 "removed": []
737 },
740 },
738 {
741 {
739 "rev": 6,
742 "rev": 6,
740 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
743 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
741 "branch": "default",
744 "branch": "default",
742 "phase": "draft",
745 "phase": "draft",
743 "user": "person",
746 "user": "person",
744 "date": [1500001, 0],
747 "date": [1500001, 0],
745 "desc": "merge",
748 "desc": "merge",
746 "bookmarks": [],
749 "bookmarks": [],
747 "tags": [],
750 "tags": [],
748 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
751 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
749 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
752 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
750 "extra": {"branch": "default"},
753 "extra": {"branch": "default"},
751 "modified": [],
754 "modified": [],
752 "added": [],
755 "added": [],
753 "removed": []
756 "removed": []
754 },
757 },
755 {
758 {
756 "rev": 5,
759 "rev": 5,
757 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
760 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
758 "branch": "default",
761 "branch": "default",
759 "phase": "draft",
762 "phase": "draft",
760 "user": "person",
763 "user": "person",
761 "date": [1500000, 0],
764 "date": [1500000, 0],
762 "desc": "new head",
765 "desc": "new head",
763 "bookmarks": [],
766 "bookmarks": [],
764 "tags": [],
767 "tags": [],
765 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
768 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
766 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
769 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
767 "extra": {"branch": "default"},
770 "extra": {"branch": "default"},
768 "modified": [],
771 "modified": [],
769 "added": ["d"],
772 "added": ["d"],
770 "removed": []
773 "removed": []
771 },
774 },
772 {
775 {
773 "rev": 4,
776 "rev": 4,
774 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
777 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
775 "branch": "foo",
778 "branch": "foo",
776 "phase": "draft",
779 "phase": "draft",
777 "user": "person",
780 "user": "person",
778 "date": [1400000, 0],
781 "date": [1400000, 0],
779 "desc": "new branch",
782 "desc": "new branch",
780 "bookmarks": [],
783 "bookmarks": [],
781 "tags": [],
784 "tags": [],
782 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
785 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
783 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
786 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
784 "extra": {"branch": "foo"},
787 "extra": {"branch": "foo"},
785 "modified": [],
788 "modified": [],
786 "added": [],
789 "added": [],
787 "removed": []
790 "removed": []
788 },
791 },
789 {
792 {
790 "rev": 3,
793 "rev": 3,
791 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
794 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
792 "branch": "default",
795 "branch": "default",
793 "phase": "draft",
796 "phase": "draft",
794 "user": "person",
797 "user": "person",
795 "date": [1300000, 0],
798 "date": [1300000, 0],
796 "desc": "no user, no domain",
799 "desc": "no user, no domain",
797 "bookmarks": [],
800 "bookmarks": [],
798 "tags": [],
801 "tags": [],
799 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
802 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
800 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
803 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
801 "extra": {"branch": "default"},
804 "extra": {"branch": "default"},
802 "modified": ["c"],
805 "modified": ["c"],
803 "added": [],
806 "added": [],
804 "removed": []
807 "removed": []
805 },
808 },
806 {
809 {
807 "rev": 2,
810 "rev": 2,
808 "node": "97054abb4ab824450e9164180baf491ae0078465",
811 "node": "97054abb4ab824450e9164180baf491ae0078465",
809 "branch": "default",
812 "branch": "default",
810 "phase": "draft",
813 "phase": "draft",
811 "user": "other@place",
814 "user": "other@place",
812 "date": [1200000, 0],
815 "date": [1200000, 0],
813 "desc": "no person",
816 "desc": "no person",
814 "bookmarks": [],
817 "bookmarks": [],
815 "tags": [],
818 "tags": [],
816 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
819 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
817 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
820 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
818 "extra": {"branch": "default"},
821 "extra": {"branch": "default"},
819 "modified": [],
822 "modified": [],
820 "added": ["c"],
823 "added": ["c"],
821 "removed": []
824 "removed": []
822 },
825 },
823 {
826 {
824 "rev": 1,
827 "rev": 1,
825 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
828 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
826 "branch": "default",
829 "branch": "default",
827 "phase": "draft",
830 "phase": "draft",
828 "user": "A. N. Other <other@place>",
831 "user": "A. N. Other <other@place>",
829 "date": [1100000, 0],
832 "date": [1100000, 0],
830 "desc": "other 1\nother 2\n\nother 3",
833 "desc": "other 1\nother 2\n\nother 3",
831 "bookmarks": [],
834 "bookmarks": [],
832 "tags": [],
835 "tags": [],
833 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
836 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
834 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
837 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
835 "extra": {"branch": "default"},
838 "extra": {"branch": "default"},
836 "modified": [],
839 "modified": [],
837 "added": ["b"],
840 "added": ["b"],
838 "removed": []
841 "removed": []
839 },
842 },
840 {
843 {
841 "rev": 0,
844 "rev": 0,
842 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
845 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
843 "branch": "default",
846 "branch": "default",
844 "phase": "draft",
847 "phase": "draft",
845 "user": "User Name <user@hostname>",
848 "user": "User Name <user@hostname>",
846 "date": [1000000, 0],
849 "date": [1000000, 0],
847 "desc": "line 1\nline 2",
850 "desc": "line 1\nline 2",
848 "bookmarks": [],
851 "bookmarks": [],
849 "tags": [],
852 "tags": [],
850 "parents": ["0000000000000000000000000000000000000000"],
853 "parents": ["0000000000000000000000000000000000000000"],
851 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
854 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
852 "extra": {"branch": "default"},
855 "extra": {"branch": "default"},
853 "modified": [],
856 "modified": [],
854 "added": ["a"],
857 "added": ["a"],
855 "removed": []
858 "removed": []
856 }
859 }
857 ]
860 ]
858
861
859 Error if style not readable:
862 Error if style not readable:
860
863
861 #if unix-permissions no-root
864 #if unix-permissions no-root
862 $ touch q
865 $ touch q
863 $ chmod 0 q
866 $ chmod 0 q
864 $ hg log --style ./q
867 $ hg log --style ./q
865 abort: Permission denied: ./q
868 abort: Permission denied: ./q
866 [255]
869 [255]
867 #endif
870 #endif
868
871
869 Error if no style:
872 Error if no style:
870
873
871 $ hg log --style notexist
874 $ hg log --style notexist
872 abort: style 'notexist' not found
875 abort: style 'notexist' not found
873 (available styles: bisect, changelog, compact, default, phases, xml)
876 (available styles: bisect, changelog, compact, default, phases, xml)
874 [255]
877 [255]
875
878
876 $ hg log -T list
879 $ hg log -T list
877 available styles: bisect, changelog, compact, default, phases, xml
880 available styles: bisect, changelog, compact, default, phases, xml
878 abort: specify a template
881 abort: specify a template
879 [255]
882 [255]
880
883
881 Error if style missing key:
884 Error if style missing key:
882
885
883 $ echo 'q = q' > t
886 $ echo 'q = q' > t
884 $ hg log --style ./t
887 $ hg log --style ./t
885 abort: "changeset" not in template map
888 abort: "changeset" not in template map
886 [255]
889 [255]
887
890
888 Error if style missing value:
891 Error if style missing value:
889
892
890 $ echo 'changeset =' > t
893 $ echo 'changeset =' > t
891 $ hg log --style t
894 $ hg log --style t
892 abort: t:1: missing value
895 abort: t:1: missing value
893 [255]
896 [255]
894
897
895 Error if include fails:
898 Error if include fails:
896
899
897 $ echo 'changeset = q' >> t
900 $ echo 'changeset = q' >> t
898 #if unix-permissions no-root
901 #if unix-permissions no-root
899 $ hg log --style ./t
902 $ hg log --style ./t
900 abort: template file ./q: Permission denied
903 abort: template file ./q: Permission denied
901 [255]
904 [255]
902 $ rm q
905 $ rm q
903 #endif
906 #endif
904
907
905 Include works:
908 Include works:
906
909
907 $ echo '{rev}' > q
910 $ echo '{rev}' > q
908 $ hg log --style ./t
911 $ hg log --style ./t
909 8
912 8
910 7
913 7
911 6
914 6
912 5
915 5
913 4
916 4
914 3
917 3
915 2
918 2
916 1
919 1
917 0
920 0
918
921
919 Check that {phase} works correctly on parents:
922 Check that {phase} works correctly on parents:
920
923
921 $ cat << EOF > parentphase
924 $ cat << EOF > parentphase
922 > changeset_debug = '{rev} ({phase}):{parents}\n'
925 > changeset_debug = '{rev} ({phase}):{parents}\n'
923 > parent = ' {rev} ({phase})'
926 > parent = ' {rev} ({phase})'
924 > EOF
927 > EOF
925 $ hg phase -r 5 --public
928 $ hg phase -r 5 --public
926 $ hg phase -r 7 --secret --force
929 $ hg phase -r 7 --secret --force
927 $ hg log --debug -G --style ./parentphase
930 $ hg log --debug -G --style ./parentphase
928 @ 8 (secret): 7 (secret) -1 (public)
931 @ 8 (secret): 7 (secret) -1 (public)
929 |
932 |
930 o 7 (secret): -1 (public) -1 (public)
933 o 7 (secret): -1 (public) -1 (public)
931
934
932 o 6 (draft): 5 (public) 4 (draft)
935 o 6 (draft): 5 (public) 4 (draft)
933 |\
936 |\
934 | o 5 (public): 3 (public) -1 (public)
937 | o 5 (public): 3 (public) -1 (public)
935 | |
938 | |
936 o | 4 (draft): 3 (public) -1 (public)
939 o | 4 (draft): 3 (public) -1 (public)
937 |/
940 |/
938 o 3 (public): 2 (public) -1 (public)
941 o 3 (public): 2 (public) -1 (public)
939 |
942 |
940 o 2 (public): 1 (public) -1 (public)
943 o 2 (public): 1 (public) -1 (public)
941 |
944 |
942 o 1 (public): 0 (public) -1 (public)
945 o 1 (public): 0 (public) -1 (public)
943 |
946 |
944 o 0 (public): -1 (public) -1 (public)
947 o 0 (public): -1 (public) -1 (public)
945
948
946
949
947 Missing non-standard names give no error (backward compatibility):
950 Missing non-standard names give no error (backward compatibility):
948
951
949 $ echo "changeset = '{c}'" > t
952 $ echo "changeset = '{c}'" > t
950 $ hg log --style ./t
953 $ hg log --style ./t
951
954
952 Defining non-standard name works:
955 Defining non-standard name works:
953
956
954 $ cat <<EOF > t
957 $ cat <<EOF > t
955 > changeset = '{c}'
958 > changeset = '{c}'
956 > c = q
959 > c = q
957 > EOF
960 > EOF
958 $ hg log --style ./t
961 $ hg log --style ./t
959 8
962 8
960 7
963 7
961 6
964 6
962 5
965 5
963 4
966 4
964 3
967 3
965 2
968 2
966 1
969 1
967 0
970 0
968
971
969 ui.style works:
972 ui.style works:
970
973
971 $ echo '[ui]' > .hg/hgrc
974 $ echo '[ui]' > .hg/hgrc
972 $ echo 'style = t' >> .hg/hgrc
975 $ echo 'style = t' >> .hg/hgrc
973 $ hg log
976 $ hg log
974 8
977 8
975 7
978 7
976 6
979 6
977 5
980 5
978 4
981 4
979 3
982 3
980 2
983 2
981 1
984 1
982 0
985 0
983
986
984
987
985 Issue338:
988 Issue338:
986
989
987 $ hg log --style=changelog > changelog
990 $ hg log --style=changelog > changelog
988
991
989 $ cat changelog
992 $ cat changelog
990 2020-01-01 test <test>
993 2020-01-01 test <test>
991
994
992 * fourth, second, third:
995 * fourth, second, third:
993 third
996 third
994 [95c24699272e] [tip]
997 [95c24699272e] [tip]
995
998
996 1970-01-12 User Name <user@hostname>
999 1970-01-12 User Name <user@hostname>
997
1000
998 * second:
1001 * second:
999 second
1002 second
1000 [29114dbae42b]
1003 [29114dbae42b]
1001
1004
1002 1970-01-18 person <person>
1005 1970-01-18 person <person>
1003
1006
1004 * merge
1007 * merge
1005 [d41e714fe50d]
1008 [d41e714fe50d]
1006
1009
1007 * d:
1010 * d:
1008 new head
1011 new head
1009 [13207e5a10d9]
1012 [13207e5a10d9]
1010
1013
1011 1970-01-17 person <person>
1014 1970-01-17 person <person>
1012
1015
1013 * new branch
1016 * new branch
1014 [bbe44766e73d] <foo>
1017 [bbe44766e73d] <foo>
1015
1018
1016 1970-01-16 person <person>
1019 1970-01-16 person <person>
1017
1020
1018 * c:
1021 * c:
1019 no user, no domain
1022 no user, no domain
1020 [10e46f2dcbf4]
1023 [10e46f2dcbf4]
1021
1024
1022 1970-01-14 other <other@place>
1025 1970-01-14 other <other@place>
1023
1026
1024 * c:
1027 * c:
1025 no person
1028 no person
1026 [97054abb4ab8]
1029 [97054abb4ab8]
1027
1030
1028 1970-01-13 A. N. Other <other@place>
1031 1970-01-13 A. N. Other <other@place>
1029
1032
1030 * b:
1033 * b:
1031 other 1 other 2
1034 other 1 other 2
1032
1035
1033 other 3
1036 other 3
1034 [b608e9d1a3f0]
1037 [b608e9d1a3f0]
1035
1038
1036 1970-01-12 User Name <user@hostname>
1039 1970-01-12 User Name <user@hostname>
1037
1040
1038 * a:
1041 * a:
1039 line 1 line 2
1042 line 1 line 2
1040 [1e4e1b8f71e0]
1043 [1e4e1b8f71e0]
1041
1044
1042
1045
1043 Issue2130: xml output for 'hg heads' is malformed
1046 Issue2130: xml output for 'hg heads' is malformed
1044
1047
1045 $ hg heads --style changelog
1048 $ hg heads --style changelog
1046 2020-01-01 test <test>
1049 2020-01-01 test <test>
1047
1050
1048 * fourth, second, third:
1051 * fourth, second, third:
1049 third
1052 third
1050 [95c24699272e] [tip]
1053 [95c24699272e] [tip]
1051
1054
1052 1970-01-18 person <person>
1055 1970-01-18 person <person>
1053
1056
1054 * merge
1057 * merge
1055 [d41e714fe50d]
1058 [d41e714fe50d]
1056
1059
1057 1970-01-17 person <person>
1060 1970-01-17 person <person>
1058
1061
1059 * new branch
1062 * new branch
1060 [bbe44766e73d] <foo>
1063 [bbe44766e73d] <foo>
1061
1064
1062
1065
1063 Keys work:
1066 Keys work:
1064
1067
1065 $ for key in author branch branches date desc file_adds file_dels file_mods \
1068 $ for key in author branch branches date desc file_adds file_dels file_mods \
1066 > file_copies file_copies_switch files \
1069 > file_copies file_copies_switch files \
1067 > manifest node parents rev tags diffstat extras \
1070 > manifest node parents rev tags diffstat extras \
1068 > p1rev p2rev p1node p2node; do
1071 > p1rev p2rev p1node p2node; do
1069 > for mode in '' --verbose --debug; do
1072 > for mode in '' --verbose --debug; do
1070 > hg log $mode --template "$key$mode: {$key}\n"
1073 > hg log $mode --template "$key$mode: {$key}\n"
1071 > done
1074 > done
1072 > done
1075 > done
1073 author: test
1076 author: test
1074 author: User Name <user@hostname>
1077 author: User Name <user@hostname>
1075 author: person
1078 author: person
1076 author: person
1079 author: person
1077 author: person
1080 author: person
1078 author: person
1081 author: person
1079 author: other@place
1082 author: other@place
1080 author: A. N. Other <other@place>
1083 author: A. N. Other <other@place>
1081 author: User Name <user@hostname>
1084 author: User Name <user@hostname>
1082 author--verbose: test
1085 author--verbose: test
1083 author--verbose: User Name <user@hostname>
1086 author--verbose: User Name <user@hostname>
1084 author--verbose: person
1087 author--verbose: person
1085 author--verbose: person
1088 author--verbose: person
1086 author--verbose: person
1089 author--verbose: person
1087 author--verbose: person
1090 author--verbose: person
1088 author--verbose: other@place
1091 author--verbose: other@place
1089 author--verbose: A. N. Other <other@place>
1092 author--verbose: A. N. Other <other@place>
1090 author--verbose: User Name <user@hostname>
1093 author--verbose: User Name <user@hostname>
1091 author--debug: test
1094 author--debug: test
1092 author--debug: User Name <user@hostname>
1095 author--debug: User Name <user@hostname>
1093 author--debug: person
1096 author--debug: person
1094 author--debug: person
1097 author--debug: person
1095 author--debug: person
1098 author--debug: person
1096 author--debug: person
1099 author--debug: person
1097 author--debug: other@place
1100 author--debug: other@place
1098 author--debug: A. N. Other <other@place>
1101 author--debug: A. N. Other <other@place>
1099 author--debug: User Name <user@hostname>
1102 author--debug: User Name <user@hostname>
1100 branch: default
1103 branch: default
1101 branch: default
1104 branch: default
1102 branch: default
1105 branch: default
1103 branch: default
1106 branch: default
1104 branch: foo
1107 branch: foo
1105 branch: default
1108 branch: default
1106 branch: default
1109 branch: default
1107 branch: default
1110 branch: default
1108 branch: default
1111 branch: default
1109 branch--verbose: default
1112 branch--verbose: default
1110 branch--verbose: default
1113 branch--verbose: default
1111 branch--verbose: default
1114 branch--verbose: default
1112 branch--verbose: default
1115 branch--verbose: default
1113 branch--verbose: foo
1116 branch--verbose: foo
1114 branch--verbose: default
1117 branch--verbose: default
1115 branch--verbose: default
1118 branch--verbose: default
1116 branch--verbose: default
1119 branch--verbose: default
1117 branch--verbose: default
1120 branch--verbose: default
1118 branch--debug: default
1121 branch--debug: default
1119 branch--debug: default
1122 branch--debug: default
1120 branch--debug: default
1123 branch--debug: default
1121 branch--debug: default
1124 branch--debug: default
1122 branch--debug: foo
1125 branch--debug: foo
1123 branch--debug: default
1126 branch--debug: default
1124 branch--debug: default
1127 branch--debug: default
1125 branch--debug: default
1128 branch--debug: default
1126 branch--debug: default
1129 branch--debug: default
1127 branches:
1130 branches:
1128 branches:
1131 branches:
1129 branches:
1132 branches:
1130 branches:
1133 branches:
1131 branches: foo
1134 branches: foo
1132 branches:
1135 branches:
1133 branches:
1136 branches:
1134 branches:
1137 branches:
1135 branches:
1138 branches:
1136 branches--verbose:
1139 branches--verbose:
1137 branches--verbose:
1140 branches--verbose:
1138 branches--verbose:
1141 branches--verbose:
1139 branches--verbose:
1142 branches--verbose:
1140 branches--verbose: foo
1143 branches--verbose: foo
1141 branches--verbose:
1144 branches--verbose:
1142 branches--verbose:
1145 branches--verbose:
1143 branches--verbose:
1146 branches--verbose:
1144 branches--verbose:
1147 branches--verbose:
1145 branches--debug:
1148 branches--debug:
1146 branches--debug:
1149 branches--debug:
1147 branches--debug:
1150 branches--debug:
1148 branches--debug:
1151 branches--debug:
1149 branches--debug: foo
1152 branches--debug: foo
1150 branches--debug:
1153 branches--debug:
1151 branches--debug:
1154 branches--debug:
1152 branches--debug:
1155 branches--debug:
1153 branches--debug:
1156 branches--debug:
1154 date: 1577872860.00
1157 date: 1577872860.00
1155 date: 1000000.00
1158 date: 1000000.00
1156 date: 1500001.00
1159 date: 1500001.00
1157 date: 1500000.00
1160 date: 1500000.00
1158 date: 1400000.00
1161 date: 1400000.00
1159 date: 1300000.00
1162 date: 1300000.00
1160 date: 1200000.00
1163 date: 1200000.00
1161 date: 1100000.00
1164 date: 1100000.00
1162 date: 1000000.00
1165 date: 1000000.00
1163 date--verbose: 1577872860.00
1166 date--verbose: 1577872860.00
1164 date--verbose: 1000000.00
1167 date--verbose: 1000000.00
1165 date--verbose: 1500001.00
1168 date--verbose: 1500001.00
1166 date--verbose: 1500000.00
1169 date--verbose: 1500000.00
1167 date--verbose: 1400000.00
1170 date--verbose: 1400000.00
1168 date--verbose: 1300000.00
1171 date--verbose: 1300000.00
1169 date--verbose: 1200000.00
1172 date--verbose: 1200000.00
1170 date--verbose: 1100000.00
1173 date--verbose: 1100000.00
1171 date--verbose: 1000000.00
1174 date--verbose: 1000000.00
1172 date--debug: 1577872860.00
1175 date--debug: 1577872860.00
1173 date--debug: 1000000.00
1176 date--debug: 1000000.00
1174 date--debug: 1500001.00
1177 date--debug: 1500001.00
1175 date--debug: 1500000.00
1178 date--debug: 1500000.00
1176 date--debug: 1400000.00
1179 date--debug: 1400000.00
1177 date--debug: 1300000.00
1180 date--debug: 1300000.00
1178 date--debug: 1200000.00
1181 date--debug: 1200000.00
1179 date--debug: 1100000.00
1182 date--debug: 1100000.00
1180 date--debug: 1000000.00
1183 date--debug: 1000000.00
1181 desc: third
1184 desc: third
1182 desc: second
1185 desc: second
1183 desc: merge
1186 desc: merge
1184 desc: new head
1187 desc: new head
1185 desc: new branch
1188 desc: new branch
1186 desc: no user, no domain
1189 desc: no user, no domain
1187 desc: no person
1190 desc: no person
1188 desc: other 1
1191 desc: other 1
1189 other 2
1192 other 2
1190
1193
1191 other 3
1194 other 3
1192 desc: line 1
1195 desc: line 1
1193 line 2
1196 line 2
1194 desc--verbose: third
1197 desc--verbose: third
1195 desc--verbose: second
1198 desc--verbose: second
1196 desc--verbose: merge
1199 desc--verbose: merge
1197 desc--verbose: new head
1200 desc--verbose: new head
1198 desc--verbose: new branch
1201 desc--verbose: new branch
1199 desc--verbose: no user, no domain
1202 desc--verbose: no user, no domain
1200 desc--verbose: no person
1203 desc--verbose: no person
1201 desc--verbose: other 1
1204 desc--verbose: other 1
1202 other 2
1205 other 2
1203
1206
1204 other 3
1207 other 3
1205 desc--verbose: line 1
1208 desc--verbose: line 1
1206 line 2
1209 line 2
1207 desc--debug: third
1210 desc--debug: third
1208 desc--debug: second
1211 desc--debug: second
1209 desc--debug: merge
1212 desc--debug: merge
1210 desc--debug: new head
1213 desc--debug: new head
1211 desc--debug: new branch
1214 desc--debug: new branch
1212 desc--debug: no user, no domain
1215 desc--debug: no user, no domain
1213 desc--debug: no person
1216 desc--debug: no person
1214 desc--debug: other 1
1217 desc--debug: other 1
1215 other 2
1218 other 2
1216
1219
1217 other 3
1220 other 3
1218 desc--debug: line 1
1221 desc--debug: line 1
1219 line 2
1222 line 2
1220 file_adds: fourth third
1223 file_adds: fourth third
1221 file_adds: second
1224 file_adds: second
1222 file_adds:
1225 file_adds:
1223 file_adds: d
1226 file_adds: d
1224 file_adds:
1227 file_adds:
1225 file_adds:
1228 file_adds:
1226 file_adds: c
1229 file_adds: c
1227 file_adds: b
1230 file_adds: b
1228 file_adds: a
1231 file_adds: a
1229 file_adds--verbose: fourth third
1232 file_adds--verbose: fourth third
1230 file_adds--verbose: second
1233 file_adds--verbose: second
1231 file_adds--verbose:
1234 file_adds--verbose:
1232 file_adds--verbose: d
1235 file_adds--verbose: d
1233 file_adds--verbose:
1236 file_adds--verbose:
1234 file_adds--verbose:
1237 file_adds--verbose:
1235 file_adds--verbose: c
1238 file_adds--verbose: c
1236 file_adds--verbose: b
1239 file_adds--verbose: b
1237 file_adds--verbose: a
1240 file_adds--verbose: a
1238 file_adds--debug: fourth third
1241 file_adds--debug: fourth third
1239 file_adds--debug: second
1242 file_adds--debug: second
1240 file_adds--debug:
1243 file_adds--debug:
1241 file_adds--debug: d
1244 file_adds--debug: d
1242 file_adds--debug:
1245 file_adds--debug:
1243 file_adds--debug:
1246 file_adds--debug:
1244 file_adds--debug: c
1247 file_adds--debug: c
1245 file_adds--debug: b
1248 file_adds--debug: b
1246 file_adds--debug: a
1249 file_adds--debug: a
1247 file_dels: second
1250 file_dels: second
1248 file_dels:
1251 file_dels:
1249 file_dels:
1252 file_dels:
1250 file_dels:
1253 file_dels:
1251 file_dels:
1254 file_dels:
1252 file_dels:
1255 file_dels:
1253 file_dels:
1256 file_dels:
1254 file_dels:
1257 file_dels:
1255 file_dels:
1258 file_dels:
1256 file_dels--verbose: second
1259 file_dels--verbose: second
1257 file_dels--verbose:
1260 file_dels--verbose:
1258 file_dels--verbose:
1261 file_dels--verbose:
1259 file_dels--verbose:
1262 file_dels--verbose:
1260 file_dels--verbose:
1263 file_dels--verbose:
1261 file_dels--verbose:
1264 file_dels--verbose:
1262 file_dels--verbose:
1265 file_dels--verbose:
1263 file_dels--verbose:
1266 file_dels--verbose:
1264 file_dels--verbose:
1267 file_dels--verbose:
1265 file_dels--debug: second
1268 file_dels--debug: second
1266 file_dels--debug:
1269 file_dels--debug:
1267 file_dels--debug:
1270 file_dels--debug:
1268 file_dels--debug:
1271 file_dels--debug:
1269 file_dels--debug:
1272 file_dels--debug:
1270 file_dels--debug:
1273 file_dels--debug:
1271 file_dels--debug:
1274 file_dels--debug:
1272 file_dels--debug:
1275 file_dels--debug:
1273 file_dels--debug:
1276 file_dels--debug:
1274 file_mods:
1277 file_mods:
1275 file_mods:
1278 file_mods:
1276 file_mods:
1279 file_mods:
1277 file_mods:
1280 file_mods:
1278 file_mods:
1281 file_mods:
1279 file_mods: c
1282 file_mods: c
1280 file_mods:
1283 file_mods:
1281 file_mods:
1284 file_mods:
1282 file_mods:
1285 file_mods:
1283 file_mods--verbose:
1286 file_mods--verbose:
1284 file_mods--verbose:
1287 file_mods--verbose:
1285 file_mods--verbose:
1288 file_mods--verbose:
1286 file_mods--verbose:
1289 file_mods--verbose:
1287 file_mods--verbose:
1290 file_mods--verbose:
1288 file_mods--verbose: c
1291 file_mods--verbose: c
1289 file_mods--verbose:
1292 file_mods--verbose:
1290 file_mods--verbose:
1293 file_mods--verbose:
1291 file_mods--verbose:
1294 file_mods--verbose:
1292 file_mods--debug:
1295 file_mods--debug:
1293 file_mods--debug:
1296 file_mods--debug:
1294 file_mods--debug:
1297 file_mods--debug:
1295 file_mods--debug:
1298 file_mods--debug:
1296 file_mods--debug:
1299 file_mods--debug:
1297 file_mods--debug: c
1300 file_mods--debug: c
1298 file_mods--debug:
1301 file_mods--debug:
1299 file_mods--debug:
1302 file_mods--debug:
1300 file_mods--debug:
1303 file_mods--debug:
1301 file_copies: fourth (second)
1304 file_copies: fourth (second)
1302 file_copies:
1305 file_copies:
1303 file_copies:
1306 file_copies:
1304 file_copies:
1307 file_copies:
1305 file_copies:
1308 file_copies:
1306 file_copies:
1309 file_copies:
1307 file_copies:
1310 file_copies:
1308 file_copies:
1311 file_copies:
1309 file_copies:
1312 file_copies:
1310 file_copies--verbose: fourth (second)
1313 file_copies--verbose: fourth (second)
1311 file_copies--verbose:
1314 file_copies--verbose:
1312 file_copies--verbose:
1315 file_copies--verbose:
1313 file_copies--verbose:
1316 file_copies--verbose:
1314 file_copies--verbose:
1317 file_copies--verbose:
1315 file_copies--verbose:
1318 file_copies--verbose:
1316 file_copies--verbose:
1319 file_copies--verbose:
1317 file_copies--verbose:
1320 file_copies--verbose:
1318 file_copies--verbose:
1321 file_copies--verbose:
1319 file_copies--debug: fourth (second)
1322 file_copies--debug: fourth (second)
1320 file_copies--debug:
1323 file_copies--debug:
1321 file_copies--debug:
1324 file_copies--debug:
1322 file_copies--debug:
1325 file_copies--debug:
1323 file_copies--debug:
1326 file_copies--debug:
1324 file_copies--debug:
1327 file_copies--debug:
1325 file_copies--debug:
1328 file_copies--debug:
1326 file_copies--debug:
1329 file_copies--debug:
1327 file_copies--debug:
1330 file_copies--debug:
1328 file_copies_switch:
1331 file_copies_switch:
1329 file_copies_switch:
1332 file_copies_switch:
1330 file_copies_switch:
1333 file_copies_switch:
1331 file_copies_switch:
1334 file_copies_switch:
1332 file_copies_switch:
1335 file_copies_switch:
1333 file_copies_switch:
1336 file_copies_switch:
1334 file_copies_switch:
1337 file_copies_switch:
1335 file_copies_switch:
1338 file_copies_switch:
1336 file_copies_switch:
1339 file_copies_switch:
1337 file_copies_switch--verbose:
1340 file_copies_switch--verbose:
1338 file_copies_switch--verbose:
1341 file_copies_switch--verbose:
1339 file_copies_switch--verbose:
1342 file_copies_switch--verbose:
1340 file_copies_switch--verbose:
1343 file_copies_switch--verbose:
1341 file_copies_switch--verbose:
1344 file_copies_switch--verbose:
1342 file_copies_switch--verbose:
1345 file_copies_switch--verbose:
1343 file_copies_switch--verbose:
1346 file_copies_switch--verbose:
1344 file_copies_switch--verbose:
1347 file_copies_switch--verbose:
1345 file_copies_switch--verbose:
1348 file_copies_switch--verbose:
1346 file_copies_switch--debug:
1349 file_copies_switch--debug:
1347 file_copies_switch--debug:
1350 file_copies_switch--debug:
1348 file_copies_switch--debug:
1351 file_copies_switch--debug:
1349 file_copies_switch--debug:
1352 file_copies_switch--debug:
1350 file_copies_switch--debug:
1353 file_copies_switch--debug:
1351 file_copies_switch--debug:
1354 file_copies_switch--debug:
1352 file_copies_switch--debug:
1355 file_copies_switch--debug:
1353 file_copies_switch--debug:
1356 file_copies_switch--debug:
1354 file_copies_switch--debug:
1357 file_copies_switch--debug:
1355 files: fourth second third
1358 files: fourth second third
1356 files: second
1359 files: second
1357 files:
1360 files:
1358 files: d
1361 files: d
1359 files:
1362 files:
1360 files: c
1363 files: c
1361 files: c
1364 files: c
1362 files: b
1365 files: b
1363 files: a
1366 files: a
1364 files--verbose: fourth second third
1367 files--verbose: fourth second third
1365 files--verbose: second
1368 files--verbose: second
1366 files--verbose:
1369 files--verbose:
1367 files--verbose: d
1370 files--verbose: d
1368 files--verbose:
1371 files--verbose:
1369 files--verbose: c
1372 files--verbose: c
1370 files--verbose: c
1373 files--verbose: c
1371 files--verbose: b
1374 files--verbose: b
1372 files--verbose: a
1375 files--verbose: a
1373 files--debug: fourth second third
1376 files--debug: fourth second third
1374 files--debug: second
1377 files--debug: second
1375 files--debug:
1378 files--debug:
1376 files--debug: d
1379 files--debug: d
1377 files--debug:
1380 files--debug:
1378 files--debug: c
1381 files--debug: c
1379 files--debug: c
1382 files--debug: c
1380 files--debug: b
1383 files--debug: b
1381 files--debug: a
1384 files--debug: a
1382 manifest: 6:94961b75a2da
1385 manifest: 6:94961b75a2da
1383 manifest: 5:f2dbc354b94e
1386 manifest: 5:f2dbc354b94e
1384 manifest: 4:4dc3def4f9b4
1387 manifest: 4:4dc3def4f9b4
1385 manifest: 4:4dc3def4f9b4
1388 manifest: 4:4dc3def4f9b4
1386 manifest: 3:cb5a1327723b
1389 manifest: 3:cb5a1327723b
1387 manifest: 3:cb5a1327723b
1390 manifest: 3:cb5a1327723b
1388 manifest: 2:6e0e82995c35
1391 manifest: 2:6e0e82995c35
1389 manifest: 1:4e8d705b1e53
1392 manifest: 1:4e8d705b1e53
1390 manifest: 0:a0c8bcbbb45c
1393 manifest: 0:a0c8bcbbb45c
1391 manifest--verbose: 6:94961b75a2da
1394 manifest--verbose: 6:94961b75a2da
1392 manifest--verbose: 5:f2dbc354b94e
1395 manifest--verbose: 5:f2dbc354b94e
1393 manifest--verbose: 4:4dc3def4f9b4
1396 manifest--verbose: 4:4dc3def4f9b4
1394 manifest--verbose: 4:4dc3def4f9b4
1397 manifest--verbose: 4:4dc3def4f9b4
1395 manifest--verbose: 3:cb5a1327723b
1398 manifest--verbose: 3:cb5a1327723b
1396 manifest--verbose: 3:cb5a1327723b
1399 manifest--verbose: 3:cb5a1327723b
1397 manifest--verbose: 2:6e0e82995c35
1400 manifest--verbose: 2:6e0e82995c35
1398 manifest--verbose: 1:4e8d705b1e53
1401 manifest--verbose: 1:4e8d705b1e53
1399 manifest--verbose: 0:a0c8bcbbb45c
1402 manifest--verbose: 0:a0c8bcbbb45c
1400 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1403 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1401 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1404 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1402 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1405 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1403 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1406 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1404 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1407 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1405 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1408 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1406 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1409 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1407 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1410 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1408 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1411 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1409 node: 95c24699272ef57d062b8bccc32c878bf841784a
1412 node: 95c24699272ef57d062b8bccc32c878bf841784a
1410 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1413 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1411 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1414 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1412 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1415 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1413 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1416 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1414 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1417 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1415 node: 97054abb4ab824450e9164180baf491ae0078465
1418 node: 97054abb4ab824450e9164180baf491ae0078465
1416 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1419 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1417 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1420 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1418 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1421 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1419 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1422 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1420 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1423 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1421 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1424 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1422 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1425 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1423 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1426 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1424 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1427 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1425 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1428 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1426 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1429 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1427 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1430 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1428 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1431 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1429 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1432 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1430 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1433 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1431 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1434 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1432 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1435 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1433 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1436 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1434 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1437 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1435 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1438 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1436 parents:
1439 parents:
1437 parents: -1:000000000000
1440 parents: -1:000000000000
1438 parents: 5:13207e5a10d9 4:bbe44766e73d
1441 parents: 5:13207e5a10d9 4:bbe44766e73d
1439 parents: 3:10e46f2dcbf4
1442 parents: 3:10e46f2dcbf4
1440 parents:
1443 parents:
1441 parents:
1444 parents:
1442 parents:
1445 parents:
1443 parents:
1446 parents:
1444 parents:
1447 parents:
1445 parents--verbose:
1448 parents--verbose:
1446 parents--verbose: -1:000000000000
1449 parents--verbose: -1:000000000000
1447 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1450 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1448 parents--verbose: 3:10e46f2dcbf4
1451 parents--verbose: 3:10e46f2dcbf4
1449 parents--verbose:
1452 parents--verbose:
1450 parents--verbose:
1453 parents--verbose:
1451 parents--verbose:
1454 parents--verbose:
1452 parents--verbose:
1455 parents--verbose:
1453 parents--verbose:
1456 parents--verbose:
1454 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1457 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1455 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1458 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1456 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1459 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1457 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1460 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1458 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1461 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1459 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1462 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1460 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1463 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1461 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1464 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1462 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1465 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1463 rev: 8
1466 rev: 8
1464 rev: 7
1467 rev: 7
1465 rev: 6
1468 rev: 6
1466 rev: 5
1469 rev: 5
1467 rev: 4
1470 rev: 4
1468 rev: 3
1471 rev: 3
1469 rev: 2
1472 rev: 2
1470 rev: 1
1473 rev: 1
1471 rev: 0
1474 rev: 0
1472 rev--verbose: 8
1475 rev--verbose: 8
1473 rev--verbose: 7
1476 rev--verbose: 7
1474 rev--verbose: 6
1477 rev--verbose: 6
1475 rev--verbose: 5
1478 rev--verbose: 5
1476 rev--verbose: 4
1479 rev--verbose: 4
1477 rev--verbose: 3
1480 rev--verbose: 3
1478 rev--verbose: 2
1481 rev--verbose: 2
1479 rev--verbose: 1
1482 rev--verbose: 1
1480 rev--verbose: 0
1483 rev--verbose: 0
1481 rev--debug: 8
1484 rev--debug: 8
1482 rev--debug: 7
1485 rev--debug: 7
1483 rev--debug: 6
1486 rev--debug: 6
1484 rev--debug: 5
1487 rev--debug: 5
1485 rev--debug: 4
1488 rev--debug: 4
1486 rev--debug: 3
1489 rev--debug: 3
1487 rev--debug: 2
1490 rev--debug: 2
1488 rev--debug: 1
1491 rev--debug: 1
1489 rev--debug: 0
1492 rev--debug: 0
1490 tags: tip
1493 tags: tip
1491 tags:
1494 tags:
1492 tags:
1495 tags:
1493 tags:
1496 tags:
1494 tags:
1497 tags:
1495 tags:
1498 tags:
1496 tags:
1499 tags:
1497 tags:
1500 tags:
1498 tags:
1501 tags:
1499 tags--verbose: tip
1502 tags--verbose: tip
1500 tags--verbose:
1503 tags--verbose:
1501 tags--verbose:
1504 tags--verbose:
1502 tags--verbose:
1505 tags--verbose:
1503 tags--verbose:
1506 tags--verbose:
1504 tags--verbose:
1507 tags--verbose:
1505 tags--verbose:
1508 tags--verbose:
1506 tags--verbose:
1509 tags--verbose:
1507 tags--verbose:
1510 tags--verbose:
1508 tags--debug: tip
1511 tags--debug: tip
1509 tags--debug:
1512 tags--debug:
1510 tags--debug:
1513 tags--debug:
1511 tags--debug:
1514 tags--debug:
1512 tags--debug:
1515 tags--debug:
1513 tags--debug:
1516 tags--debug:
1514 tags--debug:
1517 tags--debug:
1515 tags--debug:
1518 tags--debug:
1516 tags--debug:
1519 tags--debug:
1517 diffstat: 3: +2/-1
1520 diffstat: 3: +2/-1
1518 diffstat: 1: +1/-0
1521 diffstat: 1: +1/-0
1519 diffstat: 0: +0/-0
1522 diffstat: 0: +0/-0
1520 diffstat: 1: +1/-0
1523 diffstat: 1: +1/-0
1521 diffstat: 0: +0/-0
1524 diffstat: 0: +0/-0
1522 diffstat: 1: +1/-0
1525 diffstat: 1: +1/-0
1523 diffstat: 1: +4/-0
1526 diffstat: 1: +4/-0
1524 diffstat: 1: +2/-0
1527 diffstat: 1: +2/-0
1525 diffstat: 1: +1/-0
1528 diffstat: 1: +1/-0
1526 diffstat--verbose: 3: +2/-1
1529 diffstat--verbose: 3: +2/-1
1527 diffstat--verbose: 1: +1/-0
1530 diffstat--verbose: 1: +1/-0
1528 diffstat--verbose: 0: +0/-0
1531 diffstat--verbose: 0: +0/-0
1529 diffstat--verbose: 1: +1/-0
1532 diffstat--verbose: 1: +1/-0
1530 diffstat--verbose: 0: +0/-0
1533 diffstat--verbose: 0: +0/-0
1531 diffstat--verbose: 1: +1/-0
1534 diffstat--verbose: 1: +1/-0
1532 diffstat--verbose: 1: +4/-0
1535 diffstat--verbose: 1: +4/-0
1533 diffstat--verbose: 1: +2/-0
1536 diffstat--verbose: 1: +2/-0
1534 diffstat--verbose: 1: +1/-0
1537 diffstat--verbose: 1: +1/-0
1535 diffstat--debug: 3: +2/-1
1538 diffstat--debug: 3: +2/-1
1536 diffstat--debug: 1: +1/-0
1539 diffstat--debug: 1: +1/-0
1537 diffstat--debug: 0: +0/-0
1540 diffstat--debug: 0: +0/-0
1538 diffstat--debug: 1: +1/-0
1541 diffstat--debug: 1: +1/-0
1539 diffstat--debug: 0: +0/-0
1542 diffstat--debug: 0: +0/-0
1540 diffstat--debug: 1: +1/-0
1543 diffstat--debug: 1: +1/-0
1541 diffstat--debug: 1: +4/-0
1544 diffstat--debug: 1: +4/-0
1542 diffstat--debug: 1: +2/-0
1545 diffstat--debug: 1: +2/-0
1543 diffstat--debug: 1: +1/-0
1546 diffstat--debug: 1: +1/-0
1544 extras: branch=default
1547 extras: branch=default
1545 extras: branch=default
1548 extras: branch=default
1546 extras: branch=default
1549 extras: branch=default
1547 extras: branch=default
1550 extras: branch=default
1548 extras: branch=foo
1551 extras: branch=foo
1549 extras: branch=default
1552 extras: branch=default
1550 extras: branch=default
1553 extras: branch=default
1551 extras: branch=default
1554 extras: branch=default
1552 extras: branch=default
1555 extras: branch=default
1553 extras--verbose: branch=default
1556 extras--verbose: branch=default
1554 extras--verbose: branch=default
1557 extras--verbose: branch=default
1555 extras--verbose: branch=default
1558 extras--verbose: branch=default
1556 extras--verbose: branch=default
1559 extras--verbose: branch=default
1557 extras--verbose: branch=foo
1560 extras--verbose: branch=foo
1558 extras--verbose: branch=default
1561 extras--verbose: branch=default
1559 extras--verbose: branch=default
1562 extras--verbose: branch=default
1560 extras--verbose: branch=default
1563 extras--verbose: branch=default
1561 extras--verbose: branch=default
1564 extras--verbose: branch=default
1562 extras--debug: branch=default
1565 extras--debug: branch=default
1563 extras--debug: branch=default
1566 extras--debug: branch=default
1564 extras--debug: branch=default
1567 extras--debug: branch=default
1565 extras--debug: branch=default
1568 extras--debug: branch=default
1566 extras--debug: branch=foo
1569 extras--debug: branch=foo
1567 extras--debug: branch=default
1570 extras--debug: branch=default
1568 extras--debug: branch=default
1571 extras--debug: branch=default
1569 extras--debug: branch=default
1572 extras--debug: branch=default
1570 extras--debug: branch=default
1573 extras--debug: branch=default
1571 p1rev: 7
1574 p1rev: 7
1572 p1rev: -1
1575 p1rev: -1
1573 p1rev: 5
1576 p1rev: 5
1574 p1rev: 3
1577 p1rev: 3
1575 p1rev: 3
1578 p1rev: 3
1576 p1rev: 2
1579 p1rev: 2
1577 p1rev: 1
1580 p1rev: 1
1578 p1rev: 0
1581 p1rev: 0
1579 p1rev: -1
1582 p1rev: -1
1580 p1rev--verbose: 7
1583 p1rev--verbose: 7
1581 p1rev--verbose: -1
1584 p1rev--verbose: -1
1582 p1rev--verbose: 5
1585 p1rev--verbose: 5
1583 p1rev--verbose: 3
1586 p1rev--verbose: 3
1584 p1rev--verbose: 3
1587 p1rev--verbose: 3
1585 p1rev--verbose: 2
1588 p1rev--verbose: 2
1586 p1rev--verbose: 1
1589 p1rev--verbose: 1
1587 p1rev--verbose: 0
1590 p1rev--verbose: 0
1588 p1rev--verbose: -1
1591 p1rev--verbose: -1
1589 p1rev--debug: 7
1592 p1rev--debug: 7
1590 p1rev--debug: -1
1593 p1rev--debug: -1
1591 p1rev--debug: 5
1594 p1rev--debug: 5
1592 p1rev--debug: 3
1595 p1rev--debug: 3
1593 p1rev--debug: 3
1596 p1rev--debug: 3
1594 p1rev--debug: 2
1597 p1rev--debug: 2
1595 p1rev--debug: 1
1598 p1rev--debug: 1
1596 p1rev--debug: 0
1599 p1rev--debug: 0
1597 p1rev--debug: -1
1600 p1rev--debug: -1
1598 p2rev: -1
1601 p2rev: -1
1599 p2rev: -1
1602 p2rev: -1
1600 p2rev: 4
1603 p2rev: 4
1601 p2rev: -1
1604 p2rev: -1
1602 p2rev: -1
1605 p2rev: -1
1603 p2rev: -1
1606 p2rev: -1
1604 p2rev: -1
1607 p2rev: -1
1605 p2rev: -1
1608 p2rev: -1
1606 p2rev: -1
1609 p2rev: -1
1607 p2rev--verbose: -1
1610 p2rev--verbose: -1
1608 p2rev--verbose: -1
1611 p2rev--verbose: -1
1609 p2rev--verbose: 4
1612 p2rev--verbose: 4
1610 p2rev--verbose: -1
1613 p2rev--verbose: -1
1611 p2rev--verbose: -1
1614 p2rev--verbose: -1
1612 p2rev--verbose: -1
1615 p2rev--verbose: -1
1613 p2rev--verbose: -1
1616 p2rev--verbose: -1
1614 p2rev--verbose: -1
1617 p2rev--verbose: -1
1615 p2rev--verbose: -1
1618 p2rev--verbose: -1
1616 p2rev--debug: -1
1619 p2rev--debug: -1
1617 p2rev--debug: -1
1620 p2rev--debug: -1
1618 p2rev--debug: 4
1621 p2rev--debug: 4
1619 p2rev--debug: -1
1622 p2rev--debug: -1
1620 p2rev--debug: -1
1623 p2rev--debug: -1
1621 p2rev--debug: -1
1624 p2rev--debug: -1
1622 p2rev--debug: -1
1625 p2rev--debug: -1
1623 p2rev--debug: -1
1626 p2rev--debug: -1
1624 p2rev--debug: -1
1627 p2rev--debug: -1
1625 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1628 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1626 p1node: 0000000000000000000000000000000000000000
1629 p1node: 0000000000000000000000000000000000000000
1627 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1630 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1628 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1631 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1629 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1632 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1630 p1node: 97054abb4ab824450e9164180baf491ae0078465
1633 p1node: 97054abb4ab824450e9164180baf491ae0078465
1631 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1634 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1632 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1635 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1633 p1node: 0000000000000000000000000000000000000000
1636 p1node: 0000000000000000000000000000000000000000
1634 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1637 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1635 p1node--verbose: 0000000000000000000000000000000000000000
1638 p1node--verbose: 0000000000000000000000000000000000000000
1636 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1639 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1637 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1640 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1638 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1641 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1639 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1642 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1640 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1643 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1641 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1644 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1642 p1node--verbose: 0000000000000000000000000000000000000000
1645 p1node--verbose: 0000000000000000000000000000000000000000
1643 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1646 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1644 p1node--debug: 0000000000000000000000000000000000000000
1647 p1node--debug: 0000000000000000000000000000000000000000
1645 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1648 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1646 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1649 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1647 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1650 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1648 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1651 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1649 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1652 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1650 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1653 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1651 p1node--debug: 0000000000000000000000000000000000000000
1654 p1node--debug: 0000000000000000000000000000000000000000
1652 p2node: 0000000000000000000000000000000000000000
1655 p2node: 0000000000000000000000000000000000000000
1653 p2node: 0000000000000000000000000000000000000000
1656 p2node: 0000000000000000000000000000000000000000
1654 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1657 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1655 p2node: 0000000000000000000000000000000000000000
1658 p2node: 0000000000000000000000000000000000000000
1656 p2node: 0000000000000000000000000000000000000000
1659 p2node: 0000000000000000000000000000000000000000
1657 p2node: 0000000000000000000000000000000000000000
1660 p2node: 0000000000000000000000000000000000000000
1658 p2node: 0000000000000000000000000000000000000000
1661 p2node: 0000000000000000000000000000000000000000
1659 p2node: 0000000000000000000000000000000000000000
1662 p2node: 0000000000000000000000000000000000000000
1660 p2node: 0000000000000000000000000000000000000000
1663 p2node: 0000000000000000000000000000000000000000
1661 p2node--verbose: 0000000000000000000000000000000000000000
1664 p2node--verbose: 0000000000000000000000000000000000000000
1662 p2node--verbose: 0000000000000000000000000000000000000000
1665 p2node--verbose: 0000000000000000000000000000000000000000
1663 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1666 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1664 p2node--verbose: 0000000000000000000000000000000000000000
1667 p2node--verbose: 0000000000000000000000000000000000000000
1665 p2node--verbose: 0000000000000000000000000000000000000000
1668 p2node--verbose: 0000000000000000000000000000000000000000
1666 p2node--verbose: 0000000000000000000000000000000000000000
1669 p2node--verbose: 0000000000000000000000000000000000000000
1667 p2node--verbose: 0000000000000000000000000000000000000000
1670 p2node--verbose: 0000000000000000000000000000000000000000
1668 p2node--verbose: 0000000000000000000000000000000000000000
1671 p2node--verbose: 0000000000000000000000000000000000000000
1669 p2node--verbose: 0000000000000000000000000000000000000000
1672 p2node--verbose: 0000000000000000000000000000000000000000
1670 p2node--debug: 0000000000000000000000000000000000000000
1673 p2node--debug: 0000000000000000000000000000000000000000
1671 p2node--debug: 0000000000000000000000000000000000000000
1674 p2node--debug: 0000000000000000000000000000000000000000
1672 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1675 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1673 p2node--debug: 0000000000000000000000000000000000000000
1676 p2node--debug: 0000000000000000000000000000000000000000
1674 p2node--debug: 0000000000000000000000000000000000000000
1677 p2node--debug: 0000000000000000000000000000000000000000
1675 p2node--debug: 0000000000000000000000000000000000000000
1678 p2node--debug: 0000000000000000000000000000000000000000
1676 p2node--debug: 0000000000000000000000000000000000000000
1679 p2node--debug: 0000000000000000000000000000000000000000
1677 p2node--debug: 0000000000000000000000000000000000000000
1680 p2node--debug: 0000000000000000000000000000000000000000
1678 p2node--debug: 0000000000000000000000000000000000000000
1681 p2node--debug: 0000000000000000000000000000000000000000
1679
1682
1680 Filters work:
1683 Filters work:
1681
1684
1682 $ hg log --template '{author|domain}\n'
1685 $ hg log --template '{author|domain}\n'
1683
1686
1684 hostname
1687 hostname
1685
1688
1686
1689
1687
1690
1688
1691
1689 place
1692 place
1690 place
1693 place
1691 hostname
1694 hostname
1692
1695
1693 $ hg log --template '{author|person}\n'
1696 $ hg log --template '{author|person}\n'
1694 test
1697 test
1695 User Name
1698 User Name
1696 person
1699 person
1697 person
1700 person
1698 person
1701 person
1699 person
1702 person
1700 other
1703 other
1701 A. N. Other
1704 A. N. Other
1702 User Name
1705 User Name
1703
1706
1704 $ hg log --template '{author|user}\n'
1707 $ hg log --template '{author|user}\n'
1705 test
1708 test
1706 user
1709 user
1707 person
1710 person
1708 person
1711 person
1709 person
1712 person
1710 person
1713 person
1711 other
1714 other
1712 other
1715 other
1713 user
1716 user
1714
1717
1715 $ hg log --template '{date|date}\n'
1718 $ hg log --template '{date|date}\n'
1716 Wed Jan 01 10:01:00 2020 +0000
1719 Wed Jan 01 10:01:00 2020 +0000
1717 Mon Jan 12 13:46:40 1970 +0000
1720 Mon Jan 12 13:46:40 1970 +0000
1718 Sun Jan 18 08:40:01 1970 +0000
1721 Sun Jan 18 08:40:01 1970 +0000
1719 Sun Jan 18 08:40:00 1970 +0000
1722 Sun Jan 18 08:40:00 1970 +0000
1720 Sat Jan 17 04:53:20 1970 +0000
1723 Sat Jan 17 04:53:20 1970 +0000
1721 Fri Jan 16 01:06:40 1970 +0000
1724 Fri Jan 16 01:06:40 1970 +0000
1722 Wed Jan 14 21:20:00 1970 +0000
1725 Wed Jan 14 21:20:00 1970 +0000
1723 Tue Jan 13 17:33:20 1970 +0000
1726 Tue Jan 13 17:33:20 1970 +0000
1724 Mon Jan 12 13:46:40 1970 +0000
1727 Mon Jan 12 13:46:40 1970 +0000
1725
1728
1726 $ hg log --template '{date|isodate}\n'
1729 $ hg log --template '{date|isodate}\n'
1727 2020-01-01 10:01 +0000
1730 2020-01-01 10:01 +0000
1728 1970-01-12 13:46 +0000
1731 1970-01-12 13:46 +0000
1729 1970-01-18 08:40 +0000
1732 1970-01-18 08:40 +0000
1730 1970-01-18 08:40 +0000
1733 1970-01-18 08:40 +0000
1731 1970-01-17 04:53 +0000
1734 1970-01-17 04:53 +0000
1732 1970-01-16 01:06 +0000
1735 1970-01-16 01:06 +0000
1733 1970-01-14 21:20 +0000
1736 1970-01-14 21:20 +0000
1734 1970-01-13 17:33 +0000
1737 1970-01-13 17:33 +0000
1735 1970-01-12 13:46 +0000
1738 1970-01-12 13:46 +0000
1736
1739
1737 $ hg log --template '{date|isodatesec}\n'
1740 $ hg log --template '{date|isodatesec}\n'
1738 2020-01-01 10:01:00 +0000
1741 2020-01-01 10:01:00 +0000
1739 1970-01-12 13:46:40 +0000
1742 1970-01-12 13:46:40 +0000
1740 1970-01-18 08:40:01 +0000
1743 1970-01-18 08:40:01 +0000
1741 1970-01-18 08:40:00 +0000
1744 1970-01-18 08:40:00 +0000
1742 1970-01-17 04:53:20 +0000
1745 1970-01-17 04:53:20 +0000
1743 1970-01-16 01:06:40 +0000
1746 1970-01-16 01:06:40 +0000
1744 1970-01-14 21:20:00 +0000
1747 1970-01-14 21:20:00 +0000
1745 1970-01-13 17:33:20 +0000
1748 1970-01-13 17:33:20 +0000
1746 1970-01-12 13:46:40 +0000
1749 1970-01-12 13:46:40 +0000
1747
1750
1748 $ hg log --template '{date|rfc822date}\n'
1751 $ hg log --template '{date|rfc822date}\n'
1749 Wed, 01 Jan 2020 10:01:00 +0000
1752 Wed, 01 Jan 2020 10:01:00 +0000
1750 Mon, 12 Jan 1970 13:46:40 +0000
1753 Mon, 12 Jan 1970 13:46:40 +0000
1751 Sun, 18 Jan 1970 08:40:01 +0000
1754 Sun, 18 Jan 1970 08:40:01 +0000
1752 Sun, 18 Jan 1970 08:40:00 +0000
1755 Sun, 18 Jan 1970 08:40:00 +0000
1753 Sat, 17 Jan 1970 04:53:20 +0000
1756 Sat, 17 Jan 1970 04:53:20 +0000
1754 Fri, 16 Jan 1970 01:06:40 +0000
1757 Fri, 16 Jan 1970 01:06:40 +0000
1755 Wed, 14 Jan 1970 21:20:00 +0000
1758 Wed, 14 Jan 1970 21:20:00 +0000
1756 Tue, 13 Jan 1970 17:33:20 +0000
1759 Tue, 13 Jan 1970 17:33:20 +0000
1757 Mon, 12 Jan 1970 13:46:40 +0000
1760 Mon, 12 Jan 1970 13:46:40 +0000
1758
1761
1759 $ hg log --template '{desc|firstline}\n'
1762 $ hg log --template '{desc|firstline}\n'
1760 third
1763 third
1761 second
1764 second
1762 merge
1765 merge
1763 new head
1766 new head
1764 new branch
1767 new branch
1765 no user, no domain
1768 no user, no domain
1766 no person
1769 no person
1767 other 1
1770 other 1
1768 line 1
1771 line 1
1769
1772
1770 $ hg log --template '{node|short}\n'
1773 $ hg log --template '{node|short}\n'
1771 95c24699272e
1774 95c24699272e
1772 29114dbae42b
1775 29114dbae42b
1773 d41e714fe50d
1776 d41e714fe50d
1774 13207e5a10d9
1777 13207e5a10d9
1775 bbe44766e73d
1778 bbe44766e73d
1776 10e46f2dcbf4
1779 10e46f2dcbf4
1777 97054abb4ab8
1780 97054abb4ab8
1778 b608e9d1a3f0
1781 b608e9d1a3f0
1779 1e4e1b8f71e0
1782 1e4e1b8f71e0
1780
1783
1781 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1784 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1782 <changeset author="test"/>
1785 <changeset author="test"/>
1783 <changeset author="User Name &lt;user@hostname&gt;"/>
1786 <changeset author="User Name &lt;user@hostname&gt;"/>
1784 <changeset author="person"/>
1787 <changeset author="person"/>
1785 <changeset author="person"/>
1788 <changeset author="person"/>
1786 <changeset author="person"/>
1789 <changeset author="person"/>
1787 <changeset author="person"/>
1790 <changeset author="person"/>
1788 <changeset author="other@place"/>
1791 <changeset author="other@place"/>
1789 <changeset author="A. N. Other &lt;other@place&gt;"/>
1792 <changeset author="A. N. Other &lt;other@place&gt;"/>
1790 <changeset author="User Name &lt;user@hostname&gt;"/>
1793 <changeset author="User Name &lt;user@hostname&gt;"/>
1791
1794
1792 $ hg log --template '{rev}: {children}\n'
1795 $ hg log --template '{rev}: {children}\n'
1793 8:
1796 8:
1794 7: 8:95c24699272e
1797 7: 8:95c24699272e
1795 6:
1798 6:
1796 5: 6:d41e714fe50d
1799 5: 6:d41e714fe50d
1797 4: 6:d41e714fe50d
1800 4: 6:d41e714fe50d
1798 3: 4:bbe44766e73d 5:13207e5a10d9
1801 3: 4:bbe44766e73d 5:13207e5a10d9
1799 2: 3:10e46f2dcbf4
1802 2: 3:10e46f2dcbf4
1800 1: 2:97054abb4ab8
1803 1: 2:97054abb4ab8
1801 0: 1:b608e9d1a3f0
1804 0: 1:b608e9d1a3f0
1802
1805
1803 Formatnode filter works:
1806 Formatnode filter works:
1804
1807
1805 $ hg -q log -r 0 --template '{node|formatnode}\n'
1808 $ hg -q log -r 0 --template '{node|formatnode}\n'
1806 1e4e1b8f71e0
1809 1e4e1b8f71e0
1807
1810
1808 $ hg log -r 0 --template '{node|formatnode}\n'
1811 $ hg log -r 0 --template '{node|formatnode}\n'
1809 1e4e1b8f71e0
1812 1e4e1b8f71e0
1810
1813
1811 $ hg -v log -r 0 --template '{node|formatnode}\n'
1814 $ hg -v log -r 0 --template '{node|formatnode}\n'
1812 1e4e1b8f71e0
1815 1e4e1b8f71e0
1813
1816
1814 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1817 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1815 1e4e1b8f71e05681d422154f5421e385fec3454f
1818 1e4e1b8f71e05681d422154f5421e385fec3454f
1816
1819
1817 Age filter:
1820 Age filter:
1818
1821
1819 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1822 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1820
1823
1821 >>> from datetime import datetime, timedelta
1824 >>> from datetime import datetime, timedelta
1822 >>> fp = open('a', 'w')
1825 >>> fp = open('a', 'w')
1823 >>> n = datetime.now() + timedelta(366 * 7)
1826 >>> n = datetime.now() + timedelta(366 * 7)
1824 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1827 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1825 >>> fp.close()
1828 >>> fp.close()
1826 $ hg add a
1829 $ hg add a
1827 $ hg commit -m future -d "`cat a`"
1830 $ hg commit -m future -d "`cat a`"
1828
1831
1829 $ hg log -l1 --template '{date|age}\n'
1832 $ hg log -l1 --template '{date|age}\n'
1830 7 years from now
1833 7 years from now
1831
1834
1832 Count filter:
1835 Count filter:
1833
1836
1834 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1837 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1835 40 12
1838 40 12
1836
1839
1837 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1840 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1838 0 1 4
1841 0 1 4
1839
1842
1840 $ hg log -G --template '{rev}: children: {children|count}, \
1843 $ hg log -G --template '{rev}: children: {children|count}, \
1841 > tags: {tags|count}, file_adds: {file_adds|count}, \
1844 > tags: {tags|count}, file_adds: {file_adds|count}, \
1842 > ancestors: {revset("ancestors(%s)", rev)|count}'
1845 > ancestors: {revset("ancestors(%s)", rev)|count}'
1843 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1846 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1844 |
1847 |
1845 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1848 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1846 |
1849 |
1847 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1850 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1848
1851
1849 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1852 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1850 |\
1853 |\
1851 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1854 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1852 | |
1855 | |
1853 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1856 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1854 |/
1857 |/
1855 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1858 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1856 |
1859 |
1857 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1860 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1858 |
1861 |
1859 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1862 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1860 |
1863 |
1861 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1864 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1862
1865
1863
1866
1864 Error on syntax:
1867 Error on syntax:
1865
1868
1866 $ echo 'x = "f' >> t
1869 $ echo 'x = "f' >> t
1867 $ hg log
1870 $ hg log
1868 abort: t:3: unmatched quotes
1871 abort: t:3: unmatched quotes
1869 [255]
1872 [255]
1870
1873
1871 Behind the scenes, this will throw TypeError
1874 Behind the scenes, this will throw TypeError
1872
1875
1873 $ hg log -l 3 --template '{date|obfuscate}\n'
1876 $ hg log -l 3 --template '{date|obfuscate}\n'
1874 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1877 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1875 [255]
1878 [255]
1876
1879
1877 Behind the scenes, this will throw a ValueError
1880 Behind the scenes, this will throw a ValueError
1878
1881
1879 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1882 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1880 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1883 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1881 [255]
1884 [255]
1882
1885
1883 Behind the scenes, this will throw AttributeError
1886 Behind the scenes, this will throw AttributeError
1884
1887
1885 $ hg log -l 3 --template 'line: {date|escape}\n'
1888 $ hg log -l 3 --template 'line: {date|escape}\n'
1886 abort: template filter 'escape' is not compatible with keyword 'date'
1889 abort: template filter 'escape' is not compatible with keyword 'date'
1887 [255]
1890 [255]
1888
1891
1889 Behind the scenes, this will throw ValueError
1892 Behind the scenes, this will throw ValueError
1890
1893
1891 $ hg tip --template '{author|email|date}\n'
1894 $ hg tip --template '{author|email|date}\n'
1892 abort: template filter 'datefilter' is not compatible with keyword 'author'
1895 abort: template filter 'datefilter' is not compatible with keyword 'author'
1893 [255]
1896 [255]
1894
1897
1895 Thrown an error if a template function doesn't exist
1898 Thrown an error if a template function doesn't exist
1896
1899
1897 $ hg tip --template '{foo()}\n'
1900 $ hg tip --template '{foo()}\n'
1898 hg: parse error: unknown function 'foo'
1901 hg: parse error: unknown function 'foo'
1899 [255]
1902 [255]
1900
1903
1901 Test diff function:
1904 Test diff function:
1902
1905
1903 $ hg diff -c 8
1906 $ hg diff -c 8
1904 diff -r 29114dbae42b -r 95c24699272e fourth
1907 diff -r 29114dbae42b -r 95c24699272e fourth
1905 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1908 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1906 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1909 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1907 @@ -0,0 +1,1 @@
1910 @@ -0,0 +1,1 @@
1908 +second
1911 +second
1909 diff -r 29114dbae42b -r 95c24699272e second
1912 diff -r 29114dbae42b -r 95c24699272e second
1910 --- a/second Mon Jan 12 13:46:40 1970 +0000
1913 --- a/second Mon Jan 12 13:46:40 1970 +0000
1911 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1914 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1912 @@ -1,1 +0,0 @@
1915 @@ -1,1 +0,0 @@
1913 -second
1916 -second
1914 diff -r 29114dbae42b -r 95c24699272e third
1917 diff -r 29114dbae42b -r 95c24699272e third
1915 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1918 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1916 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1919 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1917 @@ -0,0 +1,1 @@
1920 @@ -0,0 +1,1 @@
1918 +third
1921 +third
1919
1922
1920 $ hg log -r 8 -T "{diff()}"
1923 $ hg log -r 8 -T "{diff()}"
1921 diff -r 29114dbae42b -r 95c24699272e fourth
1924 diff -r 29114dbae42b -r 95c24699272e fourth
1922 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1925 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1923 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1926 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1924 @@ -0,0 +1,1 @@
1927 @@ -0,0 +1,1 @@
1925 +second
1928 +second
1926 diff -r 29114dbae42b -r 95c24699272e second
1929 diff -r 29114dbae42b -r 95c24699272e second
1927 --- a/second Mon Jan 12 13:46:40 1970 +0000
1930 --- a/second Mon Jan 12 13:46:40 1970 +0000
1928 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1931 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1929 @@ -1,1 +0,0 @@
1932 @@ -1,1 +0,0 @@
1930 -second
1933 -second
1931 diff -r 29114dbae42b -r 95c24699272e third
1934 diff -r 29114dbae42b -r 95c24699272e third
1932 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1935 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1933 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1936 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1934 @@ -0,0 +1,1 @@
1937 @@ -0,0 +1,1 @@
1935 +third
1938 +third
1936
1939
1937 $ hg log -r 8 -T "{diff('glob:f*')}"
1940 $ hg log -r 8 -T "{diff('glob:f*')}"
1938 diff -r 29114dbae42b -r 95c24699272e fourth
1941 diff -r 29114dbae42b -r 95c24699272e fourth
1939 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1942 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1940 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1943 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
1941 @@ -0,0 +1,1 @@
1944 @@ -0,0 +1,1 @@
1942 +second
1945 +second
1943
1946
1944 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
1947 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
1945 diff -r 29114dbae42b -r 95c24699272e second
1948 diff -r 29114dbae42b -r 95c24699272e second
1946 --- a/second Mon Jan 12 13:46:40 1970 +0000
1949 --- a/second Mon Jan 12 13:46:40 1970 +0000
1947 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1950 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1948 @@ -1,1 +0,0 @@
1951 @@ -1,1 +0,0 @@
1949 -second
1952 -second
1950 diff -r 29114dbae42b -r 95c24699272e third
1953 diff -r 29114dbae42b -r 95c24699272e third
1951 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1954 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1952 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1955 +++ b/third Wed Jan 01 10:01:00 2020 +0000
1953 @@ -0,0 +1,1 @@
1956 @@ -0,0 +1,1 @@
1954 +third
1957 +third
1955
1958
1956 $ cd ..
1959 $ cd ..
1957
1960
1958
1961
1959 latesttag:
1962 latesttag:
1960
1963
1961 $ hg init latesttag
1964 $ hg init latesttag
1962 $ cd latesttag
1965 $ cd latesttag
1963
1966
1964 $ echo a > file
1967 $ echo a > file
1965 $ hg ci -Am a -d '0 0'
1968 $ hg ci -Am a -d '0 0'
1966 adding file
1969 adding file
1967
1970
1968 $ echo b >> file
1971 $ echo b >> file
1969 $ hg ci -m b -d '1 0'
1972 $ hg ci -m b -d '1 0'
1970
1973
1971 $ echo c >> head1
1974 $ echo c >> head1
1972 $ hg ci -Am h1c -d '2 0'
1975 $ hg ci -Am h1c -d '2 0'
1973 adding head1
1976 adding head1
1974
1977
1975 $ hg update -q 1
1978 $ hg update -q 1
1976 $ echo d >> head2
1979 $ echo d >> head2
1977 $ hg ci -Am h2d -d '3 0'
1980 $ hg ci -Am h2d -d '3 0'
1978 adding head2
1981 adding head2
1979 created new head
1982 created new head
1980
1983
1981 $ echo e >> head2
1984 $ echo e >> head2
1982 $ hg ci -m h2e -d '4 0'
1985 $ hg ci -m h2e -d '4 0'
1983
1986
1984 $ hg merge -q
1987 $ hg merge -q
1985 $ hg ci -m merge -d '5 -3600'
1988 $ hg ci -m merge -d '5 -3600'
1986
1989
1987 No tag set:
1990 No tag set:
1988
1991
1989 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1992 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1990 5: null+5
1993 5: null+5
1991 4: null+4
1994 4: null+4
1992 3: null+3
1995 3: null+3
1993 2: null+3
1996 2: null+3
1994 1: null+2
1997 1: null+2
1995 0: null+1
1998 0: null+1
1996
1999
1997 One common tag: longest path wins:
2000 One common tag: longest path wins:
1998
2001
1999 $ hg tag -r 1 -m t1 -d '6 0' t1
2002 $ hg tag -r 1 -m t1 -d '6 0' t1
2000 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2003 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2001 6: t1+4
2004 6: t1+4
2002 5: t1+3
2005 5: t1+3
2003 4: t1+2
2006 4: t1+2
2004 3: t1+1
2007 3: t1+1
2005 2: t1+1
2008 2: t1+1
2006 1: t1+0
2009 1: t1+0
2007 0: null+1
2010 0: null+1
2008
2011
2009 One ancestor tag: more recent wins:
2012 One ancestor tag: more recent wins:
2010
2013
2011 $ hg tag -r 2 -m t2 -d '7 0' t2
2014 $ hg tag -r 2 -m t2 -d '7 0' t2
2012 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2015 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2013 7: t2+3
2016 7: t2+3
2014 6: t2+2
2017 6: t2+2
2015 5: t2+1
2018 5: t2+1
2016 4: t1+2
2019 4: t1+2
2017 3: t1+1
2020 3: t1+1
2018 2: t2+0
2021 2: t2+0
2019 1: t1+0
2022 1: t1+0
2020 0: null+1
2023 0: null+1
2021
2024
2022 Two branch tags: more recent wins:
2025 Two branch tags: more recent wins:
2023
2026
2024 $ hg tag -r 3 -m t3 -d '8 0' t3
2027 $ hg tag -r 3 -m t3 -d '8 0' t3
2025 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2028 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2026 8: t3+5
2029 8: t3+5
2027 7: t3+4
2030 7: t3+4
2028 6: t3+3
2031 6: t3+3
2029 5: t3+2
2032 5: t3+2
2030 4: t3+1
2033 4: t3+1
2031 3: t3+0
2034 3: t3+0
2032 2: t2+0
2035 2: t2+0
2033 1: t1+0
2036 1: t1+0
2034 0: null+1
2037 0: null+1
2035
2038
2036 Merged tag overrides:
2039 Merged tag overrides:
2037
2040
2038 $ hg tag -r 5 -m t5 -d '9 0' t5
2041 $ hg tag -r 5 -m t5 -d '9 0' t5
2039 $ hg tag -r 3 -m at3 -d '10 0' at3
2042 $ hg tag -r 3 -m at3 -d '10 0' at3
2040 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2043 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2041 10: t5+5
2044 10: t5+5
2042 9: t5+4
2045 9: t5+4
2043 8: t5+3
2046 8: t5+3
2044 7: t5+2
2047 7: t5+2
2045 6: t5+1
2048 6: t5+1
2046 5: t5+0
2049 5: t5+0
2047 4: at3:t3+1
2050 4: at3:t3+1
2048 3: at3:t3+0
2051 3: at3:t3+0
2049 2: t2+0
2052 2: t2+0
2050 1: t1+0
2053 1: t1+0
2051 0: null+1
2054 0: null+1
2052
2055
2053 $ cd ..
2056 $ cd ..
2054
2057
2055
2058
2056 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2059 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2057 if it is a relative path
2060 if it is a relative path
2058
2061
2059 $ mkdir -p home/styles
2062 $ mkdir -p home/styles
2060
2063
2061 $ cat > home/styles/teststyle <<EOF
2064 $ cat > home/styles/teststyle <<EOF
2062 > changeset = 'test {rev}:{node|short}\n'
2065 > changeset = 'test {rev}:{node|short}\n'
2063 > EOF
2066 > EOF
2064
2067
2065 $ HOME=`pwd`/home; export HOME
2068 $ HOME=`pwd`/home; export HOME
2066
2069
2067 $ cat > latesttag/.hg/hgrc <<EOF
2070 $ cat > latesttag/.hg/hgrc <<EOF
2068 > [ui]
2071 > [ui]
2069 > style = ~/styles/teststyle
2072 > style = ~/styles/teststyle
2070 > EOF
2073 > EOF
2071
2074
2072 $ hg -R latesttag tip
2075 $ hg -R latesttag tip
2073 test 10:9b4a630e5f5f
2076 test 10:9b4a630e5f5f
2074
2077
2075 Test recursive showlist template (issue1989):
2078 Test recursive showlist template (issue1989):
2076
2079
2077 $ cat > style1989 <<EOF
2080 $ cat > style1989 <<EOF
2078 > changeset = '{file_mods}{manifest}{extras}'
2081 > changeset = '{file_mods}{manifest}{extras}'
2079 > file_mod = 'M|{author|person}\n'
2082 > file_mod = 'M|{author|person}\n'
2080 > manifest = '{rev},{author}\n'
2083 > manifest = '{rev},{author}\n'
2081 > extra = '{key}: {author}\n'
2084 > extra = '{key}: {author}\n'
2082 > EOF
2085 > EOF
2083
2086
2084 $ hg -R latesttag log -r tip --style=style1989
2087 $ hg -R latesttag log -r tip --style=style1989
2085 M|test
2088 M|test
2086 10,test
2089 10,test
2087 branch: test
2090 branch: test
2088
2091
2089 Test new-style inline templating:
2092 Test new-style inline templating:
2090
2093
2091 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2094 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2092 modified files: .hgtags
2095 modified files: .hgtags
2093
2096
2094 Test the sub function of templating for expansion:
2097 Test the sub function of templating for expansion:
2095
2098
2096 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2099 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2097 xx
2100 xx
2098
2101
2099 Test the strip function with chars specified:
2102 Test the strip function with chars specified:
2100
2103
2101 $ hg log -R latesttag --template '{desc}\n'
2104 $ hg log -R latesttag --template '{desc}\n'
2102 at3
2105 at3
2103 t5
2106 t5
2104 t3
2107 t3
2105 t2
2108 t2
2106 t1
2109 t1
2107 merge
2110 merge
2108 h2e
2111 h2e
2109 h2d
2112 h2d
2110 h1c
2113 h1c
2111 b
2114 b
2112 a
2115 a
2113
2116
2114 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2117 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2115 at3
2118 at3
2116 5
2119 5
2117 3
2120 3
2118 2
2121 2
2119 1
2122 1
2120 merg
2123 merg
2121 h2
2124 h2
2122 h2d
2125 h2d
2123 h1c
2126 h1c
2124 b
2127 b
2125 a
2128 a
2126
2129
2127 Test date format:
2130 Test date format:
2128
2131
2129 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2132 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2130 date: 70 01 01 10 +0000
2133 date: 70 01 01 10 +0000
2131 date: 70 01 01 09 +0000
2134 date: 70 01 01 09 +0000
2132 date: 70 01 01 08 +0000
2135 date: 70 01 01 08 +0000
2133 date: 70 01 01 07 +0000
2136 date: 70 01 01 07 +0000
2134 date: 70 01 01 06 +0000
2137 date: 70 01 01 06 +0000
2135 date: 70 01 01 05 +0100
2138 date: 70 01 01 05 +0100
2136 date: 70 01 01 04 +0000
2139 date: 70 01 01 04 +0000
2137 date: 70 01 01 03 +0000
2140 date: 70 01 01 03 +0000
2138 date: 70 01 01 02 +0000
2141 date: 70 01 01 02 +0000
2139 date: 70 01 01 01 +0000
2142 date: 70 01 01 01 +0000
2140 date: 70 01 01 00 +0000
2143 date: 70 01 01 00 +0000
2141
2144
2142 Test string escaping:
2145 Test string escaping:
2143
2146
2144 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2147 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2145 >
2148 >
2146 <>\n<[>
2149 <>\n<[>
2147 <>\n<]>
2150 <>\n<]>
2148 <>\n<
2151 <>\n<
2149
2152
2150 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2153 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2151
2154
2152 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2155 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2153 \x6e
2156 \x6e
2154 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2157 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2155 \x5c\x786e
2158 \x5c\x786e
2156 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2159 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2157 \x6e
2160 \x6e
2158 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2161 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2159 \x5c\x786e
2162 \x5c\x786e
2160
2163
2161 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2164 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2162 \x6e
2165 \x6e
2163 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2166 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2164 \x5c\x786e
2167 \x5c\x786e
2165 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2168 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2166 \x6e
2169 \x6e
2167 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2170 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2168 \x5c\x786e
2171 \x5c\x786e
2169
2172
2170 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2173 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2171 fourth
2174 fourth
2172 second
2175 second
2173 third
2176 third
2174 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2177 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2175 fourth\nsecond\nthird
2178 fourth\nsecond\nthird
2176
2179
2177 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2180 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2178 <p>
2181 <p>
2179 1st
2182 1st
2180 </p>
2183 </p>
2181 <p>
2184 <p>
2182 2nd
2185 2nd
2183 </p>
2186 </p>
2184 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2187 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2185 <p>
2188 <p>
2186 1st\n\n2nd
2189 1st\n\n2nd
2187 </p>
2190 </p>
2188 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2191 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2189 1st
2192 1st
2190
2193
2191 2nd
2194 2nd
2192
2195
2193 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2196 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2194 o perso
2197 o perso
2195 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2198 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2196 no person
2199 no person
2197 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2200 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2198 o perso
2201 o perso
2199 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2202 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2200 no perso
2203 no perso
2201
2204
2202 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2205 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2203 -o perso-
2206 -o perso-
2204 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2207 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2205 no person
2208 no person
2206 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2209 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2207 \x2do perso\x2d
2210 \x2do perso\x2d
2208 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2211 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2209 -o perso-
2212 -o perso-
2210 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2213 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2211 \x2do perso\x6e
2214 \x2do perso\x6e
2212
2215
2213 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2216 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2214 fourth
2217 fourth
2215 second
2218 second
2216 third
2219 third
2217 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2220 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2218 fourth\nsecond\nthird\n
2221 fourth\nsecond\nthird\n
2219
2222
2220 Test string escaping in nested expression:
2223 Test string escaping in nested expression:
2221
2224
2222 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2225 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2223 fourth\x6esecond\x6ethird
2226 fourth\x6esecond\x6ethird
2224 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2227 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2225 fourth\x6esecond\x6ethird
2228 fourth\x6esecond\x6ethird
2226
2229
2227 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2230 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2228 fourth\x6esecond\x6ethird
2231 fourth\x6esecond\x6ethird
2229 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2232 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2230 fourth\x5c\x786esecond\x5c\x786ethird
2233 fourth\x5c\x786esecond\x5c\x786ethird
2231
2234
2232 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2235 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2233 3:\x6eo user, \x6eo domai\x6e
2236 3:\x6eo user, \x6eo domai\x6e
2234 4:\x5c\x786eew bra\x5c\x786ech
2237 4:\x5c\x786eew bra\x5c\x786ech
2235
2238
2236 Test recursive evaluation:
2239 Test recursive evaluation:
2237
2240
2238 $ hg init r
2241 $ hg init r
2239 $ cd r
2242 $ cd r
2240 $ echo a > a
2243 $ echo a > a
2241 $ hg ci -Am '{rev}'
2244 $ hg ci -Am '{rev}'
2242 adding a
2245 adding a
2243 $ hg log -r 0 --template '{if(rev, desc)}\n'
2246 $ hg log -r 0 --template '{if(rev, desc)}\n'
2244 {rev}
2247 {rev}
2245 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2248 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2246 test 0
2249 test 0
2247
2250
2248 $ hg branch -q 'text.{rev}'
2251 $ hg branch -q 'text.{rev}'
2249 $ echo aa >> aa
2252 $ echo aa >> aa
2250 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2253 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2251
2254
2252 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2255 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2253 {node|short}desc to
2256 {node|short}desc to
2254 text.{rev}be wrapped
2257 text.{rev}be wrapped
2255 text.{rev}desc to be
2258 text.{rev}desc to be
2256 text.{rev}wrapped (no-eol)
2259 text.{rev}wrapped (no-eol)
2257 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2260 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2258 bcc7ff960b8e:desc to
2261 bcc7ff960b8e:desc to
2259 text.1:be wrapped
2262 text.1:be wrapped
2260 text.1:desc to be
2263 text.1:desc to be
2261 text.1:wrapped (no-eol)
2264 text.1:wrapped (no-eol)
2262
2265
2263 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2266 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2264 {node|short} (no-eol)
2267 {node|short} (no-eol)
2265 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2268 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2266 bcc-ff---b-e (no-eol)
2269 bcc-ff---b-e (no-eol)
2267
2270
2268 $ cat >> .hg/hgrc <<EOF
2271 $ cat >> .hg/hgrc <<EOF
2269 > [extensions]
2272 > [extensions]
2270 > color=
2273 > color=
2271 > [color]
2274 > [color]
2272 > mode=ansi
2275 > mode=ansi
2273 > text.{rev} = red
2276 > text.{rev} = red
2274 > text.1 = green
2277 > text.1 = green
2275 > EOF
2278 > EOF
2276 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2279 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2277 \x1b[0;31mtext\x1b[0m (esc)
2280 \x1b[0;31mtext\x1b[0m (esc)
2278 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2281 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2279 \x1b[0;32mtext\x1b[0m (esc)
2282 \x1b[0;32mtext\x1b[0m (esc)
2280
2283
2281 Test branches inside if statement:
2284 Test branches inside if statement:
2282
2285
2283 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2286 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2284 no
2287 no
2285
2288
2286 Test shortest(node) function:
2289 Test shortest(node) function:
2287
2290
2288 $ echo b > b
2291 $ echo b > b
2289 $ hg ci -qAm b
2292 $ hg ci -qAm b
2290 $ hg log --template '{shortest(node)}\n'
2293 $ hg log --template '{shortest(node)}\n'
2291 e777
2294 e777
2292 bcc7
2295 bcc7
2293 f776
2296 f776
2294 $ hg log --template '{shortest(node, 10)}\n'
2297 $ hg log --template '{shortest(node, 10)}\n'
2295 e777603221
2298 e777603221
2296 bcc7ff960b
2299 bcc7ff960b
2297 f7769ec2ab
2300 f7769ec2ab
2298
2301
2299 Test pad function
2302 Test pad function
2300
2303
2301 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2304 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2302 2 test
2305 2 test
2303 1 {node|short}
2306 1 {node|short}
2304 0 test
2307 0 test
2305
2308
2306 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2309 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2307 2 test
2310 2 test
2308 1 {node|short}
2311 1 {node|short}
2309 0 test
2312 0 test
2310
2313
2311 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2314 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2312 2------------------- test
2315 2------------------- test
2313 1------------------- {node|short}
2316 1------------------- {node|short}
2314 0------------------- test
2317 0------------------- test
2315
2318
2316 Test ifcontains function
2319 Test ifcontains function
2317
2320
2318 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2321 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2319 2 is in the string
2322 2 is in the string
2320 1 is not
2323 1 is not
2321 0 is in the string
2324 0 is in the string
2322
2325
2323 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2326 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2324 2 did not add a
2327 2 did not add a
2325 1 did not add a
2328 1 did not add a
2326 0 added a
2329 0 added a
2327
2330
2328 Test revset function
2331 Test revset function
2329
2332
2330 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2333 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2331 2 current rev
2334 2 current rev
2332 1 not current rev
2335 1 not current rev
2333 0 not current rev
2336 0 not current rev
2334
2337
2335 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2338 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2336 2 match rev
2339 2 match rev
2337 1 match rev
2340 1 match rev
2338 0 not match rev
2341 0 not match rev
2339
2342
2340 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2343 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2341 2 Parents: 1
2344 2 Parents: 1
2342 1 Parents: 0
2345 1 Parents: 0
2343 0 Parents:
2346 0 Parents:
2344
2347
2345 $ cat >> .hg/hgrc <<EOF
2348 $ cat >> .hg/hgrc <<EOF
2346 > [revsetalias]
2349 > [revsetalias]
2347 > myparents(\$1) = parents(\$1)
2350 > myparents(\$1) = parents(\$1)
2348 > EOF
2351 > EOF
2349 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2352 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2350 2 Parents: 1
2353 2 Parents: 1
2351 1 Parents: 0
2354 1 Parents: 0
2352 0 Parents:
2355 0 Parents:
2353
2356
2354 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2357 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2355 Rev: 2
2358 Rev: 2
2356 Ancestor: 0
2359 Ancestor: 0
2357 Ancestor: 1
2360 Ancestor: 1
2358 Ancestor: 2
2361 Ancestor: 2
2359
2362
2360 Rev: 1
2363 Rev: 1
2361 Ancestor: 0
2364 Ancestor: 0
2362 Ancestor: 1
2365 Ancestor: 1
2363
2366
2364 Rev: 0
2367 Rev: 0
2365 Ancestor: 0
2368 Ancestor: 0
2366
2369
2367 Test current bookmark templating
2370 Test current bookmark templating
2368
2371
2369 $ hg book foo
2372 $ hg book foo
2370 $ hg book bar
2373 $ hg book bar
2371 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2374 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2372 2 bar* foo
2375 2 bar* foo
2373 1
2376 1
2374 0
2377 0
2375 $ hg log --template "{rev} {currentbookmark}\n"
2378 $ hg log --template "{rev} {currentbookmark}\n"
2376 2 bar
2379 2 bar
2377 1
2380 1
2378 0
2381 0
2379 $ hg bookmarks --inactive bar
2382 $ hg bookmarks --inactive bar
2380 $ hg log --template "{rev} {currentbookmark}\n"
2383 $ hg log --template "{rev} {currentbookmark}\n"
2381 2
2384 2
2382 1
2385 1
2383 0
2386 0
2384 $ hg book -r1 baz
2387 $ hg book -r1 baz
2385 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2388 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2386 2 bar foo
2389 2 bar foo
2387 1 baz
2390 1 baz
2388 0
2391 0
2392 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
2393 2 t
2394 1 f
2395 0 f
2389
2396
2390 Test stringify on sub expressions
2397 Test stringify on sub expressions
2391
2398
2392 $ cd ..
2399 $ cd ..
2393 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2400 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2394 fourth, second, third
2401 fourth, second, third
2395 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2402 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2396 abc
2403 abc
2397
2404
2398 Test splitlines
2405 Test splitlines
2399
2406
2400 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2407 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2401 @ foo future
2408 @ foo future
2402 |
2409 |
2403 o foo third
2410 o foo third
2404 |
2411 |
2405 o foo second
2412 o foo second
2406
2413
2407 o foo merge
2414 o foo merge
2408 |\
2415 |\
2409 | o foo new head
2416 | o foo new head
2410 | |
2417 | |
2411 o | foo new branch
2418 o | foo new branch
2412 |/
2419 |/
2413 o foo no user, no domain
2420 o foo no user, no domain
2414 |
2421 |
2415 o foo no person
2422 o foo no person
2416 |
2423 |
2417 o foo other 1
2424 o foo other 1
2418 | foo other 2
2425 | foo other 2
2419 | foo
2426 | foo
2420 | foo other 3
2427 | foo other 3
2421 o foo line 1
2428 o foo line 1
2422 foo line 2
2429 foo line 2
2423
2430
2424 Test startswith
2431 Test startswith
2425 $ hg log -Gv -R a --template "{startswith(desc)}"
2432 $ hg log -Gv -R a --template "{startswith(desc)}"
2426 hg: parse error: startswith expects two arguments
2433 hg: parse error: startswith expects two arguments
2427 [255]
2434 [255]
2428
2435
2429 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2436 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2430 @
2437 @
2431 |
2438 |
2432 o
2439 o
2433 |
2440 |
2434 o
2441 o
2435
2442
2436 o
2443 o
2437 |\
2444 |\
2438 | o
2445 | o
2439 | |
2446 | |
2440 o |
2447 o |
2441 |/
2448 |/
2442 o
2449 o
2443 |
2450 |
2444 o
2451 o
2445 |
2452 |
2446 o
2453 o
2447 |
2454 |
2448 o line 1
2455 o line 1
2449 line 2
2456 line 2
2450
2457
2451 Test bad template with better error message
2458 Test bad template with better error message
2452
2459
2453 $ hg log -Gv -R a --template '{desc|user()}'
2460 $ hg log -Gv -R a --template '{desc|user()}'
2454 hg: parse error: expected a symbol, got 'func'
2461 hg: parse error: expected a symbol, got 'func'
2455 [255]
2462 [255]
2456
2463
2457 Test word function (including index out of bounds graceful failure)
2464 Test word function (including index out of bounds graceful failure)
2458
2465
2459 $ hg log -Gv -R a --template "{word('1', desc)}"
2466 $ hg log -Gv -R a --template "{word('1', desc)}"
2460 @
2467 @
2461 |
2468 |
2462 o
2469 o
2463 |
2470 |
2464 o
2471 o
2465
2472
2466 o
2473 o
2467 |\
2474 |\
2468 | o head
2475 | o head
2469 | |
2476 | |
2470 o | branch
2477 o | branch
2471 |/
2478 |/
2472 o user,
2479 o user,
2473 |
2480 |
2474 o person
2481 o person
2475 |
2482 |
2476 o 1
2483 o 1
2477 |
2484 |
2478 o 1
2485 o 1
2479
2486
2480
2487
2481 Test word third parameter used as splitter
2488 Test word third parameter used as splitter
2482
2489
2483 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2490 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2484 @ future
2491 @ future
2485 |
2492 |
2486 o third
2493 o third
2487 |
2494 |
2488 o sec
2495 o sec
2489
2496
2490 o merge
2497 o merge
2491 |\
2498 |\
2492 | o new head
2499 | o new head
2493 | |
2500 | |
2494 o | new branch
2501 o | new branch
2495 |/
2502 |/
2496 o n
2503 o n
2497 |
2504 |
2498 o n
2505 o n
2499 |
2506 |
2500 o
2507 o
2501 |
2508 |
2502 o line 1
2509 o line 1
2503 line 2
2510 line 2
2504
2511
2505 Test word error messages for not enough and too many arguments
2512 Test word error messages for not enough and too many arguments
2506
2513
2507 $ hg log -Gv -R a --template "{word('0')}"
2514 $ hg log -Gv -R a --template "{word('0')}"
2508 hg: parse error: word expects two or three arguments, got 1
2515 hg: parse error: word expects two or three arguments, got 1
2509 [255]
2516 [255]
2510
2517
2511 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2518 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2512 hg: parse error: word expects two or three arguments, got 7
2519 hg: parse error: word expects two or three arguments, got 7
2513 [255]
2520 [255]
General Comments 0
You need to be logged in to leave comments. Login now