##// END OF EJS Templates
templating: make new-style templating features work with command line lists
Matt Mackall -
r17631:0b241d7a default
parent child Browse files
Show More
@@ -1,367 +1,392 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 def showlist(name, values, plural=None, **args):
12 # This helper class allows us to handle both:
13 # "{files}" (legacy command-line-specific list hack) and
14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
15
16 class _hybrid(object):
17 def __init__(self, gen, values):
18 self.gen = gen
19 self.values = values
20 def __iter__(self):
21 return self.gen
22 def __call__(self):
23 for x in self.values:
24 yield x
25
26 def showlist(name, values, plural=None, element=None, **args):
27 if not element:
28 element = name
29 f = _showlist(name, values, plural, **args)
30 return _hybrid(f, [{element: x} for x in values])
31
32 def _showlist(name, values, plural=None, **args):
13 '''expand set of values.
33 '''expand set of values.
14 name is name of key in template map.
34 name is name of key in template map.
15 values is list of strings or dicts.
35 values is list of strings or dicts.
16 plural is plural of name, if not simply name + 's'.
36 plural is plural of name, if not simply name + 's'.
17
37
18 expansion works like this, given name 'foo'.
38 expansion works like this, given name 'foo'.
19
39
20 if values is empty, expand 'no_foos'.
40 if values is empty, expand 'no_foos'.
21
41
22 if 'foo' not in template map, return values as a string,
42 if 'foo' not in template map, return values as a string,
23 joined by space.
43 joined by space.
24
44
25 expand 'start_foos'.
45 expand 'start_foos'.
26
46
27 for each value, expand 'foo'. if 'last_foo' in template
47 for each value, expand 'foo'. if 'last_foo' in template
28 map, expand it instead of 'foo' for last key.
48 map, expand it instead of 'foo' for last key.
29
49
30 expand 'end_foos'.
50 expand 'end_foos'.
31 '''
51 '''
32 templ = args['templ']
52 templ = args['templ']
33 if plural:
53 if plural:
34 names = plural
54 names = plural
35 else: names = name + 's'
55 else: names = name + 's'
36 if not values:
56 if not values:
37 noname = 'no_' + names
57 noname = 'no_' + names
38 if noname in templ:
58 if noname in templ:
39 yield templ(noname, **args)
59 yield templ(noname, **args)
40 return
60 return
41 if name not in templ:
61 if name not in templ:
42 if isinstance(values[0], str):
62 if isinstance(values[0], str):
43 yield ' '.join(values)
63 yield ' '.join(values)
44 else:
64 else:
45 for v in values:
65 for v in values:
46 yield dict(v, **args)
66 yield dict(v, **args)
47 return
67 return
48 startname = 'start_' + names
68 startname = 'start_' + names
49 if startname in templ:
69 if startname in templ:
50 yield templ(startname, **args)
70 yield templ(startname, **args)
51 vargs = args.copy()
71 vargs = args.copy()
52 def one(v, tag=name):
72 def one(v, tag=name):
53 try:
73 try:
54 vargs.update(v)
74 vargs.update(v)
55 except (AttributeError, ValueError):
75 except (AttributeError, ValueError):
56 try:
76 try:
57 for a, b in v:
77 for a, b in v:
58 vargs[a] = b
78 vargs[a] = b
59 except ValueError:
79 except ValueError:
60 vargs[name] = v
80 vargs[name] = v
61 return templ(tag, **vargs)
81 return templ(tag, **vargs)
62 lastname = 'last_' + name
82 lastname = 'last_' + name
63 if lastname in templ:
83 if lastname in templ:
64 last = values.pop()
84 last = values.pop()
65 else:
85 else:
66 last = None
86 last = None
67 for v in values:
87 for v in values:
68 yield one(v)
88 yield one(v)
69 if last is not None:
89 if last is not None:
70 yield one(last, tag=lastname)
90 yield one(last, tag=lastname)
71 endname = 'end_' + names
91 endname = 'end_' + names
72 if endname in templ:
92 if endname in templ:
73 yield templ(endname, **args)
93 yield templ(endname, **args)
74
94
75 def getfiles(repo, ctx, revcache):
95 def getfiles(repo, ctx, revcache):
76 if 'files' not in revcache:
96 if 'files' not in revcache:
77 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
97 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
78 return revcache['files']
98 return revcache['files']
79
99
80 def getlatesttags(repo, ctx, cache):
100 def getlatesttags(repo, ctx, cache):
81 '''return date, distance and name for the latest tag of rev'''
101 '''return date, distance and name for the latest tag of rev'''
82
102
83 if 'latesttags' not in cache:
103 if 'latesttags' not in cache:
84 # Cache mapping from rev to a tuple with tag date, tag
104 # Cache mapping from rev to a tuple with tag date, tag
85 # distance and tag name
105 # distance and tag name
86 cache['latesttags'] = {-1: (0, 0, 'null')}
106 cache['latesttags'] = {-1: (0, 0, 'null')}
87 latesttags = cache['latesttags']
107 latesttags = cache['latesttags']
88
108
89 rev = ctx.rev()
109 rev = ctx.rev()
90 todo = [rev]
110 todo = [rev]
91 while todo:
111 while todo:
92 rev = todo.pop()
112 rev = todo.pop()
93 if rev in latesttags:
113 if rev in latesttags:
94 continue
114 continue
95 ctx = repo[rev]
115 ctx = repo[rev]
96 tags = [t for t in ctx.tags() if repo.tagtype(t) == 'global']
116 tags = [t for t in ctx.tags() if repo.tagtype(t) == 'global']
97 if tags:
117 if tags:
98 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
118 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
99 continue
119 continue
100 try:
120 try:
101 # The tuples are laid out so the right one can be found by
121 # The tuples are laid out so the right one can be found by
102 # comparison.
122 # comparison.
103 pdate, pdist, ptag = max(
123 pdate, pdist, ptag = max(
104 latesttags[p.rev()] for p in ctx.parents())
124 latesttags[p.rev()] for p in ctx.parents())
105 except KeyError:
125 except KeyError:
106 # Cache miss - recurse
126 # Cache miss - recurse
107 todo.append(rev)
127 todo.append(rev)
108 todo.extend(p.rev() for p in ctx.parents())
128 todo.extend(p.rev() for p in ctx.parents())
109 continue
129 continue
110 latesttags[rev] = pdate, pdist + 1, ptag
130 latesttags[rev] = pdate, pdist + 1, ptag
111 return latesttags[rev]
131 return latesttags[rev]
112
132
113 def getrenamedfn(repo, endrev=None):
133 def getrenamedfn(repo, endrev=None):
114 rcache = {}
134 rcache = {}
115 if endrev is None:
135 if endrev is None:
116 endrev = len(repo)
136 endrev = len(repo)
117
137
118 def getrenamed(fn, rev):
138 def getrenamed(fn, rev):
119 '''looks up all renames for a file (up to endrev) the first
139 '''looks up all renames for a file (up to endrev) the first
120 time the file is given. It indexes on the changerev and only
140 time the file is given. It indexes on the changerev and only
121 parses the manifest if linkrev != changerev.
141 parses the manifest if linkrev != changerev.
122 Returns rename info for fn at changerev rev.'''
142 Returns rename info for fn at changerev rev.'''
123 if fn not in rcache:
143 if fn not in rcache:
124 rcache[fn] = {}
144 rcache[fn] = {}
125 fl = repo.file(fn)
145 fl = repo.file(fn)
126 for i in fl:
146 for i in fl:
127 lr = fl.linkrev(i)
147 lr = fl.linkrev(i)
128 renamed = fl.renamed(fl.node(i))
148 renamed = fl.renamed(fl.node(i))
129 rcache[fn][lr] = renamed
149 rcache[fn][lr] = renamed
130 if lr >= endrev:
150 if lr >= endrev:
131 break
151 break
132 if rev in rcache[fn]:
152 if rev in rcache[fn]:
133 return rcache[fn][rev]
153 return rcache[fn][rev]
134
154
135 # If linkrev != rev (i.e. rev not found in rcache) fallback to
155 # If linkrev != rev (i.e. rev not found in rcache) fallback to
136 # filectx logic.
156 # filectx logic.
137 try:
157 try:
138 return repo[rev][fn].renamed()
158 return repo[rev][fn].renamed()
139 except error.LookupError:
159 except error.LookupError:
140 return None
160 return None
141
161
142 return getrenamed
162 return getrenamed
143
163
144
164
145 def showauthor(repo, ctx, templ, **args):
165 def showauthor(repo, ctx, templ, **args):
146 """:author: String. The unmodified author of the changeset."""
166 """:author: String. The unmodified author of the changeset."""
147 return ctx.user()
167 return ctx.user()
148
168
149 def showbisect(repo, ctx, templ, **args):
169 def showbisect(repo, ctx, templ, **args):
150 """:bisect: String. The changeset bisection status."""
170 """:bisect: String. The changeset bisection status."""
151 return hbisect.label(repo, ctx.node())
171 return hbisect.label(repo, ctx.node())
152
172
153 def showbranch(**args):
173 def showbranch(**args):
154 """:branch: String. The name of the branch on which the changeset was
174 """:branch: String. The name of the branch on which the changeset was
155 committed.
175 committed.
156 """
176 """
157 return args['ctx'].branch()
177 return args['ctx'].branch()
158
178
159 def showbranches(**args):
179 def showbranches(**args):
160 """:branches: List of strings. The name of the branch on which the
180 """:branches: List of strings. The name of the branch on which the
161 changeset was committed. Will be empty if the branch name was
181 changeset was committed. Will be empty if the branch name was
162 default.
182 default.
163 """
183 """
164 branch = args['ctx'].branch()
184 branch = args['ctx'].branch()
165 if branch != 'default':
185 if branch != 'default':
166 return showlist('branch', [branch], plural='branches', **args)
186 return showlist('branch', [branch], plural='branches', **args)
167
187
168 def showbookmarks(**args):
188 def showbookmarks(**args):
169 """:bookmarks: List of strings. Any bookmarks associated with the
189 """:bookmarks: List of strings. Any bookmarks associated with the
170 changeset.
190 changeset.
171 """
191 """
172 bookmarks = args['ctx'].bookmarks()
192 bookmarks = args['ctx'].bookmarks()
173 return showlist('bookmark', bookmarks, **args)
193 return showlist('bookmark', bookmarks, **args)
174
194
175 def showchildren(**args):
195 def showchildren(**args):
176 """:children: List of strings. The children of the changeset."""
196 """:children: List of strings. The children of the changeset."""
177 ctx = args['ctx']
197 ctx = args['ctx']
178 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
198 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
179 return showlist('children', childrevs, **args)
199 return showlist('children', childrevs, element='child', **args)
180
200
181 def showdate(repo, ctx, templ, **args):
201 def showdate(repo, ctx, templ, **args):
182 """:date: Date information. The date when the changeset was committed."""
202 """:date: Date information. The date when the changeset was committed."""
183 return ctx.date()
203 return ctx.date()
184
204
185 def showdescription(repo, ctx, templ, **args):
205 def showdescription(repo, ctx, templ, **args):
186 """:desc: String. The text of the changeset description."""
206 """:desc: String. The text of the changeset description."""
187 return ctx.description().strip()
207 return ctx.description().strip()
188
208
189 def showdiffstat(repo, ctx, templ, **args):
209 def showdiffstat(repo, ctx, templ, **args):
190 """:diffstat: String. Statistics of changes with the following format:
210 """:diffstat: String. Statistics of changes with the following format:
191 "modified files: +added/-removed lines"
211 "modified files: +added/-removed lines"
192 """
212 """
193 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
213 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
194 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
214 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
195 return '%s: +%s/-%s' % (len(stats), adds, removes)
215 return '%s: +%s/-%s' % (len(stats), adds, removes)
196
216
197 def showextras(**args):
217 def showextras(**args):
198 templ = args['templ']
218 templ = args['templ']
199 for key, value in sorted(args['ctx'].extra().items()):
219 for key, value in sorted(args['ctx'].extra().items()):
200 args = args.copy()
220 args = args.copy()
201 args.update(dict(key=key, value=value))
221 args.update(dict(key=key, value=value))
202 yield templ('extra', **args)
222 yield templ('extra', **args)
203
223
204 def showfileadds(**args):
224 def showfileadds(**args):
205 """:file_adds: List of strings. Files added by this changeset."""
225 """:file_adds: List of strings. Files added by this changeset."""
206 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
226 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
207 return showlist('file_add', getfiles(repo, ctx, revcache)[1], **args)
227 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
228 element='file', **args)
208
229
209 def showfilecopies(**args):
230 def showfilecopies(**args):
210 """:file_copies: List of strings. Files copied in this changeset with
231 """:file_copies: List of strings. Files copied in this changeset with
211 their sources.
232 their sources.
212 """
233 """
213 cache, ctx = args['cache'], args['ctx']
234 cache, ctx = args['cache'], args['ctx']
214 copies = args['revcache'].get('copies')
235 copies = args['revcache'].get('copies')
215 if copies is None:
236 if copies is None:
216 if 'getrenamed' not in cache:
237 if 'getrenamed' not in cache:
217 cache['getrenamed'] = getrenamedfn(args['repo'])
238 cache['getrenamed'] = getrenamedfn(args['repo'])
218 copies = []
239 copies = []
219 getrenamed = cache['getrenamed']
240 getrenamed = cache['getrenamed']
220 for fn in ctx.files():
241 for fn in ctx.files():
221 rename = getrenamed(fn, ctx.rev())
242 rename = getrenamed(fn, ctx.rev())
222 if rename:
243 if rename:
223 copies.append((fn, rename[0]))
244 copies.append((fn, rename[0]))
224
245
225 c = [{'name': x[0], 'source': x[1]} for x in copies]
246 c = [{'name': x[0], 'source': x[1]} for x in copies]
226 return showlist('file_copy', c, plural='file_copies', **args)
247 return showlist('file_copy', c, plural='file_copies',
248 element='file', **args)
227
249
228 # showfilecopiesswitch() displays file copies only if copy records are
250 # showfilecopiesswitch() displays file copies only if copy records are
229 # provided before calling the templater, usually with a --copies
251 # provided before calling the templater, usually with a --copies
230 # command line switch.
252 # command line switch.
231 def showfilecopiesswitch(**args):
253 def showfilecopiesswitch(**args):
232 """:file_copies_switch: List of strings. Like "file_copies" but displayed
254 """:file_copies_switch: List of strings. Like "file_copies" but displayed
233 only if the --copied switch is set.
255 only if the --copied switch is set.
234 """
256 """
235 copies = args['revcache'].get('copies') or []
257 copies = args['revcache'].get('copies') or []
236 c = [{'name': x[0], 'source': x[1]} for x in copies]
258 c = [{'name': x[0], 'source': x[1]} for x in copies]
237 return showlist('file_copy', c, plural='file_copies', **args)
259 return showlist('file_copy', c, plural='file_copies',
260 element='file', **args)
238
261
239 def showfiledels(**args):
262 def showfiledels(**args):
240 """:file_dels: List of strings. Files removed by this changeset."""
263 """:file_dels: List of strings. Files removed by this changeset."""
241 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
264 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
242 return showlist('file_del', getfiles(repo, ctx, revcache)[2], **args)
265 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
266 element='file', **args)
243
267
244 def showfilemods(**args):
268 def showfilemods(**args):
245 """:file_mods: List of strings. Files modified by this changeset."""
269 """:file_mods: List of strings. Files modified by this changeset."""
246 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
270 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
247 return showlist('file_mod', getfiles(repo, ctx, revcache)[0], **args)
271 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
272 element='file', **args)
248
273
249 def showfiles(**args):
274 def showfiles(**args):
250 """:files: List of strings. All files modified, added, or removed by this
275 """:files: List of strings. All files modified, added, or removed by this
251 changeset.
276 changeset.
252 """
277 """
253 return showlist('file', args['ctx'].files(), **args)
278 return showlist('file', args['ctx'].files(), **args)
254
279
255 def showlatesttag(repo, ctx, templ, cache, **args):
280 def showlatesttag(repo, ctx, templ, cache, **args):
256 """:latesttag: String. Most recent global tag in the ancestors of this
281 """:latesttag: String. Most recent global tag in the ancestors of this
257 changeset.
282 changeset.
258 """
283 """
259 return getlatesttags(repo, ctx, cache)[2]
284 return getlatesttags(repo, ctx, cache)[2]
260
285
261 def showlatesttagdistance(repo, ctx, templ, cache, **args):
286 def showlatesttagdistance(repo, ctx, templ, cache, **args):
262 """:latesttagdistance: Integer. Longest path to the latest tag."""
287 """:latesttagdistance: Integer. Longest path to the latest tag."""
263 return getlatesttags(repo, ctx, cache)[1]
288 return getlatesttags(repo, ctx, cache)[1]
264
289
265 def showmanifest(**args):
290 def showmanifest(**args):
266 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
291 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
267 args = args.copy()
292 args = args.copy()
268 args.update(dict(rev=repo.manifest.rev(ctx.changeset()[0]),
293 args.update(dict(rev=repo.manifest.rev(ctx.changeset()[0]),
269 node=hex(ctx.changeset()[0])))
294 node=hex(ctx.changeset()[0])))
270 return templ('manifest', **args)
295 return templ('manifest', **args)
271
296
272 def shownode(repo, ctx, templ, **args):
297 def shownode(repo, ctx, templ, **args):
273 """:node: String. The changeset identification hash, as a 40 hexadecimal
298 """:node: String. The changeset identification hash, as a 40 hexadecimal
274 digit string.
299 digit string.
275 """
300 """
276 return ctx.hex()
301 return ctx.hex()
277
302
278 def showp1rev(repo, ctx, templ, **args):
303 def showp1rev(repo, ctx, templ, **args):
279 """:p1rev: Integer. The repository-local revision number of the changeset's
304 """:p1rev: Integer. The repository-local revision number of the changeset's
280 first parent, or -1 if the changeset has no parents."""
305 first parent, or -1 if the changeset has no parents."""
281 return ctx.p1().rev()
306 return ctx.p1().rev()
282
307
283 def showp2rev(repo, ctx, templ, **args):
308 def showp2rev(repo, ctx, templ, **args):
284 """:p2rev: Integer. The repository-local revision number of the changeset's
309 """:p2rev: Integer. The repository-local revision number of the changeset's
285 second parent, or -1 if the changeset has no second parent."""
310 second parent, or -1 if the changeset has no second parent."""
286 return ctx.p2().rev()
311 return ctx.p2().rev()
287
312
288 def showp1node(repo, ctx, templ, **args):
313 def showp1node(repo, ctx, templ, **args):
289 """:p1node: String. The identification hash of the changeset's first parent,
314 """:p1node: String. The identification hash of the changeset's first parent,
290 as a 40 digit hexadecimal string. If the changeset has no parents, all
315 as a 40 digit hexadecimal string. If the changeset has no parents, all
291 digits are 0."""
316 digits are 0."""
292 return ctx.p1().hex()
317 return ctx.p1().hex()
293
318
294 def showp2node(repo, ctx, templ, **args):
319 def showp2node(repo, ctx, templ, **args):
295 """:p2node: String. The identification hash of the changeset's second
320 """:p2node: String. The identification hash of the changeset's second
296 parent, as a 40 digit hexadecimal string. If the changeset has no second
321 parent, as a 40 digit hexadecimal string. If the changeset has no second
297 parent, all digits are 0."""
322 parent, all digits are 0."""
298 return ctx.p2().hex()
323 return ctx.p2().hex()
299
324
300 def showphase(repo, ctx, templ, **args):
325 def showphase(repo, ctx, templ, **args):
301 """:phase: String. The changeset phase name."""
326 """:phase: String. The changeset phase name."""
302 return ctx.phasestr()
327 return ctx.phasestr()
303
328
304 def showphaseidx(repo, ctx, templ, **args):
329 def showphaseidx(repo, ctx, templ, **args):
305 """:phaseidx: Integer. The changeset phase index."""
330 """:phaseidx: Integer. The changeset phase index."""
306 return ctx.phase()
331 return ctx.phase()
307
332
308 def showrev(repo, ctx, templ, **args):
333 def showrev(repo, ctx, templ, **args):
309 """:rev: Integer. The repository-local changeset revision number."""
334 """:rev: Integer. The repository-local changeset revision number."""
310 return ctx.rev()
335 return ctx.rev()
311
336
312 def showtags(**args):
337 def showtags(**args):
313 """:tags: List of strings. Any tags associated with the changeset."""
338 """:tags: List of strings. Any tags associated with the changeset."""
314 return showlist('tag', args['ctx'].tags(), **args)
339 return showlist('tag', args['ctx'].tags(), **args)
315
340
316 # keywords are callables like:
341 # keywords are callables like:
317 # fn(repo, ctx, templ, cache, revcache, **args)
342 # fn(repo, ctx, templ, cache, revcache, **args)
318 # with:
343 # with:
319 # repo - current repository instance
344 # repo - current repository instance
320 # ctx - the changectx being displayed
345 # ctx - the changectx being displayed
321 # templ - the templater instance
346 # templ - the templater instance
322 # cache - a cache dictionary for the whole templater run
347 # cache - a cache dictionary for the whole templater run
323 # revcache - a cache dictionary for the current revision
348 # revcache - a cache dictionary for the current revision
324 keywords = {
349 keywords = {
325 'author': showauthor,
350 'author': showauthor,
326 'bisect': showbisect,
351 'bisect': showbisect,
327 'branch': showbranch,
352 'branch': showbranch,
328 'branches': showbranches,
353 'branches': showbranches,
329 'bookmarks': showbookmarks,
354 'bookmarks': showbookmarks,
330 'children': showchildren,
355 'children': showchildren,
331 'date': showdate,
356 'date': showdate,
332 'desc': showdescription,
357 'desc': showdescription,
333 'diffstat': showdiffstat,
358 'diffstat': showdiffstat,
334 'extras': showextras,
359 'extras': showextras,
335 'file_adds': showfileadds,
360 'file_adds': showfileadds,
336 'file_copies': showfilecopies,
361 'file_copies': showfilecopies,
337 'file_copies_switch': showfilecopiesswitch,
362 'file_copies_switch': showfilecopiesswitch,
338 'file_dels': showfiledels,
363 'file_dels': showfiledels,
339 'file_mods': showfilemods,
364 'file_mods': showfilemods,
340 'files': showfiles,
365 'files': showfiles,
341 'latesttag': showlatesttag,
366 'latesttag': showlatesttag,
342 'latesttagdistance': showlatesttagdistance,
367 'latesttagdistance': showlatesttagdistance,
343 'manifest': showmanifest,
368 'manifest': showmanifest,
344 'node': shownode,
369 'node': shownode,
345 'p1rev': showp1rev,
370 'p1rev': showp1rev,
346 'p1node': showp1node,
371 'p1node': showp1node,
347 'p2rev': showp2rev,
372 'p2rev': showp2rev,
348 'p2node': showp2node,
373 'p2node': showp2node,
349 'phase': showphase,
374 'phase': showphase,
350 'phaseidx': showphaseidx,
375 'phaseidx': showphaseidx,
351 'rev': showrev,
376 'rev': showrev,
352 'tags': showtags,
377 'tags': showtags,
353 }
378 }
354
379
355 def _showparents(**args):
380 def _showparents(**args):
356 """:parents: List of strings. The parents of the changeset in "rev:node"
381 """:parents: List of strings. The parents of the changeset in "rev:node"
357 format. If the changeset has only one "natural" parent (the predecessor
382 format. If the changeset has only one "natural" parent (the predecessor
358 revision) nothing is shown."""
383 revision) nothing is shown."""
359 pass
384 pass
360
385
361 dockeywords = {
386 dockeywords = {
362 'parents': _showparents,
387 'parents': _showparents,
363 }
388 }
364 dockeywords.update(keywords)
389 dockeywords.update(keywords)
365
390
366 # tell hggettext to extract docstrings from these functions:
391 # tell hggettext to extract docstrings from these functions:
367 i18nfunctions = dockeywords.values()
392 i18nfunctions = dockeywords.values()
@@ -1,402 +1,405 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 sys, os
9 import sys, os
10 import util, config, templatefilters, parser, error
10 import util, config, templatefilters, parser, error
11
11
12 # template parsing
12 # template parsing
13
13
14 elements = {
14 elements = {
15 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
15 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
16 ",": (2, None, ("list", 2)),
16 ",": (2, None, ("list", 2)),
17 "|": (5, None, ("|", 5)),
17 "|": (5, None, ("|", 5)),
18 "%": (6, None, ("%", 6)),
18 "%": (6, None, ("%", 6)),
19 ")": (0, None, None),
19 ")": (0, None, None),
20 "symbol": (0, ("symbol",), None),
20 "symbol": (0, ("symbol",), None),
21 "string": (0, ("string",), None),
21 "string": (0, ("string",), None),
22 "end": (0, None, None),
22 "end": (0, None, None),
23 }
23 }
24
24
25 def tokenizer(data):
25 def tokenizer(data):
26 program, start, end = data
26 program, start, end = data
27 pos = start
27 pos = start
28 while pos < end:
28 while pos < end:
29 c = program[pos]
29 c = program[pos]
30 if c.isspace(): # skip inter-token whitespace
30 if c.isspace(): # skip inter-token whitespace
31 pass
31 pass
32 elif c in "(,)%|": # handle simple operators
32 elif c in "(,)%|": # handle simple operators
33 yield (c, None, pos)
33 yield (c, None, pos)
34 elif (c in '"\'' or c == 'r' and
34 elif (c in '"\'' or c == 'r' and
35 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
35 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
36 if c == 'r':
36 if c == 'r':
37 pos += 1
37 pos += 1
38 c = program[pos]
38 c = program[pos]
39 decode = lambda x: x
39 decode = lambda x: x
40 else:
40 else:
41 decode = lambda x: x.decode('string-escape')
41 decode = lambda x: x.decode('string-escape')
42 pos += 1
42 pos += 1
43 s = pos
43 s = pos
44 while pos < end: # find closing quote
44 while pos < end: # find closing quote
45 d = program[pos]
45 d = program[pos]
46 if d == '\\': # skip over escaped characters
46 if d == '\\': # skip over escaped characters
47 pos += 2
47 pos += 2
48 continue
48 continue
49 if d == c:
49 if d == c:
50 yield ('string', decode(program[s:pos]), s)
50 yield ('string', decode(program[s:pos]), s)
51 break
51 break
52 pos += 1
52 pos += 1
53 else:
53 else:
54 raise error.ParseError(_("unterminated string"), s)
54 raise error.ParseError(_("unterminated string"), s)
55 elif c.isalnum() or c in '_':
55 elif c.isalnum() or c in '_':
56 s = pos
56 s = pos
57 pos += 1
57 pos += 1
58 while pos < end: # find end of symbol
58 while pos < end: # find end of symbol
59 d = program[pos]
59 d = program[pos]
60 if not (d.isalnum() or d == "_"):
60 if not (d.isalnum() or d == "_"):
61 break
61 break
62 pos += 1
62 pos += 1
63 sym = program[s:pos]
63 sym = program[s:pos]
64 yield ('symbol', sym, s)
64 yield ('symbol', sym, s)
65 pos -= 1
65 pos -= 1
66 elif c == '}':
66 elif c == '}':
67 pos += 1
67 pos += 1
68 break
68 break
69 else:
69 else:
70 raise error.ParseError(_("syntax error"), pos)
70 raise error.ParseError(_("syntax error"), pos)
71 pos += 1
71 pos += 1
72 yield ('end', None, pos)
72 yield ('end', None, pos)
73
73
74 def compiletemplate(tmpl, context):
74 def compiletemplate(tmpl, context):
75 parsed = []
75 parsed = []
76 pos, stop = 0, len(tmpl)
76 pos, stop = 0, len(tmpl)
77 p = parser.parser(tokenizer, elements)
77 p = parser.parser(tokenizer, elements)
78
78
79 while pos < stop:
79 while pos < stop:
80 n = tmpl.find('{', pos)
80 n = tmpl.find('{', pos)
81 if n < 0:
81 if n < 0:
82 parsed.append(("string", tmpl[pos:]))
82 parsed.append(("string", tmpl[pos:]))
83 break
83 break
84 if n > 0 and tmpl[n - 1] == '\\':
84 if n > 0 and tmpl[n - 1] == '\\':
85 # escaped
85 # escaped
86 parsed.append(("string", tmpl[pos:n - 1] + "{"))
86 parsed.append(("string", tmpl[pos:n - 1] + "{"))
87 pos = n + 1
87 pos = n + 1
88 continue
88 continue
89 if n > pos:
89 if n > pos:
90 parsed.append(("string", tmpl[pos:n]))
90 parsed.append(("string", tmpl[pos:n]))
91
91
92 pd = [tmpl, n + 1, stop]
92 pd = [tmpl, n + 1, stop]
93 parseres, pos = p.parse(pd)
93 parseres, pos = p.parse(pd)
94 parsed.append(parseres)
94 parsed.append(parseres)
95
95
96 return [compileexp(e, context) for e in parsed]
96 return [compileexp(e, context) for e in parsed]
97
97
98 def compileexp(exp, context):
98 def compileexp(exp, context):
99 t = exp[0]
99 t = exp[0]
100 if t in methods:
100 if t in methods:
101 return methods[t](exp, context)
101 return methods[t](exp, context)
102 raise error.ParseError(_("unknown method '%s'") % t)
102 raise error.ParseError(_("unknown method '%s'") % t)
103
103
104 # template evaluation
104 # template evaluation
105
105
106 def getsymbol(exp):
106 def getsymbol(exp):
107 if exp[0] == 'symbol':
107 if exp[0] == 'symbol':
108 return exp[1]
108 return exp[1]
109 raise error.ParseError(_("expected a symbol"))
109 raise error.ParseError(_("expected a symbol"))
110
110
111 def getlist(x):
111 def getlist(x):
112 if not x:
112 if not x:
113 return []
113 return []
114 if x[0] == 'list':
114 if x[0] == 'list':
115 return getlist(x[1]) + [x[2]]
115 return getlist(x[1]) + [x[2]]
116 return [x]
116 return [x]
117
117
118 def getfilter(exp, context):
118 def getfilter(exp, context):
119 f = getsymbol(exp)
119 f = getsymbol(exp)
120 if f not in context._filters:
120 if f not in context._filters:
121 raise error.ParseError(_("unknown function '%s'") % f)
121 raise error.ParseError(_("unknown function '%s'") % f)
122 return context._filters[f]
122 return context._filters[f]
123
123
124 def gettemplate(exp, context):
124 def gettemplate(exp, context):
125 if exp[0] == 'string':
125 if exp[0] == 'string':
126 return compiletemplate(exp[1], context)
126 return compiletemplate(exp[1], context)
127 if exp[0] == 'symbol':
127 if exp[0] == 'symbol':
128 return context._load(exp[1])
128 return context._load(exp[1])
129 raise error.ParseError(_("expected template specifier"))
129 raise error.ParseError(_("expected template specifier"))
130
130
131 def runstring(context, mapping, data):
131 def runstring(context, mapping, data):
132 return data
132 return data
133
133
134 def runsymbol(context, mapping, key):
134 def runsymbol(context, mapping, key):
135 v = mapping.get(key)
135 v = mapping.get(key)
136 if v is None:
136 if v is None:
137 v = context._defaults.get(key, '')
137 v = context._defaults.get(key, '')
138 if util.safehasattr(v, '__call__'):
138 if util.safehasattr(v, '__call__'):
139 return v(**mapping)
139 return v(**mapping)
140 return v
140 return v
141
141
142 def buildfilter(exp, context):
142 def buildfilter(exp, context):
143 func, data = compileexp(exp[1], context)
143 func, data = compileexp(exp[1], context)
144 filt = getfilter(exp[2], context)
144 filt = getfilter(exp[2], context)
145 return (runfilter, (func, data, filt))
145 return (runfilter, (func, data, filt))
146
146
147 def runfilter(context, mapping, data):
147 def runfilter(context, mapping, data):
148 func, data, filt = data
148 func, data, filt = data
149 try:
149 try:
150 return filt(func(context, mapping, data))
150 return filt(func(context, mapping, data))
151 except (ValueError, AttributeError, TypeError):
151 except (ValueError, AttributeError, TypeError):
152 if isinstance(data, tuple):
152 if isinstance(data, tuple):
153 dt = data[1]
153 dt = data[1]
154 else:
154 else:
155 dt = data
155 dt = data
156 raise util.Abort(_("template filter '%s' is not compatible with "
156 raise util.Abort(_("template filter '%s' is not compatible with "
157 "keyword '%s'") % (filt.func_name, dt))
157 "keyword '%s'") % (filt.func_name, dt))
158
158
159 def buildmap(exp, context):
159 def buildmap(exp, context):
160 func, data = compileexp(exp[1], context)
160 func, data = compileexp(exp[1], context)
161 ctmpl = gettemplate(exp[2], context)
161 ctmpl = gettemplate(exp[2], context)
162 return (runmap, (func, data, ctmpl))
162 return (runmap, (func, data, ctmpl))
163
163
164 def runmap(context, mapping, data):
164 def runmap(context, mapping, data):
165 func, data, ctmpl = data
165 func, data, ctmpl = data
166 d = func(context, mapping, data)
166 d = func(context, mapping, data)
167 if util.safehasattr(d, '__call__'):
168 d = d()
169
167 lm = mapping.copy()
170 lm = mapping.copy()
168
171
169 for i in d:
172 for i in d:
170 if isinstance(i, dict):
173 if isinstance(i, dict):
171 lm.update(i)
174 lm.update(i)
172 for f, d in ctmpl:
175 for f, d in ctmpl:
173 yield f(context, lm, d)
176 yield f(context, lm, d)
174 else:
177 else:
175 # v is not an iterable of dicts, this happen when 'key'
178 # v is not an iterable of dicts, this happen when 'key'
176 # has been fully expanded already and format is useless.
179 # has been fully expanded already and format is useless.
177 # If so, return the expanded value.
180 # If so, return the expanded value.
178 yield i
181 yield i
179
182
180 def buildfunc(exp, context):
183 def buildfunc(exp, context):
181 n = getsymbol(exp[1])
184 n = getsymbol(exp[1])
182 args = [compileexp(x, context) for x in getlist(exp[2])]
185 args = [compileexp(x, context) for x in getlist(exp[2])]
183 if n in funcs:
186 if n in funcs:
184 f = funcs[n]
187 f = funcs[n]
185 return (f, args)
188 return (f, args)
186 if n in context._filters:
189 if n in context._filters:
187 if len(args) != 1:
190 if len(args) != 1:
188 raise error.ParseError(_("filter %s expects one argument") % n)
191 raise error.ParseError(_("filter %s expects one argument") % n)
189 f = context._filters[n]
192 f = context._filters[n]
190 return (runfilter, (args[0][0], args[0][1], f))
193 return (runfilter, (args[0][0], args[0][1], f))
191
194
192 methods = {
195 methods = {
193 "string": lambda e, c: (runstring, e[1]),
196 "string": lambda e, c: (runstring, e[1]),
194 "symbol": lambda e, c: (runsymbol, e[1]),
197 "symbol": lambda e, c: (runsymbol, e[1]),
195 "group": lambda e, c: compileexp(e[1], c),
198 "group": lambda e, c: compileexp(e[1], c),
196 # ".": buildmember,
199 # ".": buildmember,
197 "|": buildfilter,
200 "|": buildfilter,
198 "%": buildmap,
201 "%": buildmap,
199 "func": buildfunc,
202 "func": buildfunc,
200 }
203 }
201
204
202 funcs = {
205 funcs = {
203 }
206 }
204
207
205 # template engine
208 # template engine
206
209
207 path = ['templates', '../templates']
210 path = ['templates', '../templates']
208 stringify = templatefilters.stringify
211 stringify = templatefilters.stringify
209
212
210 def _flatten(thing):
213 def _flatten(thing):
211 '''yield a single stream from a possibly nested set of iterators'''
214 '''yield a single stream from a possibly nested set of iterators'''
212 if isinstance(thing, str):
215 if isinstance(thing, str):
213 yield thing
216 yield thing
214 elif not util.safehasattr(thing, '__iter__'):
217 elif not util.safehasattr(thing, '__iter__'):
215 if thing is not None:
218 if thing is not None:
216 yield str(thing)
219 yield str(thing)
217 else:
220 else:
218 for i in thing:
221 for i in thing:
219 if isinstance(i, str):
222 if isinstance(i, str):
220 yield i
223 yield i
221 elif not util.safehasattr(i, '__iter__'):
224 elif not util.safehasattr(i, '__iter__'):
222 if i is not None:
225 if i is not None:
223 yield str(i)
226 yield str(i)
224 elif i is not None:
227 elif i is not None:
225 for j in _flatten(i):
228 for j in _flatten(i):
226 yield j
229 yield j
227
230
228 def parsestring(s, quoted=True):
231 def parsestring(s, quoted=True):
229 '''parse a string using simple c-like syntax.
232 '''parse a string using simple c-like syntax.
230 string must be in quotes if quoted is True.'''
233 string must be in quotes if quoted is True.'''
231 if quoted:
234 if quoted:
232 if len(s) < 2 or s[0] != s[-1]:
235 if len(s) < 2 or s[0] != s[-1]:
233 raise SyntaxError(_('unmatched quotes'))
236 raise SyntaxError(_('unmatched quotes'))
234 return s[1:-1].decode('string_escape')
237 return s[1:-1].decode('string_escape')
235
238
236 return s.decode('string_escape')
239 return s.decode('string_escape')
237
240
238 class engine(object):
241 class engine(object):
239 '''template expansion engine.
242 '''template expansion engine.
240
243
241 template expansion works like this. a map file contains key=value
244 template expansion works like this. a map file contains key=value
242 pairs. if value is quoted, it is treated as string. otherwise, it
245 pairs. if value is quoted, it is treated as string. otherwise, it
243 is treated as name of template file.
246 is treated as name of template file.
244
247
245 templater is asked to expand a key in map. it looks up key, and
248 templater is asked to expand a key in map. it looks up key, and
246 looks for strings like this: {foo}. it expands {foo} by looking up
249 looks for strings like this: {foo}. it expands {foo} by looking up
247 foo in map, and substituting it. expansion is recursive: it stops
250 foo in map, and substituting it. expansion is recursive: it stops
248 when there is no more {foo} to replace.
251 when there is no more {foo} to replace.
249
252
250 expansion also allows formatting and filtering.
253 expansion also allows formatting and filtering.
251
254
252 format uses key to expand each item in list. syntax is
255 format uses key to expand each item in list. syntax is
253 {key%format}.
256 {key%format}.
254
257
255 filter uses function to transform value. syntax is
258 filter uses function to transform value. syntax is
256 {key|filter1|filter2|...}.'''
259 {key|filter1|filter2|...}.'''
257
260
258 def __init__(self, loader, filters={}, defaults={}):
261 def __init__(self, loader, filters={}, defaults={}):
259 self._loader = loader
262 self._loader = loader
260 self._filters = filters
263 self._filters = filters
261 self._defaults = defaults
264 self._defaults = defaults
262 self._cache = {}
265 self._cache = {}
263
266
264 def _load(self, t):
267 def _load(self, t):
265 '''load, parse, and cache a template'''
268 '''load, parse, and cache a template'''
266 if t not in self._cache:
269 if t not in self._cache:
267 self._cache[t] = compiletemplate(self._loader(t), self)
270 self._cache[t] = compiletemplate(self._loader(t), self)
268 return self._cache[t]
271 return self._cache[t]
269
272
270 def process(self, t, mapping):
273 def process(self, t, mapping):
271 '''Perform expansion. t is name of map element to expand.
274 '''Perform expansion. t is name of map element to expand.
272 mapping contains added elements for use during expansion. Is a
275 mapping contains added elements for use during expansion. Is a
273 generator.'''
276 generator.'''
274 return _flatten(func(self, mapping, data) for func, data in
277 return _flatten(func(self, mapping, data) for func, data in
275 self._load(t))
278 self._load(t))
276
279
277 engines = {'default': engine}
280 engines = {'default': engine}
278
281
279 class templater(object):
282 class templater(object):
280
283
281 def __init__(self, mapfile, filters={}, defaults={}, cache={},
284 def __init__(self, mapfile, filters={}, defaults={}, cache={},
282 minchunk=1024, maxchunk=65536):
285 minchunk=1024, maxchunk=65536):
283 '''set up template engine.
286 '''set up template engine.
284 mapfile is name of file to read map definitions from.
287 mapfile is name of file to read map definitions from.
285 filters is dict of functions. each transforms a value into another.
288 filters is dict of functions. each transforms a value into another.
286 defaults is dict of default map definitions.'''
289 defaults is dict of default map definitions.'''
287 self.mapfile = mapfile or 'template'
290 self.mapfile = mapfile or 'template'
288 self.cache = cache.copy()
291 self.cache = cache.copy()
289 self.map = {}
292 self.map = {}
290 self.base = (mapfile and os.path.dirname(mapfile)) or ''
293 self.base = (mapfile and os.path.dirname(mapfile)) or ''
291 self.filters = templatefilters.filters.copy()
294 self.filters = templatefilters.filters.copy()
292 self.filters.update(filters)
295 self.filters.update(filters)
293 self.defaults = defaults
296 self.defaults = defaults
294 self.minchunk, self.maxchunk = minchunk, maxchunk
297 self.minchunk, self.maxchunk = minchunk, maxchunk
295 self.ecache = {}
298 self.ecache = {}
296
299
297 if not mapfile:
300 if not mapfile:
298 return
301 return
299 if not os.path.exists(mapfile):
302 if not os.path.exists(mapfile):
300 raise util.Abort(_('style not found: %s') % mapfile)
303 raise util.Abort(_('style not found: %s') % mapfile)
301
304
302 conf = config.config()
305 conf = config.config()
303 conf.read(mapfile)
306 conf.read(mapfile)
304
307
305 for key, val in conf[''].items():
308 for key, val in conf[''].items():
306 if not val:
309 if not val:
307 raise SyntaxError(_('%s: missing value') % conf.source('', key))
310 raise SyntaxError(_('%s: missing value') % conf.source('', key))
308 if val[0] in "'\"":
311 if val[0] in "'\"":
309 try:
312 try:
310 self.cache[key] = parsestring(val)
313 self.cache[key] = parsestring(val)
311 except SyntaxError, inst:
314 except SyntaxError, inst:
312 raise SyntaxError('%s: %s' %
315 raise SyntaxError('%s: %s' %
313 (conf.source('', key), inst.args[0]))
316 (conf.source('', key), inst.args[0]))
314 else:
317 else:
315 val = 'default', val
318 val = 'default', val
316 if ':' in val[1]:
319 if ':' in val[1]:
317 val = val[1].split(':', 1)
320 val = val[1].split(':', 1)
318 self.map[key] = val[0], os.path.join(self.base, val[1])
321 self.map[key] = val[0], os.path.join(self.base, val[1])
319
322
320 def __contains__(self, key):
323 def __contains__(self, key):
321 return key in self.cache or key in self.map
324 return key in self.cache or key in self.map
322
325
323 def load(self, t):
326 def load(self, t):
324 '''Get the template for the given template name. Use a local cache.'''
327 '''Get the template for the given template name. Use a local cache.'''
325 if t not in self.cache:
328 if t not in self.cache:
326 try:
329 try:
327 self.cache[t] = util.readfile(self.map[t][1])
330 self.cache[t] = util.readfile(self.map[t][1])
328 except KeyError, inst:
331 except KeyError, inst:
329 raise util.Abort(_('"%s" not in template map') % inst.args[0])
332 raise util.Abort(_('"%s" not in template map') % inst.args[0])
330 except IOError, inst:
333 except IOError, inst:
331 raise IOError(inst.args[0], _('template file %s: %s') %
334 raise IOError(inst.args[0], _('template file %s: %s') %
332 (self.map[t][1], inst.args[1]))
335 (self.map[t][1], inst.args[1]))
333 return self.cache[t]
336 return self.cache[t]
334
337
335 def __call__(self, t, **mapping):
338 def __call__(self, t, **mapping):
336 ttype = t in self.map and self.map[t][0] or 'default'
339 ttype = t in self.map and self.map[t][0] or 'default'
337 if ttype not in self.ecache:
340 if ttype not in self.ecache:
338 self.ecache[ttype] = engines[ttype](self.load,
341 self.ecache[ttype] = engines[ttype](self.load,
339 self.filters, self.defaults)
342 self.filters, self.defaults)
340 proc = self.ecache[ttype]
343 proc = self.ecache[ttype]
341
344
342 stream = proc.process(t, mapping)
345 stream = proc.process(t, mapping)
343 if self.minchunk:
346 if self.minchunk:
344 stream = util.increasingchunks(stream, min=self.minchunk,
347 stream = util.increasingchunks(stream, min=self.minchunk,
345 max=self.maxchunk)
348 max=self.maxchunk)
346 return stream
349 return stream
347
350
348 def templatepath(name=None):
351 def templatepath(name=None):
349 '''return location of template file or directory (if no name).
352 '''return location of template file or directory (if no name).
350 returns None if not found.'''
353 returns None if not found.'''
351 normpaths = []
354 normpaths = []
352
355
353 # executable version (py2exe) doesn't support __file__
356 # executable version (py2exe) doesn't support __file__
354 if util.mainfrozen():
357 if util.mainfrozen():
355 module = sys.executable
358 module = sys.executable
356 else:
359 else:
357 module = __file__
360 module = __file__
358 for f in path:
361 for f in path:
359 if f.startswith('/'):
362 if f.startswith('/'):
360 p = f
363 p = f
361 else:
364 else:
362 fl = f.split('/')
365 fl = f.split('/')
363 p = os.path.join(os.path.dirname(module), *fl)
366 p = os.path.join(os.path.dirname(module), *fl)
364 if name:
367 if name:
365 p = os.path.join(p, name)
368 p = os.path.join(p, name)
366 if name and os.path.exists(p):
369 if name and os.path.exists(p):
367 return os.path.normpath(p)
370 return os.path.normpath(p)
368 elif os.path.isdir(p):
371 elif os.path.isdir(p):
369 normpaths.append(os.path.normpath(p))
372 normpaths.append(os.path.normpath(p))
370
373
371 return normpaths
374 return normpaths
372
375
373 def stylemap(styles, paths=None):
376 def stylemap(styles, paths=None):
374 """Return path to mapfile for a given style.
377 """Return path to mapfile for a given style.
375
378
376 Searches mapfile in the following locations:
379 Searches mapfile in the following locations:
377 1. templatepath/style/map
380 1. templatepath/style/map
378 2. templatepath/map-style
381 2. templatepath/map-style
379 3. templatepath/map
382 3. templatepath/map
380 """
383 """
381
384
382 if paths is None:
385 if paths is None:
383 paths = templatepath()
386 paths = templatepath()
384 elif isinstance(paths, str):
387 elif isinstance(paths, str):
385 paths = [paths]
388 paths = [paths]
386
389
387 if isinstance(styles, str):
390 if isinstance(styles, str):
388 styles = [styles]
391 styles = [styles]
389
392
390 for style in styles:
393 for style in styles:
391 if not style:
394 if not style:
392 continue
395 continue
393 locations = [os.path.join(style, 'map'), 'map-' + style]
396 locations = [os.path.join(style, 'map'), 'map-' + style]
394 locations.append('map')
397 locations.append('map')
395
398
396 for path in paths:
399 for path in paths:
397 for location in locations:
400 for location in locations:
398 mapfile = os.path.join(path, location)
401 mapfile = os.path.join(path, location)
399 if os.path.isfile(mapfile):
402 if os.path.isfile(mapfile):
400 return style, mapfile
403 return style, mapfile
401
404
402 raise RuntimeError("No hgweb templates found in %r" % paths)
405 raise RuntimeError("No hgweb templates found in %r" % paths)
@@ -1,1522 +1,1527 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 Quoting for ui.logtemplate
46 Quoting for ui.logtemplate
47
47
48 $ hg tip --config "ui.logtemplate={rev}\n"
48 $ hg tip --config "ui.logtemplate={rev}\n"
49 8
49 8
50 $ hg tip --config "ui.logtemplate='{rev}\n'"
50 $ hg tip --config "ui.logtemplate='{rev}\n'"
51 8
51 8
52 $ hg tip --config 'ui.logtemplate="{rev}\n"'
52 $ hg tip --config 'ui.logtemplate="{rev}\n"'
53 8
53 8
54
54
55 Make sure user/global hgrc does not affect tests
55 Make sure user/global hgrc does not affect tests
56
56
57 $ echo '[ui]' > .hg/hgrc
57 $ echo '[ui]' > .hg/hgrc
58 $ echo 'logtemplate =' >> .hg/hgrc
58 $ echo 'logtemplate =' >> .hg/hgrc
59 $ echo 'style =' >> .hg/hgrc
59 $ echo 'style =' >> .hg/hgrc
60
60
61 Default style is like normal output:
61 Default style is like normal output:
62
62
63 $ hg log > log.out
63 $ hg log > log.out
64 $ hg log --style default > style.out
64 $ hg log --style default > style.out
65 $ cmp log.out style.out || diff -u log.out style.out
65 $ cmp log.out style.out || diff -u log.out style.out
66
66
67 $ hg log -v > log.out
67 $ hg log -v > log.out
68 $ hg log -v --style default > style.out
68 $ hg log -v --style default > style.out
69 $ cmp log.out style.out || diff -u log.out style.out
69 $ cmp log.out style.out || diff -u log.out style.out
70
70
71 $ hg log --debug > log.out
71 $ hg log --debug > log.out
72 $ hg log --debug --style default > style.out
72 $ hg log --debug --style default > style.out
73 $ cmp log.out style.out || diff -u log.out style.out
73 $ cmp log.out style.out || diff -u log.out style.out
74
74
75 Revision with no copies (used to print a traceback):
75 Revision with no copies (used to print a traceback):
76
76
77 $ hg tip -v --template '\n'
77 $ hg tip -v --template '\n'
78
78
79
79
80 Compact style works:
80 Compact style works:
81
81
82 $ hg log --style compact
82 $ hg log --style compact
83 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
83 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
84 third
84 third
85
85
86 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
86 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
87 second
87 second
88
88
89 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
89 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
90 merge
90 merge
91
91
92 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
92 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
93 new head
93 new head
94
94
95 4 bbe44766e73d 1970-01-17 04:53 +0000 person
95 4 bbe44766e73d 1970-01-17 04:53 +0000 person
96 new branch
96 new branch
97
97
98 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
98 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
99 no user, no domain
99 no user, no domain
100
100
101 2 97054abb4ab8 1970-01-14 21:20 +0000 other
101 2 97054abb4ab8 1970-01-14 21:20 +0000 other
102 no person
102 no person
103
103
104 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
104 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
105 other 1
105 other 1
106
106
107 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
107 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
108 line 1
108 line 1
109
109
110
110
111 $ hg log -v --style compact
111 $ hg log -v --style compact
112 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
112 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
113 third
113 third
114
114
115 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
115 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
116 second
116 second
117
117
118 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
118 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
119 merge
119 merge
120
120
121 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
121 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
122 new head
122 new head
123
123
124 4 bbe44766e73d 1970-01-17 04:53 +0000 person
124 4 bbe44766e73d 1970-01-17 04:53 +0000 person
125 new branch
125 new branch
126
126
127 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
127 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
128 no user, no domain
128 no user, no domain
129
129
130 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
130 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
131 no person
131 no person
132
132
133 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
133 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
134 other 1
134 other 1
135 other 2
135 other 2
136
136
137 other 3
137 other 3
138
138
139 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
139 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
140 line 1
140 line 1
141 line 2
141 line 2
142
142
143
143
144 $ hg log --debug --style compact
144 $ hg log --debug --style compact
145 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
145 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
146 third
146 third
147
147
148 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
148 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
149 second
149 second
150
150
151 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
151 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
152 merge
152 merge
153
153
154 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
154 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
155 new head
155 new head
156
156
157 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
157 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
158 new branch
158 new branch
159
159
160 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
160 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
161 no user, no domain
161 no user, no domain
162
162
163 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
163 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
164 no person
164 no person
165
165
166 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
166 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
167 other 1
167 other 1
168 other 2
168 other 2
169
169
170 other 3
170 other 3
171
171
172 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
172 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
173 line 1
173 line 1
174 line 2
174 line 2
175
175
176
176
177 Test xml styles:
177 Test xml styles:
178
178
179 $ hg log --style xml
179 $ hg log --style xml
180 <?xml version="1.0"?>
180 <?xml version="1.0"?>
181 <log>
181 <log>
182 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
182 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
183 <tag>tip</tag>
183 <tag>tip</tag>
184 <author email="test">test</author>
184 <author email="test">test</author>
185 <date>2020-01-01T10:01:00+00:00</date>
185 <date>2020-01-01T10:01:00+00:00</date>
186 <msg xml:space="preserve">third</msg>
186 <msg xml:space="preserve">third</msg>
187 </logentry>
187 </logentry>
188 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
188 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
189 <parent revision="-1" node="0000000000000000000000000000000000000000" />
189 <parent revision="-1" node="0000000000000000000000000000000000000000" />
190 <author email="user@hostname">User Name</author>
190 <author email="user@hostname">User Name</author>
191 <date>1970-01-12T13:46:40+00:00</date>
191 <date>1970-01-12T13:46:40+00:00</date>
192 <msg xml:space="preserve">second</msg>
192 <msg xml:space="preserve">second</msg>
193 </logentry>
193 </logentry>
194 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
194 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
195 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
195 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
196 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
196 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
197 <author email="person">person</author>
197 <author email="person">person</author>
198 <date>1970-01-18T08:40:01+00:00</date>
198 <date>1970-01-18T08:40:01+00:00</date>
199 <msg xml:space="preserve">merge</msg>
199 <msg xml:space="preserve">merge</msg>
200 </logentry>
200 </logentry>
201 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
201 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
202 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
202 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
203 <author email="person">person</author>
203 <author email="person">person</author>
204 <date>1970-01-18T08:40:00+00:00</date>
204 <date>1970-01-18T08:40:00+00:00</date>
205 <msg xml:space="preserve">new head</msg>
205 <msg xml:space="preserve">new head</msg>
206 </logentry>
206 </logentry>
207 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
207 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
208 <branch>foo</branch>
208 <branch>foo</branch>
209 <author email="person">person</author>
209 <author email="person">person</author>
210 <date>1970-01-17T04:53:20+00:00</date>
210 <date>1970-01-17T04:53:20+00:00</date>
211 <msg xml:space="preserve">new branch</msg>
211 <msg xml:space="preserve">new branch</msg>
212 </logentry>
212 </logentry>
213 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
213 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
214 <author email="person">person</author>
214 <author email="person">person</author>
215 <date>1970-01-16T01:06:40+00:00</date>
215 <date>1970-01-16T01:06:40+00:00</date>
216 <msg xml:space="preserve">no user, no domain</msg>
216 <msg xml:space="preserve">no user, no domain</msg>
217 </logentry>
217 </logentry>
218 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
218 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
219 <author email="other@place">other</author>
219 <author email="other@place">other</author>
220 <date>1970-01-14T21:20:00+00:00</date>
220 <date>1970-01-14T21:20:00+00:00</date>
221 <msg xml:space="preserve">no person</msg>
221 <msg xml:space="preserve">no person</msg>
222 </logentry>
222 </logentry>
223 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
223 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
224 <author email="other@place">A. N. Other</author>
224 <author email="other@place">A. N. Other</author>
225 <date>1970-01-13T17:33:20+00:00</date>
225 <date>1970-01-13T17:33:20+00:00</date>
226 <msg xml:space="preserve">other 1
226 <msg xml:space="preserve">other 1
227 other 2
227 other 2
228
228
229 other 3</msg>
229 other 3</msg>
230 </logentry>
230 </logentry>
231 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
231 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
232 <author email="user@hostname">User Name</author>
232 <author email="user@hostname">User Name</author>
233 <date>1970-01-12T13:46:40+00:00</date>
233 <date>1970-01-12T13:46:40+00:00</date>
234 <msg xml:space="preserve">line 1
234 <msg xml:space="preserve">line 1
235 line 2</msg>
235 line 2</msg>
236 </logentry>
236 </logentry>
237 </log>
237 </log>
238
238
239 $ hg log -v --style xml
239 $ hg log -v --style xml
240 <?xml version="1.0"?>
240 <?xml version="1.0"?>
241 <log>
241 <log>
242 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
242 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
243 <tag>tip</tag>
243 <tag>tip</tag>
244 <author email="test">test</author>
244 <author email="test">test</author>
245 <date>2020-01-01T10:01:00+00:00</date>
245 <date>2020-01-01T10:01:00+00:00</date>
246 <msg xml:space="preserve">third</msg>
246 <msg xml:space="preserve">third</msg>
247 <paths>
247 <paths>
248 <path action="A">fourth</path>
248 <path action="A">fourth</path>
249 <path action="A">third</path>
249 <path action="A">third</path>
250 <path action="R">second</path>
250 <path action="R">second</path>
251 </paths>
251 </paths>
252 <copies>
252 <copies>
253 <copy source="second">fourth</copy>
253 <copy source="second">fourth</copy>
254 </copies>
254 </copies>
255 </logentry>
255 </logentry>
256 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
256 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
257 <parent revision="-1" node="0000000000000000000000000000000000000000" />
257 <parent revision="-1" node="0000000000000000000000000000000000000000" />
258 <author email="user@hostname">User Name</author>
258 <author email="user@hostname">User Name</author>
259 <date>1970-01-12T13:46:40+00:00</date>
259 <date>1970-01-12T13:46:40+00:00</date>
260 <msg xml:space="preserve">second</msg>
260 <msg xml:space="preserve">second</msg>
261 <paths>
261 <paths>
262 <path action="A">second</path>
262 <path action="A">second</path>
263 </paths>
263 </paths>
264 </logentry>
264 </logentry>
265 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
265 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
266 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
266 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
267 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
267 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
268 <author email="person">person</author>
268 <author email="person">person</author>
269 <date>1970-01-18T08:40:01+00:00</date>
269 <date>1970-01-18T08:40:01+00:00</date>
270 <msg xml:space="preserve">merge</msg>
270 <msg xml:space="preserve">merge</msg>
271 <paths>
271 <paths>
272 </paths>
272 </paths>
273 </logentry>
273 </logentry>
274 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
274 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
275 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
275 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
276 <author email="person">person</author>
276 <author email="person">person</author>
277 <date>1970-01-18T08:40:00+00:00</date>
277 <date>1970-01-18T08:40:00+00:00</date>
278 <msg xml:space="preserve">new head</msg>
278 <msg xml:space="preserve">new head</msg>
279 <paths>
279 <paths>
280 <path action="A">d</path>
280 <path action="A">d</path>
281 </paths>
281 </paths>
282 </logentry>
282 </logentry>
283 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
283 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
284 <branch>foo</branch>
284 <branch>foo</branch>
285 <author email="person">person</author>
285 <author email="person">person</author>
286 <date>1970-01-17T04:53:20+00:00</date>
286 <date>1970-01-17T04:53:20+00:00</date>
287 <msg xml:space="preserve">new branch</msg>
287 <msg xml:space="preserve">new branch</msg>
288 <paths>
288 <paths>
289 </paths>
289 </paths>
290 </logentry>
290 </logentry>
291 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
291 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
292 <author email="person">person</author>
292 <author email="person">person</author>
293 <date>1970-01-16T01:06:40+00:00</date>
293 <date>1970-01-16T01:06:40+00:00</date>
294 <msg xml:space="preserve">no user, no domain</msg>
294 <msg xml:space="preserve">no user, no domain</msg>
295 <paths>
295 <paths>
296 <path action="M">c</path>
296 <path action="M">c</path>
297 </paths>
297 </paths>
298 </logentry>
298 </logentry>
299 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
299 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
300 <author email="other@place">other</author>
300 <author email="other@place">other</author>
301 <date>1970-01-14T21:20:00+00:00</date>
301 <date>1970-01-14T21:20:00+00:00</date>
302 <msg xml:space="preserve">no person</msg>
302 <msg xml:space="preserve">no person</msg>
303 <paths>
303 <paths>
304 <path action="A">c</path>
304 <path action="A">c</path>
305 </paths>
305 </paths>
306 </logentry>
306 </logentry>
307 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
307 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
308 <author email="other@place">A. N. Other</author>
308 <author email="other@place">A. N. Other</author>
309 <date>1970-01-13T17:33:20+00:00</date>
309 <date>1970-01-13T17:33:20+00:00</date>
310 <msg xml:space="preserve">other 1
310 <msg xml:space="preserve">other 1
311 other 2
311 other 2
312
312
313 other 3</msg>
313 other 3</msg>
314 <paths>
314 <paths>
315 <path action="A">b</path>
315 <path action="A">b</path>
316 </paths>
316 </paths>
317 </logentry>
317 </logentry>
318 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
318 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
319 <author email="user@hostname">User Name</author>
319 <author email="user@hostname">User Name</author>
320 <date>1970-01-12T13:46:40+00:00</date>
320 <date>1970-01-12T13:46:40+00:00</date>
321 <msg xml:space="preserve">line 1
321 <msg xml:space="preserve">line 1
322 line 2</msg>
322 line 2</msg>
323 <paths>
323 <paths>
324 <path action="A">a</path>
324 <path action="A">a</path>
325 </paths>
325 </paths>
326 </logentry>
326 </logentry>
327 </log>
327 </log>
328
328
329 $ hg log --debug --style xml
329 $ hg log --debug --style xml
330 <?xml version="1.0"?>
330 <?xml version="1.0"?>
331 <log>
331 <log>
332 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
332 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
333 <tag>tip</tag>
333 <tag>tip</tag>
334 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
334 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
335 <parent revision="-1" node="0000000000000000000000000000000000000000" />
335 <parent revision="-1" node="0000000000000000000000000000000000000000" />
336 <author email="test">test</author>
336 <author email="test">test</author>
337 <date>2020-01-01T10:01:00+00:00</date>
337 <date>2020-01-01T10:01:00+00:00</date>
338 <msg xml:space="preserve">third</msg>
338 <msg xml:space="preserve">third</msg>
339 <paths>
339 <paths>
340 <path action="A">fourth</path>
340 <path action="A">fourth</path>
341 <path action="A">third</path>
341 <path action="A">third</path>
342 <path action="R">second</path>
342 <path action="R">second</path>
343 </paths>
343 </paths>
344 <copies>
344 <copies>
345 <copy source="second">fourth</copy>
345 <copy source="second">fourth</copy>
346 </copies>
346 </copies>
347 <extra key="branch">default</extra>
347 <extra key="branch">default</extra>
348 </logentry>
348 </logentry>
349 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
349 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
350 <parent revision="-1" node="0000000000000000000000000000000000000000" />
350 <parent revision="-1" node="0000000000000000000000000000000000000000" />
351 <parent revision="-1" node="0000000000000000000000000000000000000000" />
351 <parent revision="-1" node="0000000000000000000000000000000000000000" />
352 <author email="user@hostname">User Name</author>
352 <author email="user@hostname">User Name</author>
353 <date>1970-01-12T13:46:40+00:00</date>
353 <date>1970-01-12T13:46:40+00:00</date>
354 <msg xml:space="preserve">second</msg>
354 <msg xml:space="preserve">second</msg>
355 <paths>
355 <paths>
356 <path action="A">second</path>
356 <path action="A">second</path>
357 </paths>
357 </paths>
358 <extra key="branch">default</extra>
358 <extra key="branch">default</extra>
359 </logentry>
359 </logentry>
360 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
360 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
361 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
361 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
362 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
362 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
363 <author email="person">person</author>
363 <author email="person">person</author>
364 <date>1970-01-18T08:40:01+00:00</date>
364 <date>1970-01-18T08:40:01+00:00</date>
365 <msg xml:space="preserve">merge</msg>
365 <msg xml:space="preserve">merge</msg>
366 <paths>
366 <paths>
367 </paths>
367 </paths>
368 <extra key="branch">default</extra>
368 <extra key="branch">default</extra>
369 </logentry>
369 </logentry>
370 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
370 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
371 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
371 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
372 <parent revision="-1" node="0000000000000000000000000000000000000000" />
372 <parent revision="-1" node="0000000000000000000000000000000000000000" />
373 <author email="person">person</author>
373 <author email="person">person</author>
374 <date>1970-01-18T08:40:00+00:00</date>
374 <date>1970-01-18T08:40:00+00:00</date>
375 <msg xml:space="preserve">new head</msg>
375 <msg xml:space="preserve">new head</msg>
376 <paths>
376 <paths>
377 <path action="A">d</path>
377 <path action="A">d</path>
378 </paths>
378 </paths>
379 <extra key="branch">default</extra>
379 <extra key="branch">default</extra>
380 </logentry>
380 </logentry>
381 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
381 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
382 <branch>foo</branch>
382 <branch>foo</branch>
383 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
383 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
384 <parent revision="-1" node="0000000000000000000000000000000000000000" />
384 <parent revision="-1" node="0000000000000000000000000000000000000000" />
385 <author email="person">person</author>
385 <author email="person">person</author>
386 <date>1970-01-17T04:53:20+00:00</date>
386 <date>1970-01-17T04:53:20+00:00</date>
387 <msg xml:space="preserve">new branch</msg>
387 <msg xml:space="preserve">new branch</msg>
388 <paths>
388 <paths>
389 </paths>
389 </paths>
390 <extra key="branch">foo</extra>
390 <extra key="branch">foo</extra>
391 </logentry>
391 </logentry>
392 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
392 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
393 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
393 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
394 <parent revision="-1" node="0000000000000000000000000000000000000000" />
394 <parent revision="-1" node="0000000000000000000000000000000000000000" />
395 <author email="person">person</author>
395 <author email="person">person</author>
396 <date>1970-01-16T01:06:40+00:00</date>
396 <date>1970-01-16T01:06:40+00:00</date>
397 <msg xml:space="preserve">no user, no domain</msg>
397 <msg xml:space="preserve">no user, no domain</msg>
398 <paths>
398 <paths>
399 <path action="M">c</path>
399 <path action="M">c</path>
400 </paths>
400 </paths>
401 <extra key="branch">default</extra>
401 <extra key="branch">default</extra>
402 </logentry>
402 </logentry>
403 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
403 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
404 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
404 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
405 <parent revision="-1" node="0000000000000000000000000000000000000000" />
405 <parent revision="-1" node="0000000000000000000000000000000000000000" />
406 <author email="other@place">other</author>
406 <author email="other@place">other</author>
407 <date>1970-01-14T21:20:00+00:00</date>
407 <date>1970-01-14T21:20:00+00:00</date>
408 <msg xml:space="preserve">no person</msg>
408 <msg xml:space="preserve">no person</msg>
409 <paths>
409 <paths>
410 <path action="A">c</path>
410 <path action="A">c</path>
411 </paths>
411 </paths>
412 <extra key="branch">default</extra>
412 <extra key="branch">default</extra>
413 </logentry>
413 </logentry>
414 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
414 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
415 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
415 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
416 <parent revision="-1" node="0000000000000000000000000000000000000000" />
416 <parent revision="-1" node="0000000000000000000000000000000000000000" />
417 <author email="other@place">A. N. Other</author>
417 <author email="other@place">A. N. Other</author>
418 <date>1970-01-13T17:33:20+00:00</date>
418 <date>1970-01-13T17:33:20+00:00</date>
419 <msg xml:space="preserve">other 1
419 <msg xml:space="preserve">other 1
420 other 2
420 other 2
421
421
422 other 3</msg>
422 other 3</msg>
423 <paths>
423 <paths>
424 <path action="A">b</path>
424 <path action="A">b</path>
425 </paths>
425 </paths>
426 <extra key="branch">default</extra>
426 <extra key="branch">default</extra>
427 </logentry>
427 </logentry>
428 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
428 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
429 <parent revision="-1" node="0000000000000000000000000000000000000000" />
429 <parent revision="-1" node="0000000000000000000000000000000000000000" />
430 <parent revision="-1" node="0000000000000000000000000000000000000000" />
430 <parent revision="-1" node="0000000000000000000000000000000000000000" />
431 <author email="user@hostname">User Name</author>
431 <author email="user@hostname">User Name</author>
432 <date>1970-01-12T13:46:40+00:00</date>
432 <date>1970-01-12T13:46:40+00:00</date>
433 <msg xml:space="preserve">line 1
433 <msg xml:space="preserve">line 1
434 line 2</msg>
434 line 2</msg>
435 <paths>
435 <paths>
436 <path action="A">a</path>
436 <path action="A">a</path>
437 </paths>
437 </paths>
438 <extra key="branch">default</extra>
438 <extra key="branch">default</extra>
439 </logentry>
439 </logentry>
440 </log>
440 </log>
441
441
442
442
443 Error if style not readable:
443 Error if style not readable:
444
444
445 #if unix-permissions
445 #if unix-permissions
446 $ touch q
446 $ touch q
447 $ chmod 0 q
447 $ chmod 0 q
448 $ hg log --style ./q
448 $ hg log --style ./q
449 abort: Permission denied: ./q
449 abort: Permission denied: ./q
450 [255]
450 [255]
451 #endif
451 #endif
452
452
453 Error if no style:
453 Error if no style:
454
454
455 $ hg log --style notexist
455 $ hg log --style notexist
456 abort: style not found: notexist
456 abort: style not found: notexist
457 [255]
457 [255]
458
458
459 Error if style missing key:
459 Error if style missing key:
460
460
461 $ echo 'q = q' > t
461 $ echo 'q = q' > t
462 $ hg log --style ./t
462 $ hg log --style ./t
463 abort: "changeset" not in template map
463 abort: "changeset" not in template map
464 [255]
464 [255]
465
465
466 Error if style missing value:
466 Error if style missing value:
467
467
468 $ echo 'changeset =' > t
468 $ echo 'changeset =' > t
469 $ hg log --style t
469 $ hg log --style t
470 abort: t:1: missing value
470 abort: t:1: missing value
471 [255]
471 [255]
472
472
473 Error if include fails:
473 Error if include fails:
474
474
475 $ echo 'changeset = q' >> t
475 $ echo 'changeset = q' >> t
476 #if unix-permissions
476 #if unix-permissions
477 $ hg log --style ./t
477 $ hg log --style ./t
478 abort: template file ./q: Permission denied
478 abort: template file ./q: Permission denied
479 [255]
479 [255]
480 $ rm q
480 $ rm q
481 #endif
481 #endif
482
482
483 Include works:
483 Include works:
484
484
485 $ echo '{rev}' > q
485 $ echo '{rev}' > q
486 $ hg log --style ./t
486 $ hg log --style ./t
487 8
487 8
488 7
488 7
489 6
489 6
490 5
490 5
491 4
491 4
492 3
492 3
493 2
493 2
494 1
494 1
495 0
495 0
496
496
497 ui.style works:
497 ui.style works:
498
498
499 $ echo '[ui]' > .hg/hgrc
499 $ echo '[ui]' > .hg/hgrc
500 $ echo 'style = t' >> .hg/hgrc
500 $ echo 'style = t' >> .hg/hgrc
501 $ hg log
501 $ hg log
502 8
502 8
503 7
503 7
504 6
504 6
505 5
505 5
506 4
506 4
507 3
507 3
508 2
508 2
509 1
509 1
510 0
510 0
511
511
512
512
513 Issue338:
513 Issue338:
514
514
515 $ hg log --style=changelog > changelog
515 $ hg log --style=changelog > changelog
516
516
517 $ cat changelog
517 $ cat changelog
518 2020-01-01 test <test>
518 2020-01-01 test <test>
519
519
520 * fourth, second, third:
520 * fourth, second, third:
521 third
521 third
522 [95c24699272e] [tip]
522 [95c24699272e] [tip]
523
523
524 1970-01-12 User Name <user@hostname>
524 1970-01-12 User Name <user@hostname>
525
525
526 * second:
526 * second:
527 second
527 second
528 [29114dbae42b]
528 [29114dbae42b]
529
529
530 1970-01-18 person <person>
530 1970-01-18 person <person>
531
531
532 * merge
532 * merge
533 [d41e714fe50d]
533 [d41e714fe50d]
534
534
535 * d:
535 * d:
536 new head
536 new head
537 [13207e5a10d9]
537 [13207e5a10d9]
538
538
539 1970-01-17 person <person>
539 1970-01-17 person <person>
540
540
541 * new branch
541 * new branch
542 [bbe44766e73d] <foo>
542 [bbe44766e73d] <foo>
543
543
544 1970-01-16 person <person>
544 1970-01-16 person <person>
545
545
546 * c:
546 * c:
547 no user, no domain
547 no user, no domain
548 [10e46f2dcbf4]
548 [10e46f2dcbf4]
549
549
550 1970-01-14 other <other@place>
550 1970-01-14 other <other@place>
551
551
552 * c:
552 * c:
553 no person
553 no person
554 [97054abb4ab8]
554 [97054abb4ab8]
555
555
556 1970-01-13 A. N. Other <other@place>
556 1970-01-13 A. N. Other <other@place>
557
557
558 * b:
558 * b:
559 other 1 other 2
559 other 1 other 2
560
560
561 other 3
561 other 3
562 [b608e9d1a3f0]
562 [b608e9d1a3f0]
563
563
564 1970-01-12 User Name <user@hostname>
564 1970-01-12 User Name <user@hostname>
565
565
566 * a:
566 * a:
567 line 1 line 2
567 line 1 line 2
568 [1e4e1b8f71e0]
568 [1e4e1b8f71e0]
569
569
570
570
571 Issue2130: xml output for 'hg heads' is malformed
571 Issue2130: xml output for 'hg heads' is malformed
572
572
573 $ hg heads --style changelog
573 $ hg heads --style changelog
574 2020-01-01 test <test>
574 2020-01-01 test <test>
575
575
576 * fourth, second, third:
576 * fourth, second, third:
577 third
577 third
578 [95c24699272e] [tip]
578 [95c24699272e] [tip]
579
579
580 1970-01-18 person <person>
580 1970-01-18 person <person>
581
581
582 * merge
582 * merge
583 [d41e714fe50d]
583 [d41e714fe50d]
584
584
585 1970-01-17 person <person>
585 1970-01-17 person <person>
586
586
587 * new branch
587 * new branch
588 [bbe44766e73d] <foo>
588 [bbe44766e73d] <foo>
589
589
590
590
591 Keys work:
591 Keys work:
592
592
593 $ for key in author branch branches date desc file_adds file_dels file_mods \
593 $ for key in author branch branches date desc file_adds file_dels file_mods \
594 > file_copies file_copies_switch files \
594 > file_copies file_copies_switch files \
595 > manifest node parents rev tags diffstat extras \
595 > manifest node parents rev tags diffstat extras \
596 > p1rev p2rev p1node p2node; do
596 > p1rev p2rev p1node p2node; do
597 > for mode in '' --verbose --debug; do
597 > for mode in '' --verbose --debug; do
598 > hg log $mode --template "$key$mode: {$key}\n"
598 > hg log $mode --template "$key$mode: {$key}\n"
599 > done
599 > done
600 > done
600 > done
601 author: test
601 author: test
602 author: User Name <user@hostname>
602 author: User Name <user@hostname>
603 author: person
603 author: person
604 author: person
604 author: person
605 author: person
605 author: person
606 author: person
606 author: person
607 author: other@place
607 author: other@place
608 author: A. N. Other <other@place>
608 author: A. N. Other <other@place>
609 author: User Name <user@hostname>
609 author: User Name <user@hostname>
610 author--verbose: test
610 author--verbose: test
611 author--verbose: User Name <user@hostname>
611 author--verbose: User Name <user@hostname>
612 author--verbose: person
612 author--verbose: person
613 author--verbose: person
613 author--verbose: person
614 author--verbose: person
614 author--verbose: person
615 author--verbose: person
615 author--verbose: person
616 author--verbose: other@place
616 author--verbose: other@place
617 author--verbose: A. N. Other <other@place>
617 author--verbose: A. N. Other <other@place>
618 author--verbose: User Name <user@hostname>
618 author--verbose: User Name <user@hostname>
619 author--debug: test
619 author--debug: test
620 author--debug: User Name <user@hostname>
620 author--debug: User Name <user@hostname>
621 author--debug: person
621 author--debug: person
622 author--debug: person
622 author--debug: person
623 author--debug: person
623 author--debug: person
624 author--debug: person
624 author--debug: person
625 author--debug: other@place
625 author--debug: other@place
626 author--debug: A. N. Other <other@place>
626 author--debug: A. N. Other <other@place>
627 author--debug: User Name <user@hostname>
627 author--debug: User Name <user@hostname>
628 branch: default
628 branch: default
629 branch: default
629 branch: default
630 branch: default
630 branch: default
631 branch: default
631 branch: default
632 branch: foo
632 branch: foo
633 branch: default
633 branch: default
634 branch: default
634 branch: default
635 branch: default
635 branch: default
636 branch: default
636 branch: default
637 branch--verbose: default
637 branch--verbose: default
638 branch--verbose: default
638 branch--verbose: default
639 branch--verbose: default
639 branch--verbose: default
640 branch--verbose: default
640 branch--verbose: default
641 branch--verbose: foo
641 branch--verbose: foo
642 branch--verbose: default
642 branch--verbose: default
643 branch--verbose: default
643 branch--verbose: default
644 branch--verbose: default
644 branch--verbose: default
645 branch--verbose: default
645 branch--verbose: default
646 branch--debug: default
646 branch--debug: default
647 branch--debug: default
647 branch--debug: default
648 branch--debug: default
648 branch--debug: default
649 branch--debug: default
649 branch--debug: default
650 branch--debug: foo
650 branch--debug: foo
651 branch--debug: default
651 branch--debug: default
652 branch--debug: default
652 branch--debug: default
653 branch--debug: default
653 branch--debug: default
654 branch--debug: default
654 branch--debug: default
655 branches:
655 branches:
656 branches:
656 branches:
657 branches:
657 branches:
658 branches:
658 branches:
659 branches: foo
659 branches: foo
660 branches:
660 branches:
661 branches:
661 branches:
662 branches:
662 branches:
663 branches:
663 branches:
664 branches--verbose:
664 branches--verbose:
665 branches--verbose:
665 branches--verbose:
666 branches--verbose:
666 branches--verbose:
667 branches--verbose:
667 branches--verbose:
668 branches--verbose: foo
668 branches--verbose: foo
669 branches--verbose:
669 branches--verbose:
670 branches--verbose:
670 branches--verbose:
671 branches--verbose:
671 branches--verbose:
672 branches--verbose:
672 branches--verbose:
673 branches--debug:
673 branches--debug:
674 branches--debug:
674 branches--debug:
675 branches--debug:
675 branches--debug:
676 branches--debug:
676 branches--debug:
677 branches--debug: foo
677 branches--debug: foo
678 branches--debug:
678 branches--debug:
679 branches--debug:
679 branches--debug:
680 branches--debug:
680 branches--debug:
681 branches--debug:
681 branches--debug:
682 date: 1577872860.00
682 date: 1577872860.00
683 date: 1000000.00
683 date: 1000000.00
684 date: 1500001.00
684 date: 1500001.00
685 date: 1500000.00
685 date: 1500000.00
686 date: 1400000.00
686 date: 1400000.00
687 date: 1300000.00
687 date: 1300000.00
688 date: 1200000.00
688 date: 1200000.00
689 date: 1100000.00
689 date: 1100000.00
690 date: 1000000.00
690 date: 1000000.00
691 date--verbose: 1577872860.00
691 date--verbose: 1577872860.00
692 date--verbose: 1000000.00
692 date--verbose: 1000000.00
693 date--verbose: 1500001.00
693 date--verbose: 1500001.00
694 date--verbose: 1500000.00
694 date--verbose: 1500000.00
695 date--verbose: 1400000.00
695 date--verbose: 1400000.00
696 date--verbose: 1300000.00
696 date--verbose: 1300000.00
697 date--verbose: 1200000.00
697 date--verbose: 1200000.00
698 date--verbose: 1100000.00
698 date--verbose: 1100000.00
699 date--verbose: 1000000.00
699 date--verbose: 1000000.00
700 date--debug: 1577872860.00
700 date--debug: 1577872860.00
701 date--debug: 1000000.00
701 date--debug: 1000000.00
702 date--debug: 1500001.00
702 date--debug: 1500001.00
703 date--debug: 1500000.00
703 date--debug: 1500000.00
704 date--debug: 1400000.00
704 date--debug: 1400000.00
705 date--debug: 1300000.00
705 date--debug: 1300000.00
706 date--debug: 1200000.00
706 date--debug: 1200000.00
707 date--debug: 1100000.00
707 date--debug: 1100000.00
708 date--debug: 1000000.00
708 date--debug: 1000000.00
709 desc: third
709 desc: third
710 desc: second
710 desc: second
711 desc: merge
711 desc: merge
712 desc: new head
712 desc: new head
713 desc: new branch
713 desc: new branch
714 desc: no user, no domain
714 desc: no user, no domain
715 desc: no person
715 desc: no person
716 desc: other 1
716 desc: other 1
717 other 2
717 other 2
718
718
719 other 3
719 other 3
720 desc: line 1
720 desc: line 1
721 line 2
721 line 2
722 desc--verbose: third
722 desc--verbose: third
723 desc--verbose: second
723 desc--verbose: second
724 desc--verbose: merge
724 desc--verbose: merge
725 desc--verbose: new head
725 desc--verbose: new head
726 desc--verbose: new branch
726 desc--verbose: new branch
727 desc--verbose: no user, no domain
727 desc--verbose: no user, no domain
728 desc--verbose: no person
728 desc--verbose: no person
729 desc--verbose: other 1
729 desc--verbose: other 1
730 other 2
730 other 2
731
731
732 other 3
732 other 3
733 desc--verbose: line 1
733 desc--verbose: line 1
734 line 2
734 line 2
735 desc--debug: third
735 desc--debug: third
736 desc--debug: second
736 desc--debug: second
737 desc--debug: merge
737 desc--debug: merge
738 desc--debug: new head
738 desc--debug: new head
739 desc--debug: new branch
739 desc--debug: new branch
740 desc--debug: no user, no domain
740 desc--debug: no user, no domain
741 desc--debug: no person
741 desc--debug: no person
742 desc--debug: other 1
742 desc--debug: other 1
743 other 2
743 other 2
744
744
745 other 3
745 other 3
746 desc--debug: line 1
746 desc--debug: line 1
747 line 2
747 line 2
748 file_adds: fourth third
748 file_adds: fourth third
749 file_adds: second
749 file_adds: second
750 file_adds:
750 file_adds:
751 file_adds: d
751 file_adds: d
752 file_adds:
752 file_adds:
753 file_adds:
753 file_adds:
754 file_adds: c
754 file_adds: c
755 file_adds: b
755 file_adds: b
756 file_adds: a
756 file_adds: a
757 file_adds--verbose: fourth third
757 file_adds--verbose: fourth third
758 file_adds--verbose: second
758 file_adds--verbose: second
759 file_adds--verbose:
759 file_adds--verbose:
760 file_adds--verbose: d
760 file_adds--verbose: d
761 file_adds--verbose:
761 file_adds--verbose:
762 file_adds--verbose:
762 file_adds--verbose:
763 file_adds--verbose: c
763 file_adds--verbose: c
764 file_adds--verbose: b
764 file_adds--verbose: b
765 file_adds--verbose: a
765 file_adds--verbose: a
766 file_adds--debug: fourth third
766 file_adds--debug: fourth third
767 file_adds--debug: second
767 file_adds--debug: second
768 file_adds--debug:
768 file_adds--debug:
769 file_adds--debug: d
769 file_adds--debug: d
770 file_adds--debug:
770 file_adds--debug:
771 file_adds--debug:
771 file_adds--debug:
772 file_adds--debug: c
772 file_adds--debug: c
773 file_adds--debug: b
773 file_adds--debug: b
774 file_adds--debug: a
774 file_adds--debug: a
775 file_dels: second
775 file_dels: second
776 file_dels:
776 file_dels:
777 file_dels:
777 file_dels:
778 file_dels:
778 file_dels:
779 file_dels:
779 file_dels:
780 file_dels:
780 file_dels:
781 file_dels:
781 file_dels:
782 file_dels:
782 file_dels:
783 file_dels:
783 file_dels:
784 file_dels--verbose: second
784 file_dels--verbose: second
785 file_dels--verbose:
785 file_dels--verbose:
786 file_dels--verbose:
786 file_dels--verbose:
787 file_dels--verbose:
787 file_dels--verbose:
788 file_dels--verbose:
788 file_dels--verbose:
789 file_dels--verbose:
789 file_dels--verbose:
790 file_dels--verbose:
790 file_dels--verbose:
791 file_dels--verbose:
791 file_dels--verbose:
792 file_dels--verbose:
792 file_dels--verbose:
793 file_dels--debug: second
793 file_dels--debug: second
794 file_dels--debug:
794 file_dels--debug:
795 file_dels--debug:
795 file_dels--debug:
796 file_dels--debug:
796 file_dels--debug:
797 file_dels--debug:
797 file_dels--debug:
798 file_dels--debug:
798 file_dels--debug:
799 file_dels--debug:
799 file_dels--debug:
800 file_dels--debug:
800 file_dels--debug:
801 file_dels--debug:
801 file_dels--debug:
802 file_mods:
802 file_mods:
803 file_mods:
803 file_mods:
804 file_mods:
804 file_mods:
805 file_mods:
805 file_mods:
806 file_mods:
806 file_mods:
807 file_mods: c
807 file_mods: c
808 file_mods:
808 file_mods:
809 file_mods:
809 file_mods:
810 file_mods:
810 file_mods:
811 file_mods--verbose:
811 file_mods--verbose:
812 file_mods--verbose:
812 file_mods--verbose:
813 file_mods--verbose:
813 file_mods--verbose:
814 file_mods--verbose:
814 file_mods--verbose:
815 file_mods--verbose:
815 file_mods--verbose:
816 file_mods--verbose: c
816 file_mods--verbose: c
817 file_mods--verbose:
817 file_mods--verbose:
818 file_mods--verbose:
818 file_mods--verbose:
819 file_mods--verbose:
819 file_mods--verbose:
820 file_mods--debug:
820 file_mods--debug:
821 file_mods--debug:
821 file_mods--debug:
822 file_mods--debug:
822 file_mods--debug:
823 file_mods--debug:
823 file_mods--debug:
824 file_mods--debug:
824 file_mods--debug:
825 file_mods--debug: c
825 file_mods--debug: c
826 file_mods--debug:
826 file_mods--debug:
827 file_mods--debug:
827 file_mods--debug:
828 file_mods--debug:
828 file_mods--debug:
829 file_copies: fourth (second)
829 file_copies: fourth (second)
830 file_copies:
830 file_copies:
831 file_copies:
831 file_copies:
832 file_copies:
832 file_copies:
833 file_copies:
833 file_copies:
834 file_copies:
834 file_copies:
835 file_copies:
835 file_copies:
836 file_copies:
836 file_copies:
837 file_copies:
837 file_copies:
838 file_copies--verbose: fourth (second)
838 file_copies--verbose: fourth (second)
839 file_copies--verbose:
839 file_copies--verbose:
840 file_copies--verbose:
840 file_copies--verbose:
841 file_copies--verbose:
841 file_copies--verbose:
842 file_copies--verbose:
842 file_copies--verbose:
843 file_copies--verbose:
843 file_copies--verbose:
844 file_copies--verbose:
844 file_copies--verbose:
845 file_copies--verbose:
845 file_copies--verbose:
846 file_copies--verbose:
846 file_copies--verbose:
847 file_copies--debug: fourth (second)
847 file_copies--debug: fourth (second)
848 file_copies--debug:
848 file_copies--debug:
849 file_copies--debug:
849 file_copies--debug:
850 file_copies--debug:
850 file_copies--debug:
851 file_copies--debug:
851 file_copies--debug:
852 file_copies--debug:
852 file_copies--debug:
853 file_copies--debug:
853 file_copies--debug:
854 file_copies--debug:
854 file_copies--debug:
855 file_copies--debug:
855 file_copies--debug:
856 file_copies_switch:
856 file_copies_switch:
857 file_copies_switch:
857 file_copies_switch:
858 file_copies_switch:
858 file_copies_switch:
859 file_copies_switch:
859 file_copies_switch:
860 file_copies_switch:
860 file_copies_switch:
861 file_copies_switch:
861 file_copies_switch:
862 file_copies_switch:
862 file_copies_switch:
863 file_copies_switch:
863 file_copies_switch:
864 file_copies_switch:
864 file_copies_switch:
865 file_copies_switch--verbose:
865 file_copies_switch--verbose:
866 file_copies_switch--verbose:
866 file_copies_switch--verbose:
867 file_copies_switch--verbose:
867 file_copies_switch--verbose:
868 file_copies_switch--verbose:
868 file_copies_switch--verbose:
869 file_copies_switch--verbose:
869 file_copies_switch--verbose:
870 file_copies_switch--verbose:
870 file_copies_switch--verbose:
871 file_copies_switch--verbose:
871 file_copies_switch--verbose:
872 file_copies_switch--verbose:
872 file_copies_switch--verbose:
873 file_copies_switch--verbose:
873 file_copies_switch--verbose:
874 file_copies_switch--debug:
874 file_copies_switch--debug:
875 file_copies_switch--debug:
875 file_copies_switch--debug:
876 file_copies_switch--debug:
876 file_copies_switch--debug:
877 file_copies_switch--debug:
877 file_copies_switch--debug:
878 file_copies_switch--debug:
878 file_copies_switch--debug:
879 file_copies_switch--debug:
879 file_copies_switch--debug:
880 file_copies_switch--debug:
880 file_copies_switch--debug:
881 file_copies_switch--debug:
881 file_copies_switch--debug:
882 file_copies_switch--debug:
882 file_copies_switch--debug:
883 files: fourth second third
883 files: fourth second third
884 files: second
884 files: second
885 files:
885 files:
886 files: d
886 files: d
887 files:
887 files:
888 files: c
888 files: c
889 files: c
889 files: c
890 files: b
890 files: b
891 files: a
891 files: a
892 files--verbose: fourth second third
892 files--verbose: fourth second third
893 files--verbose: second
893 files--verbose: second
894 files--verbose:
894 files--verbose:
895 files--verbose: d
895 files--verbose: d
896 files--verbose:
896 files--verbose:
897 files--verbose: c
897 files--verbose: c
898 files--verbose: c
898 files--verbose: c
899 files--verbose: b
899 files--verbose: b
900 files--verbose: a
900 files--verbose: a
901 files--debug: fourth second third
901 files--debug: fourth second third
902 files--debug: second
902 files--debug: second
903 files--debug:
903 files--debug:
904 files--debug: d
904 files--debug: d
905 files--debug:
905 files--debug:
906 files--debug: c
906 files--debug: c
907 files--debug: c
907 files--debug: c
908 files--debug: b
908 files--debug: b
909 files--debug: a
909 files--debug: a
910 manifest: 6:94961b75a2da
910 manifest: 6:94961b75a2da
911 manifest: 5:f2dbc354b94e
911 manifest: 5:f2dbc354b94e
912 manifest: 4:4dc3def4f9b4
912 manifest: 4:4dc3def4f9b4
913 manifest: 4:4dc3def4f9b4
913 manifest: 4:4dc3def4f9b4
914 manifest: 3:cb5a1327723b
914 manifest: 3:cb5a1327723b
915 manifest: 3:cb5a1327723b
915 manifest: 3:cb5a1327723b
916 manifest: 2:6e0e82995c35
916 manifest: 2:6e0e82995c35
917 manifest: 1:4e8d705b1e53
917 manifest: 1:4e8d705b1e53
918 manifest: 0:a0c8bcbbb45c
918 manifest: 0:a0c8bcbbb45c
919 manifest--verbose: 6:94961b75a2da
919 manifest--verbose: 6:94961b75a2da
920 manifest--verbose: 5:f2dbc354b94e
920 manifest--verbose: 5:f2dbc354b94e
921 manifest--verbose: 4:4dc3def4f9b4
921 manifest--verbose: 4:4dc3def4f9b4
922 manifest--verbose: 4:4dc3def4f9b4
922 manifest--verbose: 4:4dc3def4f9b4
923 manifest--verbose: 3:cb5a1327723b
923 manifest--verbose: 3:cb5a1327723b
924 manifest--verbose: 3:cb5a1327723b
924 manifest--verbose: 3:cb5a1327723b
925 manifest--verbose: 2:6e0e82995c35
925 manifest--verbose: 2:6e0e82995c35
926 manifest--verbose: 1:4e8d705b1e53
926 manifest--verbose: 1:4e8d705b1e53
927 manifest--verbose: 0:a0c8bcbbb45c
927 manifest--verbose: 0:a0c8bcbbb45c
928 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
928 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
929 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
929 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
930 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
930 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
931 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
931 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
932 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
932 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
933 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
933 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
934 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
934 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
935 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
935 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
936 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
936 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
937 node: 95c24699272ef57d062b8bccc32c878bf841784a
937 node: 95c24699272ef57d062b8bccc32c878bf841784a
938 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
938 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
939 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
939 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
940 node: 13207e5a10d9fd28ec424934298e176197f2c67f
940 node: 13207e5a10d9fd28ec424934298e176197f2c67f
941 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
941 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
942 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
942 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
943 node: 97054abb4ab824450e9164180baf491ae0078465
943 node: 97054abb4ab824450e9164180baf491ae0078465
944 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
944 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
945 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
945 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
946 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
946 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
947 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
947 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
948 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
948 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
949 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
949 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
950 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
950 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
951 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
951 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
952 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
952 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
953 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
953 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
954 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
954 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
955 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
955 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
956 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
956 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
957 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
957 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
958 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
958 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
959 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
959 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
960 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
960 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
961 node--debug: 97054abb4ab824450e9164180baf491ae0078465
961 node--debug: 97054abb4ab824450e9164180baf491ae0078465
962 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
962 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
963 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
963 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
964 parents:
964 parents:
965 parents: -1:000000000000
965 parents: -1:000000000000
966 parents: 5:13207e5a10d9 4:bbe44766e73d
966 parents: 5:13207e5a10d9 4:bbe44766e73d
967 parents: 3:10e46f2dcbf4
967 parents: 3:10e46f2dcbf4
968 parents:
968 parents:
969 parents:
969 parents:
970 parents:
970 parents:
971 parents:
971 parents:
972 parents:
972 parents:
973 parents--verbose:
973 parents--verbose:
974 parents--verbose: -1:000000000000
974 parents--verbose: -1:000000000000
975 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
975 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
976 parents--verbose: 3:10e46f2dcbf4
976 parents--verbose: 3:10e46f2dcbf4
977 parents--verbose:
977 parents--verbose:
978 parents--verbose:
978 parents--verbose:
979 parents--verbose:
979 parents--verbose:
980 parents--verbose:
980 parents--verbose:
981 parents--verbose:
981 parents--verbose:
982 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
982 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
983 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
983 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
984 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
984 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
985 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
985 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
986 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
986 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
987 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
987 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
988 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
988 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
989 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
989 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
990 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
990 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
991 rev: 8
991 rev: 8
992 rev: 7
992 rev: 7
993 rev: 6
993 rev: 6
994 rev: 5
994 rev: 5
995 rev: 4
995 rev: 4
996 rev: 3
996 rev: 3
997 rev: 2
997 rev: 2
998 rev: 1
998 rev: 1
999 rev: 0
999 rev: 0
1000 rev--verbose: 8
1000 rev--verbose: 8
1001 rev--verbose: 7
1001 rev--verbose: 7
1002 rev--verbose: 6
1002 rev--verbose: 6
1003 rev--verbose: 5
1003 rev--verbose: 5
1004 rev--verbose: 4
1004 rev--verbose: 4
1005 rev--verbose: 3
1005 rev--verbose: 3
1006 rev--verbose: 2
1006 rev--verbose: 2
1007 rev--verbose: 1
1007 rev--verbose: 1
1008 rev--verbose: 0
1008 rev--verbose: 0
1009 rev--debug: 8
1009 rev--debug: 8
1010 rev--debug: 7
1010 rev--debug: 7
1011 rev--debug: 6
1011 rev--debug: 6
1012 rev--debug: 5
1012 rev--debug: 5
1013 rev--debug: 4
1013 rev--debug: 4
1014 rev--debug: 3
1014 rev--debug: 3
1015 rev--debug: 2
1015 rev--debug: 2
1016 rev--debug: 1
1016 rev--debug: 1
1017 rev--debug: 0
1017 rev--debug: 0
1018 tags: tip
1018 tags: tip
1019 tags:
1019 tags:
1020 tags:
1020 tags:
1021 tags:
1021 tags:
1022 tags:
1022 tags:
1023 tags:
1023 tags:
1024 tags:
1024 tags:
1025 tags:
1025 tags:
1026 tags:
1026 tags:
1027 tags--verbose: tip
1027 tags--verbose: tip
1028 tags--verbose:
1028 tags--verbose:
1029 tags--verbose:
1029 tags--verbose:
1030 tags--verbose:
1030 tags--verbose:
1031 tags--verbose:
1031 tags--verbose:
1032 tags--verbose:
1032 tags--verbose:
1033 tags--verbose:
1033 tags--verbose:
1034 tags--verbose:
1034 tags--verbose:
1035 tags--verbose:
1035 tags--verbose:
1036 tags--debug: tip
1036 tags--debug: tip
1037 tags--debug:
1037 tags--debug:
1038 tags--debug:
1038 tags--debug:
1039 tags--debug:
1039 tags--debug:
1040 tags--debug:
1040 tags--debug:
1041 tags--debug:
1041 tags--debug:
1042 tags--debug:
1042 tags--debug:
1043 tags--debug:
1043 tags--debug:
1044 tags--debug:
1044 tags--debug:
1045 diffstat: 3: +2/-1
1045 diffstat: 3: +2/-1
1046 diffstat: 1: +1/-0
1046 diffstat: 1: +1/-0
1047 diffstat: 0: +0/-0
1047 diffstat: 0: +0/-0
1048 diffstat: 1: +1/-0
1048 diffstat: 1: +1/-0
1049 diffstat: 0: +0/-0
1049 diffstat: 0: +0/-0
1050 diffstat: 1: +1/-0
1050 diffstat: 1: +1/-0
1051 diffstat: 1: +4/-0
1051 diffstat: 1: +4/-0
1052 diffstat: 1: +2/-0
1052 diffstat: 1: +2/-0
1053 diffstat: 1: +1/-0
1053 diffstat: 1: +1/-0
1054 diffstat--verbose: 3: +2/-1
1054 diffstat--verbose: 3: +2/-1
1055 diffstat--verbose: 1: +1/-0
1055 diffstat--verbose: 1: +1/-0
1056 diffstat--verbose: 0: +0/-0
1056 diffstat--verbose: 0: +0/-0
1057 diffstat--verbose: 1: +1/-0
1057 diffstat--verbose: 1: +1/-0
1058 diffstat--verbose: 0: +0/-0
1058 diffstat--verbose: 0: +0/-0
1059 diffstat--verbose: 1: +1/-0
1059 diffstat--verbose: 1: +1/-0
1060 diffstat--verbose: 1: +4/-0
1060 diffstat--verbose: 1: +4/-0
1061 diffstat--verbose: 1: +2/-0
1061 diffstat--verbose: 1: +2/-0
1062 diffstat--verbose: 1: +1/-0
1062 diffstat--verbose: 1: +1/-0
1063 diffstat--debug: 3: +2/-1
1063 diffstat--debug: 3: +2/-1
1064 diffstat--debug: 1: +1/-0
1064 diffstat--debug: 1: +1/-0
1065 diffstat--debug: 0: +0/-0
1065 diffstat--debug: 0: +0/-0
1066 diffstat--debug: 1: +1/-0
1066 diffstat--debug: 1: +1/-0
1067 diffstat--debug: 0: +0/-0
1067 diffstat--debug: 0: +0/-0
1068 diffstat--debug: 1: +1/-0
1068 diffstat--debug: 1: +1/-0
1069 diffstat--debug: 1: +4/-0
1069 diffstat--debug: 1: +4/-0
1070 diffstat--debug: 1: +2/-0
1070 diffstat--debug: 1: +2/-0
1071 diffstat--debug: 1: +1/-0
1071 diffstat--debug: 1: +1/-0
1072 extras: branch=default
1072 extras: branch=default
1073 extras: branch=default
1073 extras: branch=default
1074 extras: branch=default
1074 extras: branch=default
1075 extras: branch=default
1075 extras: branch=default
1076 extras: branch=foo
1076 extras: branch=foo
1077 extras: branch=default
1077 extras: branch=default
1078 extras: branch=default
1078 extras: branch=default
1079 extras: branch=default
1079 extras: branch=default
1080 extras: branch=default
1080 extras: branch=default
1081 extras--verbose: branch=default
1081 extras--verbose: branch=default
1082 extras--verbose: branch=default
1082 extras--verbose: branch=default
1083 extras--verbose: branch=default
1083 extras--verbose: branch=default
1084 extras--verbose: branch=default
1084 extras--verbose: branch=default
1085 extras--verbose: branch=foo
1085 extras--verbose: branch=foo
1086 extras--verbose: branch=default
1086 extras--verbose: branch=default
1087 extras--verbose: branch=default
1087 extras--verbose: branch=default
1088 extras--verbose: branch=default
1088 extras--verbose: branch=default
1089 extras--verbose: branch=default
1089 extras--verbose: branch=default
1090 extras--debug: branch=default
1090 extras--debug: branch=default
1091 extras--debug: branch=default
1091 extras--debug: branch=default
1092 extras--debug: branch=default
1092 extras--debug: branch=default
1093 extras--debug: branch=default
1093 extras--debug: branch=default
1094 extras--debug: branch=foo
1094 extras--debug: branch=foo
1095 extras--debug: branch=default
1095 extras--debug: branch=default
1096 extras--debug: branch=default
1096 extras--debug: branch=default
1097 extras--debug: branch=default
1097 extras--debug: branch=default
1098 extras--debug: branch=default
1098 extras--debug: branch=default
1099 p1rev: 7
1099 p1rev: 7
1100 p1rev: -1
1100 p1rev: -1
1101 p1rev: 5
1101 p1rev: 5
1102 p1rev: 3
1102 p1rev: 3
1103 p1rev: 3
1103 p1rev: 3
1104 p1rev: 2
1104 p1rev: 2
1105 p1rev: 1
1105 p1rev: 1
1106 p1rev: 0
1106 p1rev: 0
1107 p1rev: -1
1107 p1rev: -1
1108 p1rev--verbose: 7
1108 p1rev--verbose: 7
1109 p1rev--verbose: -1
1109 p1rev--verbose: -1
1110 p1rev--verbose: 5
1110 p1rev--verbose: 5
1111 p1rev--verbose: 3
1111 p1rev--verbose: 3
1112 p1rev--verbose: 3
1112 p1rev--verbose: 3
1113 p1rev--verbose: 2
1113 p1rev--verbose: 2
1114 p1rev--verbose: 1
1114 p1rev--verbose: 1
1115 p1rev--verbose: 0
1115 p1rev--verbose: 0
1116 p1rev--verbose: -1
1116 p1rev--verbose: -1
1117 p1rev--debug: 7
1117 p1rev--debug: 7
1118 p1rev--debug: -1
1118 p1rev--debug: -1
1119 p1rev--debug: 5
1119 p1rev--debug: 5
1120 p1rev--debug: 3
1120 p1rev--debug: 3
1121 p1rev--debug: 3
1121 p1rev--debug: 3
1122 p1rev--debug: 2
1122 p1rev--debug: 2
1123 p1rev--debug: 1
1123 p1rev--debug: 1
1124 p1rev--debug: 0
1124 p1rev--debug: 0
1125 p1rev--debug: -1
1125 p1rev--debug: -1
1126 p2rev: -1
1126 p2rev: -1
1127 p2rev: -1
1127 p2rev: -1
1128 p2rev: 4
1128 p2rev: 4
1129 p2rev: -1
1129 p2rev: -1
1130 p2rev: -1
1130 p2rev: -1
1131 p2rev: -1
1131 p2rev: -1
1132 p2rev: -1
1132 p2rev: -1
1133 p2rev: -1
1133 p2rev: -1
1134 p2rev: -1
1134 p2rev: -1
1135 p2rev--verbose: -1
1135 p2rev--verbose: -1
1136 p2rev--verbose: -1
1136 p2rev--verbose: -1
1137 p2rev--verbose: 4
1137 p2rev--verbose: 4
1138 p2rev--verbose: -1
1138 p2rev--verbose: -1
1139 p2rev--verbose: -1
1139 p2rev--verbose: -1
1140 p2rev--verbose: -1
1140 p2rev--verbose: -1
1141 p2rev--verbose: -1
1141 p2rev--verbose: -1
1142 p2rev--verbose: -1
1142 p2rev--verbose: -1
1143 p2rev--verbose: -1
1143 p2rev--verbose: -1
1144 p2rev--debug: -1
1144 p2rev--debug: -1
1145 p2rev--debug: -1
1145 p2rev--debug: -1
1146 p2rev--debug: 4
1146 p2rev--debug: 4
1147 p2rev--debug: -1
1147 p2rev--debug: -1
1148 p2rev--debug: -1
1148 p2rev--debug: -1
1149 p2rev--debug: -1
1149 p2rev--debug: -1
1150 p2rev--debug: -1
1150 p2rev--debug: -1
1151 p2rev--debug: -1
1151 p2rev--debug: -1
1152 p2rev--debug: -1
1152 p2rev--debug: -1
1153 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1153 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1154 p1node: 0000000000000000000000000000000000000000
1154 p1node: 0000000000000000000000000000000000000000
1155 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1155 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1156 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1156 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1157 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1157 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1158 p1node: 97054abb4ab824450e9164180baf491ae0078465
1158 p1node: 97054abb4ab824450e9164180baf491ae0078465
1159 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1159 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1160 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1160 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1161 p1node: 0000000000000000000000000000000000000000
1161 p1node: 0000000000000000000000000000000000000000
1162 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1162 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1163 p1node--verbose: 0000000000000000000000000000000000000000
1163 p1node--verbose: 0000000000000000000000000000000000000000
1164 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1164 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1165 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1165 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1166 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1166 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1167 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1167 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1168 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1168 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1169 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1169 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1170 p1node--verbose: 0000000000000000000000000000000000000000
1170 p1node--verbose: 0000000000000000000000000000000000000000
1171 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1171 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1172 p1node--debug: 0000000000000000000000000000000000000000
1172 p1node--debug: 0000000000000000000000000000000000000000
1173 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1173 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1174 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1174 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1175 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1175 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1176 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1176 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1177 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1177 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1178 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1178 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1179 p1node--debug: 0000000000000000000000000000000000000000
1179 p1node--debug: 0000000000000000000000000000000000000000
1180 p2node: 0000000000000000000000000000000000000000
1180 p2node: 0000000000000000000000000000000000000000
1181 p2node: 0000000000000000000000000000000000000000
1181 p2node: 0000000000000000000000000000000000000000
1182 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1182 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1183 p2node: 0000000000000000000000000000000000000000
1183 p2node: 0000000000000000000000000000000000000000
1184 p2node: 0000000000000000000000000000000000000000
1184 p2node: 0000000000000000000000000000000000000000
1185 p2node: 0000000000000000000000000000000000000000
1185 p2node: 0000000000000000000000000000000000000000
1186 p2node: 0000000000000000000000000000000000000000
1186 p2node: 0000000000000000000000000000000000000000
1187 p2node: 0000000000000000000000000000000000000000
1187 p2node: 0000000000000000000000000000000000000000
1188 p2node: 0000000000000000000000000000000000000000
1188 p2node: 0000000000000000000000000000000000000000
1189 p2node--verbose: 0000000000000000000000000000000000000000
1189 p2node--verbose: 0000000000000000000000000000000000000000
1190 p2node--verbose: 0000000000000000000000000000000000000000
1190 p2node--verbose: 0000000000000000000000000000000000000000
1191 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1191 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1192 p2node--verbose: 0000000000000000000000000000000000000000
1192 p2node--verbose: 0000000000000000000000000000000000000000
1193 p2node--verbose: 0000000000000000000000000000000000000000
1193 p2node--verbose: 0000000000000000000000000000000000000000
1194 p2node--verbose: 0000000000000000000000000000000000000000
1194 p2node--verbose: 0000000000000000000000000000000000000000
1195 p2node--verbose: 0000000000000000000000000000000000000000
1195 p2node--verbose: 0000000000000000000000000000000000000000
1196 p2node--verbose: 0000000000000000000000000000000000000000
1196 p2node--verbose: 0000000000000000000000000000000000000000
1197 p2node--verbose: 0000000000000000000000000000000000000000
1197 p2node--verbose: 0000000000000000000000000000000000000000
1198 p2node--debug: 0000000000000000000000000000000000000000
1198 p2node--debug: 0000000000000000000000000000000000000000
1199 p2node--debug: 0000000000000000000000000000000000000000
1199 p2node--debug: 0000000000000000000000000000000000000000
1200 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1200 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1201 p2node--debug: 0000000000000000000000000000000000000000
1201 p2node--debug: 0000000000000000000000000000000000000000
1202 p2node--debug: 0000000000000000000000000000000000000000
1202 p2node--debug: 0000000000000000000000000000000000000000
1203 p2node--debug: 0000000000000000000000000000000000000000
1203 p2node--debug: 0000000000000000000000000000000000000000
1204 p2node--debug: 0000000000000000000000000000000000000000
1204 p2node--debug: 0000000000000000000000000000000000000000
1205 p2node--debug: 0000000000000000000000000000000000000000
1205 p2node--debug: 0000000000000000000000000000000000000000
1206 p2node--debug: 0000000000000000000000000000000000000000
1206 p2node--debug: 0000000000000000000000000000000000000000
1207
1207
1208 Filters work:
1208 Filters work:
1209
1209
1210 $ hg log --template '{author|domain}\n'
1210 $ hg log --template '{author|domain}\n'
1211
1211
1212 hostname
1212 hostname
1213
1213
1214
1214
1215
1215
1216
1216
1217 place
1217 place
1218 place
1218 place
1219 hostname
1219 hostname
1220
1220
1221 $ hg log --template '{author|person}\n'
1221 $ hg log --template '{author|person}\n'
1222 test
1222 test
1223 User Name
1223 User Name
1224 person
1224 person
1225 person
1225 person
1226 person
1226 person
1227 person
1227 person
1228 other
1228 other
1229 A. N. Other
1229 A. N. Other
1230 User Name
1230 User Name
1231
1231
1232 $ hg log --template '{author|user}\n'
1232 $ hg log --template '{author|user}\n'
1233 test
1233 test
1234 user
1234 user
1235 person
1235 person
1236 person
1236 person
1237 person
1237 person
1238 person
1238 person
1239 other
1239 other
1240 other
1240 other
1241 user
1241 user
1242
1242
1243 $ hg log --template '{date|date}\n'
1243 $ hg log --template '{date|date}\n'
1244 Wed Jan 01 10:01:00 2020 +0000
1244 Wed Jan 01 10:01:00 2020 +0000
1245 Mon Jan 12 13:46:40 1970 +0000
1245 Mon Jan 12 13:46:40 1970 +0000
1246 Sun Jan 18 08:40:01 1970 +0000
1246 Sun Jan 18 08:40:01 1970 +0000
1247 Sun Jan 18 08:40:00 1970 +0000
1247 Sun Jan 18 08:40:00 1970 +0000
1248 Sat Jan 17 04:53:20 1970 +0000
1248 Sat Jan 17 04:53:20 1970 +0000
1249 Fri Jan 16 01:06:40 1970 +0000
1249 Fri Jan 16 01:06:40 1970 +0000
1250 Wed Jan 14 21:20:00 1970 +0000
1250 Wed Jan 14 21:20:00 1970 +0000
1251 Tue Jan 13 17:33:20 1970 +0000
1251 Tue Jan 13 17:33:20 1970 +0000
1252 Mon Jan 12 13:46:40 1970 +0000
1252 Mon Jan 12 13:46:40 1970 +0000
1253
1253
1254 $ hg log --template '{date|isodate}\n'
1254 $ hg log --template '{date|isodate}\n'
1255 2020-01-01 10:01 +0000
1255 2020-01-01 10:01 +0000
1256 1970-01-12 13:46 +0000
1256 1970-01-12 13:46 +0000
1257 1970-01-18 08:40 +0000
1257 1970-01-18 08:40 +0000
1258 1970-01-18 08:40 +0000
1258 1970-01-18 08:40 +0000
1259 1970-01-17 04:53 +0000
1259 1970-01-17 04:53 +0000
1260 1970-01-16 01:06 +0000
1260 1970-01-16 01:06 +0000
1261 1970-01-14 21:20 +0000
1261 1970-01-14 21:20 +0000
1262 1970-01-13 17:33 +0000
1262 1970-01-13 17:33 +0000
1263 1970-01-12 13:46 +0000
1263 1970-01-12 13:46 +0000
1264
1264
1265 $ hg log --template '{date|isodatesec}\n'
1265 $ hg log --template '{date|isodatesec}\n'
1266 2020-01-01 10:01:00 +0000
1266 2020-01-01 10:01:00 +0000
1267 1970-01-12 13:46:40 +0000
1267 1970-01-12 13:46:40 +0000
1268 1970-01-18 08:40:01 +0000
1268 1970-01-18 08:40:01 +0000
1269 1970-01-18 08:40:00 +0000
1269 1970-01-18 08:40:00 +0000
1270 1970-01-17 04:53:20 +0000
1270 1970-01-17 04:53:20 +0000
1271 1970-01-16 01:06:40 +0000
1271 1970-01-16 01:06:40 +0000
1272 1970-01-14 21:20:00 +0000
1272 1970-01-14 21:20:00 +0000
1273 1970-01-13 17:33:20 +0000
1273 1970-01-13 17:33:20 +0000
1274 1970-01-12 13:46:40 +0000
1274 1970-01-12 13:46:40 +0000
1275
1275
1276 $ hg log --template '{date|rfc822date}\n'
1276 $ hg log --template '{date|rfc822date}\n'
1277 Wed, 01 Jan 2020 10:01:00 +0000
1277 Wed, 01 Jan 2020 10:01:00 +0000
1278 Mon, 12 Jan 1970 13:46:40 +0000
1278 Mon, 12 Jan 1970 13:46:40 +0000
1279 Sun, 18 Jan 1970 08:40:01 +0000
1279 Sun, 18 Jan 1970 08:40:01 +0000
1280 Sun, 18 Jan 1970 08:40:00 +0000
1280 Sun, 18 Jan 1970 08:40:00 +0000
1281 Sat, 17 Jan 1970 04:53:20 +0000
1281 Sat, 17 Jan 1970 04:53:20 +0000
1282 Fri, 16 Jan 1970 01:06:40 +0000
1282 Fri, 16 Jan 1970 01:06:40 +0000
1283 Wed, 14 Jan 1970 21:20:00 +0000
1283 Wed, 14 Jan 1970 21:20:00 +0000
1284 Tue, 13 Jan 1970 17:33:20 +0000
1284 Tue, 13 Jan 1970 17:33:20 +0000
1285 Mon, 12 Jan 1970 13:46:40 +0000
1285 Mon, 12 Jan 1970 13:46:40 +0000
1286
1286
1287 $ hg log --template '{desc|firstline}\n'
1287 $ hg log --template '{desc|firstline}\n'
1288 third
1288 third
1289 second
1289 second
1290 merge
1290 merge
1291 new head
1291 new head
1292 new branch
1292 new branch
1293 no user, no domain
1293 no user, no domain
1294 no person
1294 no person
1295 other 1
1295 other 1
1296 line 1
1296 line 1
1297
1297
1298 $ hg log --template '{node|short}\n'
1298 $ hg log --template '{node|short}\n'
1299 95c24699272e
1299 95c24699272e
1300 29114dbae42b
1300 29114dbae42b
1301 d41e714fe50d
1301 d41e714fe50d
1302 13207e5a10d9
1302 13207e5a10d9
1303 bbe44766e73d
1303 bbe44766e73d
1304 10e46f2dcbf4
1304 10e46f2dcbf4
1305 97054abb4ab8
1305 97054abb4ab8
1306 b608e9d1a3f0
1306 b608e9d1a3f0
1307 1e4e1b8f71e0
1307 1e4e1b8f71e0
1308
1308
1309 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1309 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1310 <changeset author="test"/>
1310 <changeset author="test"/>
1311 <changeset author="User Name &lt;user@hostname&gt;"/>
1311 <changeset author="User Name &lt;user@hostname&gt;"/>
1312 <changeset author="person"/>
1312 <changeset author="person"/>
1313 <changeset author="person"/>
1313 <changeset author="person"/>
1314 <changeset author="person"/>
1314 <changeset author="person"/>
1315 <changeset author="person"/>
1315 <changeset author="person"/>
1316 <changeset author="other@place"/>
1316 <changeset author="other@place"/>
1317 <changeset author="A. N. Other &lt;other@place&gt;"/>
1317 <changeset author="A. N. Other &lt;other@place&gt;"/>
1318 <changeset author="User Name &lt;user@hostname&gt;"/>
1318 <changeset author="User Name &lt;user@hostname&gt;"/>
1319
1319
1320 $ hg log --template '{rev}: {children}\n'
1320 $ hg log --template '{rev}: {children}\n'
1321 8:
1321 8:
1322 7: 8:95c24699272e
1322 7: 8:95c24699272e
1323 6:
1323 6:
1324 5: 6:d41e714fe50d
1324 5: 6:d41e714fe50d
1325 4: 6:d41e714fe50d
1325 4: 6:d41e714fe50d
1326 3: 4:bbe44766e73d 5:13207e5a10d9
1326 3: 4:bbe44766e73d 5:13207e5a10d9
1327 2: 3:10e46f2dcbf4
1327 2: 3:10e46f2dcbf4
1328 1: 2:97054abb4ab8
1328 1: 2:97054abb4ab8
1329 0: 1:b608e9d1a3f0
1329 0: 1:b608e9d1a3f0
1330
1330
1331 Formatnode filter works:
1331 Formatnode filter works:
1332
1332
1333 $ hg -q log -r 0 --template '{node|formatnode}\n'
1333 $ hg -q log -r 0 --template '{node|formatnode}\n'
1334 1e4e1b8f71e0
1334 1e4e1b8f71e0
1335
1335
1336 $ hg log -r 0 --template '{node|formatnode}\n'
1336 $ hg log -r 0 --template '{node|formatnode}\n'
1337 1e4e1b8f71e0
1337 1e4e1b8f71e0
1338
1338
1339 $ hg -v log -r 0 --template '{node|formatnode}\n'
1339 $ hg -v log -r 0 --template '{node|formatnode}\n'
1340 1e4e1b8f71e0
1340 1e4e1b8f71e0
1341
1341
1342 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1342 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1343 1e4e1b8f71e05681d422154f5421e385fec3454f
1343 1e4e1b8f71e05681d422154f5421e385fec3454f
1344
1344
1345 Age filter:
1345 Age filter:
1346
1346
1347 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1347 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1348
1348
1349 >>> from datetime import datetime
1349 >>> from datetime import datetime
1350 >>> fp = open('a', 'w')
1350 >>> fp = open('a', 'w')
1351 >>> fp.write(str(datetime.now().year + 8) + '-01-01 00:00')
1351 >>> fp.write(str(datetime.now().year + 8) + '-01-01 00:00')
1352 >>> fp.close()
1352 >>> fp.close()
1353 $ hg add a
1353 $ hg add a
1354 $ hg commit -m future -d "`cat a`"
1354 $ hg commit -m future -d "`cat a`"
1355
1355
1356 $ hg log -l1 --template '{date|age}\n'
1356 $ hg log -l1 --template '{date|age}\n'
1357 7 years from now
1357 7 years from now
1358
1358
1359 Error on syntax:
1359 Error on syntax:
1360
1360
1361 $ echo 'x = "f' >> t
1361 $ echo 'x = "f' >> t
1362 $ hg log
1362 $ hg log
1363 abort: t:3: unmatched quotes
1363 abort: t:3: unmatched quotes
1364 [255]
1364 [255]
1365
1365
1366 Behind the scenes, this will throw TypeError
1366 Behind the scenes, this will throw TypeError
1367
1367
1368 $ hg log -l 3 --template '{date|obfuscate}\n'
1368 $ hg log -l 3 --template '{date|obfuscate}\n'
1369 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1369 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1370 [255]
1370 [255]
1371
1371
1372 Behind the scenes, this will throw a ValueError
1372 Behind the scenes, this will throw a ValueError
1373
1373
1374 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1374 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1375 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1375 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1376 [255]
1376 [255]
1377
1377
1378 Behind the scenes, this will throw AttributeError
1378 Behind the scenes, this will throw AttributeError
1379
1379
1380 $ hg log -l 3 --template 'line: {date|escape}\n'
1380 $ hg log -l 3 --template 'line: {date|escape}\n'
1381 abort: template filter 'escape' is not compatible with keyword 'date'
1381 abort: template filter 'escape' is not compatible with keyword 'date'
1382 [255]
1382 [255]
1383
1383
1384 Behind the scenes, this will throw ValueError
1384 Behind the scenes, this will throw ValueError
1385
1385
1386 $ hg tip --template '{author|email|date}\n'
1386 $ hg tip --template '{author|email|date}\n'
1387 abort: template filter 'datefilter' is not compatible with keyword 'author'
1387 abort: template filter 'datefilter' is not compatible with keyword 'author'
1388 [255]
1388 [255]
1389
1389
1390 $ cd ..
1390 $ cd ..
1391
1391
1392
1392
1393 latesttag:
1393 latesttag:
1394
1394
1395 $ hg init latesttag
1395 $ hg init latesttag
1396 $ cd latesttag
1396 $ cd latesttag
1397
1397
1398 $ echo a > file
1398 $ echo a > file
1399 $ hg ci -Am a -d '0 0'
1399 $ hg ci -Am a -d '0 0'
1400 adding file
1400 adding file
1401
1401
1402 $ echo b >> file
1402 $ echo b >> file
1403 $ hg ci -m b -d '1 0'
1403 $ hg ci -m b -d '1 0'
1404
1404
1405 $ echo c >> head1
1405 $ echo c >> head1
1406 $ hg ci -Am h1c -d '2 0'
1406 $ hg ci -Am h1c -d '2 0'
1407 adding head1
1407 adding head1
1408
1408
1409 $ hg update -q 1
1409 $ hg update -q 1
1410 $ echo d >> head2
1410 $ echo d >> head2
1411 $ hg ci -Am h2d -d '3 0'
1411 $ hg ci -Am h2d -d '3 0'
1412 adding head2
1412 adding head2
1413 created new head
1413 created new head
1414
1414
1415 $ echo e >> head2
1415 $ echo e >> head2
1416 $ hg ci -m h2e -d '4 0'
1416 $ hg ci -m h2e -d '4 0'
1417
1417
1418 $ hg merge -q
1418 $ hg merge -q
1419 $ hg ci -m merge -d '5 0'
1419 $ hg ci -m merge -d '5 0'
1420
1420
1421 No tag set:
1421 No tag set:
1422
1422
1423 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1423 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1424 5: null+5
1424 5: null+5
1425 4: null+4
1425 4: null+4
1426 3: null+3
1426 3: null+3
1427 2: null+3
1427 2: null+3
1428 1: null+2
1428 1: null+2
1429 0: null+1
1429 0: null+1
1430
1430
1431 One common tag: longuest path wins:
1431 One common tag: longuest path wins:
1432
1432
1433 $ hg tag -r 1 -m t1 -d '6 0' t1
1433 $ hg tag -r 1 -m t1 -d '6 0' t1
1434 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1434 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1435 6: t1+4
1435 6: t1+4
1436 5: t1+3
1436 5: t1+3
1437 4: t1+2
1437 4: t1+2
1438 3: t1+1
1438 3: t1+1
1439 2: t1+1
1439 2: t1+1
1440 1: t1+0
1440 1: t1+0
1441 0: null+1
1441 0: null+1
1442
1442
1443 One ancestor tag: more recent wins:
1443 One ancestor tag: more recent wins:
1444
1444
1445 $ hg tag -r 2 -m t2 -d '7 0' t2
1445 $ hg tag -r 2 -m t2 -d '7 0' t2
1446 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1446 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1447 7: t2+3
1447 7: t2+3
1448 6: t2+2
1448 6: t2+2
1449 5: t2+1
1449 5: t2+1
1450 4: t1+2
1450 4: t1+2
1451 3: t1+1
1451 3: t1+1
1452 2: t2+0
1452 2: t2+0
1453 1: t1+0
1453 1: t1+0
1454 0: null+1
1454 0: null+1
1455
1455
1456 Two branch tags: more recent wins:
1456 Two branch tags: more recent wins:
1457
1457
1458 $ hg tag -r 3 -m t3 -d '8 0' t3
1458 $ hg tag -r 3 -m t3 -d '8 0' t3
1459 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1459 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1460 8: t3+5
1460 8: t3+5
1461 7: t3+4
1461 7: t3+4
1462 6: t3+3
1462 6: t3+3
1463 5: t3+2
1463 5: t3+2
1464 4: t3+1
1464 4: t3+1
1465 3: t3+0
1465 3: t3+0
1466 2: t2+0
1466 2: t2+0
1467 1: t1+0
1467 1: t1+0
1468 0: null+1
1468 0: null+1
1469
1469
1470 Merged tag overrides:
1470 Merged tag overrides:
1471
1471
1472 $ hg tag -r 5 -m t5 -d '9 0' t5
1472 $ hg tag -r 5 -m t5 -d '9 0' t5
1473 $ hg tag -r 3 -m at3 -d '10 0' at3
1473 $ hg tag -r 3 -m at3 -d '10 0' at3
1474 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1474 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1475 10: t5+5
1475 10: t5+5
1476 9: t5+4
1476 9: t5+4
1477 8: t5+3
1477 8: t5+3
1478 7: t5+2
1478 7: t5+2
1479 6: t5+1
1479 6: t5+1
1480 5: t5+0
1480 5: t5+0
1481 4: at3:t3+1
1481 4: at3:t3+1
1482 3: at3:t3+0
1482 3: at3:t3+0
1483 2: t2+0
1483 2: t2+0
1484 1: t1+0
1484 1: t1+0
1485 0: null+1
1485 0: null+1
1486
1486
1487 $ cd ..
1487 $ cd ..
1488
1488
1489
1489
1490 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1490 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1491 if it is a relative path
1491 if it is a relative path
1492
1492
1493 $ mkdir -p home/styles
1493 $ mkdir -p home/styles
1494
1494
1495 $ cat > home/styles/teststyle <<EOF
1495 $ cat > home/styles/teststyle <<EOF
1496 > changeset = 'test {rev}:{node|short}\n'
1496 > changeset = 'test {rev}:{node|short}\n'
1497 > EOF
1497 > EOF
1498
1498
1499 $ HOME=`pwd`/home; export HOME
1499 $ HOME=`pwd`/home; export HOME
1500
1500
1501 $ cat > latesttag/.hg/hgrc <<EOF
1501 $ cat > latesttag/.hg/hgrc <<EOF
1502 > [ui]
1502 > [ui]
1503 > style = ~/styles/teststyle
1503 > style = ~/styles/teststyle
1504 > EOF
1504 > EOF
1505
1505
1506 $ hg -R latesttag tip
1506 $ hg -R latesttag tip
1507 test 10:dee8f28249af
1507 test 10:dee8f28249af
1508
1508
1509 Test recursive showlist template (issue1989):
1509 Test recursive showlist template (issue1989):
1510
1510
1511 $ cat > style1989 <<EOF
1511 $ cat > style1989 <<EOF
1512 > changeset = '{file_mods}{manifest}{extras}'
1512 > changeset = '{file_mods}{manifest}{extras}'
1513 > file_mod = 'M|{author|person}\n'
1513 > file_mod = 'M|{author|person}\n'
1514 > manifest = '{rev},{author}\n'
1514 > manifest = '{rev},{author}\n'
1515 > extra = '{key}: {author}\n'
1515 > extra = '{key}: {author}\n'
1516 > EOF
1516 > EOF
1517
1517
1518 $ hg -R latesttag log -r tip --style=style1989
1518 $ hg -R latesttag log -r tip --style=style1989
1519 M|test
1519 M|test
1520 10,test
1520 10,test
1521 branch: test
1521 branch: test
1522
1522
1523 Test new-style inline templating:
1524
1525 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
1526 modified files: .hgtags
1527
General Comments 0
You need to be logged in to leave comments. Login now