##// END OF EJS Templates
log: populate keywords if specified in custom -Tjson(...) or -Tcbor(...)...
Yuya Nishihara -
r43372:829088e8 default
parent child Browse files
Show More
@@ -1,1064 +1,1071 b''
1 # logcmdutil.py - utility for log-like commands
1 # logcmdutil.py - utility for log-like commands
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import itertools
10 import itertools
11 import os
11 import os
12 import posixpath
12 import posixpath
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 nullid,
16 nullid,
17 wdirid,
17 wdirid,
18 wdirrev,
18 wdirrev,
19 )
19 )
20
20
21 from . import (
21 from . import (
22 dagop,
22 dagop,
23 error,
23 error,
24 formatter,
24 formatter,
25 graphmod,
25 graphmod,
26 match as matchmod,
26 match as matchmod,
27 mdiff,
27 mdiff,
28 patch,
28 patch,
29 pathutil,
29 pathutil,
30 pycompat,
30 pycompat,
31 revset,
31 revset,
32 revsetlang,
32 revsetlang,
33 scmutil,
33 scmutil,
34 smartset,
34 smartset,
35 templatekw,
35 templatekw,
36 templater,
36 templater,
37 util,
37 util,
38 )
38 )
39 from .utils import (
39 from .utils import (
40 dateutil,
40 dateutil,
41 stringutil,
41 stringutil,
42 )
42 )
43
43
44
44
45 def getlimit(opts):
45 def getlimit(opts):
46 """get the log limit according to option -l/--limit"""
46 """get the log limit according to option -l/--limit"""
47 limit = opts.get(b'limit')
47 limit = opts.get(b'limit')
48 if limit:
48 if limit:
49 try:
49 try:
50 limit = int(limit)
50 limit = int(limit)
51 except ValueError:
51 except ValueError:
52 raise error.Abort(_(b'limit must be a positive integer'))
52 raise error.Abort(_(b'limit must be a positive integer'))
53 if limit <= 0:
53 if limit <= 0:
54 raise error.Abort(_(b'limit must be positive'))
54 raise error.Abort(_(b'limit must be positive'))
55 else:
55 else:
56 limit = None
56 limit = None
57 return limit
57 return limit
58
58
59
59
60 def diffordiffstat(
60 def diffordiffstat(
61 ui,
61 ui,
62 repo,
62 repo,
63 diffopts,
63 diffopts,
64 node1,
64 node1,
65 node2,
65 node2,
66 match,
66 match,
67 changes=None,
67 changes=None,
68 stat=False,
68 stat=False,
69 fp=None,
69 fp=None,
70 graphwidth=0,
70 graphwidth=0,
71 prefix=b'',
71 prefix=b'',
72 root=b'',
72 root=b'',
73 listsubrepos=False,
73 listsubrepos=False,
74 hunksfilterfn=None,
74 hunksfilterfn=None,
75 ):
75 ):
76 '''show diff or diffstat.'''
76 '''show diff or diffstat.'''
77 ctx1 = repo[node1]
77 ctx1 = repo[node1]
78 ctx2 = repo[node2]
78 ctx2 = repo[node2]
79 if root:
79 if root:
80 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
80 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
81 else:
81 else:
82 relroot = b''
82 relroot = b''
83 copysourcematch = None
83 copysourcematch = None
84
84
85 def compose(f, g):
85 def compose(f, g):
86 return lambda x: f(g(x))
86 return lambda x: f(g(x))
87
87
88 def pathfn(f):
88 def pathfn(f):
89 return posixpath.join(prefix, f)
89 return posixpath.join(prefix, f)
90
90
91 if relroot != b'':
91 if relroot != b'':
92 # XXX relative roots currently don't work if the root is within a
92 # XXX relative roots currently don't work if the root is within a
93 # subrepo
93 # subrepo
94 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
94 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
95 uirelroot = uipathfn(pathfn(relroot))
95 uirelroot = uipathfn(pathfn(relroot))
96 relroot += b'/'
96 relroot += b'/'
97 for matchroot in match.files():
97 for matchroot in match.files():
98 if not matchroot.startswith(relroot):
98 if not matchroot.startswith(relroot):
99 ui.warn(
99 ui.warn(
100 _(b'warning: %s not inside relative root %s\n')
100 _(b'warning: %s not inside relative root %s\n')
101 % (uipathfn(pathfn(matchroot)), uirelroot)
101 % (uipathfn(pathfn(matchroot)), uirelroot)
102 )
102 )
103
103
104 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path')
104 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path')
105 match = matchmod.intersectmatchers(match, relrootmatch)
105 match = matchmod.intersectmatchers(match, relrootmatch)
106 copysourcematch = relrootmatch
106 copysourcematch = relrootmatch
107
107
108 checkroot = repo.ui.configbool(
108 checkroot = repo.ui.configbool(
109 b'devel', b'all-warnings'
109 b'devel', b'all-warnings'
110 ) or repo.ui.configbool(b'devel', b'check-relroot')
110 ) or repo.ui.configbool(b'devel', b'check-relroot')
111
111
112 def relrootpathfn(f):
112 def relrootpathfn(f):
113 if checkroot and not f.startswith(relroot):
113 if checkroot and not f.startswith(relroot):
114 raise AssertionError(
114 raise AssertionError(
115 b"file %s doesn't start with relroot %s" % (f, relroot)
115 b"file %s doesn't start with relroot %s" % (f, relroot)
116 )
116 )
117 return f[len(relroot) :]
117 return f[len(relroot) :]
118
118
119 pathfn = compose(relrootpathfn, pathfn)
119 pathfn = compose(relrootpathfn, pathfn)
120
120
121 if stat:
121 if stat:
122 diffopts = diffopts.copy(context=0, noprefix=False)
122 diffopts = diffopts.copy(context=0, noprefix=False)
123 width = 80
123 width = 80
124 if not ui.plain():
124 if not ui.plain():
125 width = ui.termwidth() - graphwidth
125 width = ui.termwidth() - graphwidth
126 # If an explicit --root was given, don't respect ui.relative-paths
126 # If an explicit --root was given, don't respect ui.relative-paths
127 if not relroot:
127 if not relroot:
128 pathfn = compose(scmutil.getuipathfn(repo), pathfn)
128 pathfn = compose(scmutil.getuipathfn(repo), pathfn)
129
129
130 chunks = ctx2.diff(
130 chunks = ctx2.diff(
131 ctx1,
131 ctx1,
132 match,
132 match,
133 changes,
133 changes,
134 opts=diffopts,
134 opts=diffopts,
135 pathfn=pathfn,
135 pathfn=pathfn,
136 copysourcematch=copysourcematch,
136 copysourcematch=copysourcematch,
137 hunksfilterfn=hunksfilterfn,
137 hunksfilterfn=hunksfilterfn,
138 )
138 )
139
139
140 if fp is not None or ui.canwritewithoutlabels():
140 if fp is not None or ui.canwritewithoutlabels():
141 out = fp or ui
141 out = fp or ui
142 if stat:
142 if stat:
143 chunks = [patch.diffstat(util.iterlines(chunks), width=width)]
143 chunks = [patch.diffstat(util.iterlines(chunks), width=width)]
144 for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
144 for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
145 out.write(chunk)
145 out.write(chunk)
146 else:
146 else:
147 if stat:
147 if stat:
148 chunks = patch.diffstatui(util.iterlines(chunks), width=width)
148 chunks = patch.diffstatui(util.iterlines(chunks), width=width)
149 else:
149 else:
150 chunks = patch.difflabel(
150 chunks = patch.difflabel(
151 lambda chunks, **kwargs: chunks, chunks, opts=diffopts
151 lambda chunks, **kwargs: chunks, chunks, opts=diffopts
152 )
152 )
153 if ui.canbatchlabeledwrites():
153 if ui.canbatchlabeledwrites():
154
154
155 def gen():
155 def gen():
156 for chunk, label in chunks:
156 for chunk, label in chunks:
157 yield ui.label(chunk, label=label)
157 yield ui.label(chunk, label=label)
158
158
159 for chunk in util.filechunkiter(util.chunkbuffer(gen())):
159 for chunk in util.filechunkiter(util.chunkbuffer(gen())):
160 ui.write(chunk)
160 ui.write(chunk)
161 else:
161 else:
162 for chunk, label in chunks:
162 for chunk, label in chunks:
163 ui.write(chunk, label=label)
163 ui.write(chunk, label=label)
164
164
165 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
165 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
166 tempnode2 = node2
166 tempnode2 = node2
167 try:
167 try:
168 if node2 is not None:
168 if node2 is not None:
169 tempnode2 = ctx2.substate[subpath][1]
169 tempnode2 = ctx2.substate[subpath][1]
170 except KeyError:
170 except KeyError:
171 # A subrepo that existed in node1 was deleted between node1 and
171 # A subrepo that existed in node1 was deleted between node1 and
172 # node2 (inclusive). Thus, ctx2's substate won't contain that
172 # node2 (inclusive). Thus, ctx2's substate won't contain that
173 # subpath. The best we can do is to ignore it.
173 # subpath. The best we can do is to ignore it.
174 tempnode2 = None
174 tempnode2 = None
175 submatch = matchmod.subdirmatcher(subpath, match)
175 submatch = matchmod.subdirmatcher(subpath, match)
176 subprefix = repo.wvfs.reljoin(prefix, subpath)
176 subprefix = repo.wvfs.reljoin(prefix, subpath)
177 if listsubrepos or match.exact(subpath) or any(submatch.files()):
177 if listsubrepos or match.exact(subpath) or any(submatch.files()):
178 sub.diff(
178 sub.diff(
179 ui,
179 ui,
180 diffopts,
180 diffopts,
181 tempnode2,
181 tempnode2,
182 submatch,
182 submatch,
183 changes=changes,
183 changes=changes,
184 stat=stat,
184 stat=stat,
185 fp=fp,
185 fp=fp,
186 prefix=subprefix,
186 prefix=subprefix,
187 )
187 )
188
188
189
189
190 class changesetdiffer(object):
190 class changesetdiffer(object):
191 """Generate diff of changeset with pre-configured filtering functions"""
191 """Generate diff of changeset with pre-configured filtering functions"""
192
192
193 def _makefilematcher(self, ctx):
193 def _makefilematcher(self, ctx):
194 return scmutil.matchall(ctx.repo())
194 return scmutil.matchall(ctx.repo())
195
195
196 def _makehunksfilter(self, ctx):
196 def _makehunksfilter(self, ctx):
197 return None
197 return None
198
198
199 def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
199 def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
200 repo = ctx.repo()
200 repo = ctx.repo()
201 node = ctx.node()
201 node = ctx.node()
202 prev = ctx.p1().node()
202 prev = ctx.p1().node()
203 diffordiffstat(
203 diffordiffstat(
204 ui,
204 ui,
205 repo,
205 repo,
206 diffopts,
206 diffopts,
207 prev,
207 prev,
208 node,
208 node,
209 match=self._makefilematcher(ctx),
209 match=self._makefilematcher(ctx),
210 stat=stat,
210 stat=stat,
211 graphwidth=graphwidth,
211 graphwidth=graphwidth,
212 hunksfilterfn=self._makehunksfilter(ctx),
212 hunksfilterfn=self._makehunksfilter(ctx),
213 )
213 )
214
214
215
215
216 def changesetlabels(ctx):
216 def changesetlabels(ctx):
217 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()]
217 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()]
218 if ctx.obsolete():
218 if ctx.obsolete():
219 labels.append(b'changeset.obsolete')
219 labels.append(b'changeset.obsolete')
220 if ctx.isunstable():
220 if ctx.isunstable():
221 labels.append(b'changeset.unstable')
221 labels.append(b'changeset.unstable')
222 for instability in ctx.instabilities():
222 for instability in ctx.instabilities():
223 labels.append(b'instability.%s' % instability)
223 labels.append(b'instability.%s' % instability)
224 return b' '.join(labels)
224 return b' '.join(labels)
225
225
226
226
227 class changesetprinter(object):
227 class changesetprinter(object):
228 '''show changeset information when templating not requested.'''
228 '''show changeset information when templating not requested.'''
229
229
230 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
230 def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
231 self.ui = ui
231 self.ui = ui
232 self.repo = repo
232 self.repo = repo
233 self.buffered = buffered
233 self.buffered = buffered
234 self._differ = differ or changesetdiffer()
234 self._differ = differ or changesetdiffer()
235 self._diffopts = patch.diffallopts(ui, diffopts)
235 self._diffopts = patch.diffallopts(ui, diffopts)
236 self._includestat = diffopts and diffopts.get(b'stat')
236 self._includestat = diffopts and diffopts.get(b'stat')
237 self._includediff = diffopts and diffopts.get(b'patch')
237 self._includediff = diffopts and diffopts.get(b'patch')
238 self.header = {}
238 self.header = {}
239 self.hunk = {}
239 self.hunk = {}
240 self.lastheader = None
240 self.lastheader = None
241 self.footer = None
241 self.footer = None
242 self._columns = templatekw.getlogcolumns()
242 self._columns = templatekw.getlogcolumns()
243
243
244 def flush(self, ctx):
244 def flush(self, ctx):
245 rev = ctx.rev()
245 rev = ctx.rev()
246 if rev in self.header:
246 if rev in self.header:
247 h = self.header[rev]
247 h = self.header[rev]
248 if h != self.lastheader:
248 if h != self.lastheader:
249 self.lastheader = h
249 self.lastheader = h
250 self.ui.write(h)
250 self.ui.write(h)
251 del self.header[rev]
251 del self.header[rev]
252 if rev in self.hunk:
252 if rev in self.hunk:
253 self.ui.write(self.hunk[rev])
253 self.ui.write(self.hunk[rev])
254 del self.hunk[rev]
254 del self.hunk[rev]
255
255
256 def close(self):
256 def close(self):
257 if self.footer:
257 if self.footer:
258 self.ui.write(self.footer)
258 self.ui.write(self.footer)
259
259
260 def show(self, ctx, copies=None, **props):
260 def show(self, ctx, copies=None, **props):
261 props = pycompat.byteskwargs(props)
261 props = pycompat.byteskwargs(props)
262 if self.buffered:
262 if self.buffered:
263 self.ui.pushbuffer(labeled=True)
263 self.ui.pushbuffer(labeled=True)
264 self._show(ctx, copies, props)
264 self._show(ctx, copies, props)
265 self.hunk[ctx.rev()] = self.ui.popbuffer()
265 self.hunk[ctx.rev()] = self.ui.popbuffer()
266 else:
266 else:
267 self._show(ctx, copies, props)
267 self._show(ctx, copies, props)
268
268
269 def _show(self, ctx, copies, props):
269 def _show(self, ctx, copies, props):
270 '''show a single changeset or file revision'''
270 '''show a single changeset or file revision'''
271 changenode = ctx.node()
271 changenode = ctx.node()
272 graphwidth = props.get(b'graphwidth', 0)
272 graphwidth = props.get(b'graphwidth', 0)
273
273
274 if self.ui.quiet:
274 if self.ui.quiet:
275 self.ui.write(
275 self.ui.write(
276 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node'
276 b"%s\n" % scmutil.formatchangeid(ctx), label=b'log.node'
277 )
277 )
278 return
278 return
279
279
280 columns = self._columns
280 columns = self._columns
281 self.ui.write(
281 self.ui.write(
282 columns[b'changeset'] % scmutil.formatchangeid(ctx),
282 columns[b'changeset'] % scmutil.formatchangeid(ctx),
283 label=changesetlabels(ctx),
283 label=changesetlabels(ctx),
284 )
284 )
285
285
286 # branches are shown first before any other names due to backwards
286 # branches are shown first before any other names due to backwards
287 # compatibility
287 # compatibility
288 branch = ctx.branch()
288 branch = ctx.branch()
289 # don't show the default branch name
289 # don't show the default branch name
290 if branch != b'default':
290 if branch != b'default':
291 self.ui.write(columns[b'branch'] % branch, label=b'log.branch')
291 self.ui.write(columns[b'branch'] % branch, label=b'log.branch')
292
292
293 for nsname, ns in self.repo.names.iteritems():
293 for nsname, ns in self.repo.names.iteritems():
294 # branches has special logic already handled above, so here we just
294 # branches has special logic already handled above, so here we just
295 # skip it
295 # skip it
296 if nsname == b'branches':
296 if nsname == b'branches':
297 continue
297 continue
298 # we will use the templatename as the color name since those two
298 # we will use the templatename as the color name since those two
299 # should be the same
299 # should be the same
300 for name in ns.names(self.repo, changenode):
300 for name in ns.names(self.repo, changenode):
301 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname)
301 self.ui.write(ns.logfmt % name, label=b'log.%s' % ns.colorname)
302 if self.ui.debugflag:
302 if self.ui.debugflag:
303 self.ui.write(
303 self.ui.write(
304 columns[b'phase'] % ctx.phasestr(), label=b'log.phase'
304 columns[b'phase'] % ctx.phasestr(), label=b'log.phase'
305 )
305 )
306 for pctx in scmutil.meaningfulparents(self.repo, ctx):
306 for pctx in scmutil.meaningfulparents(self.repo, ctx):
307 label = b'log.parent changeset.%s' % pctx.phasestr()
307 label = b'log.parent changeset.%s' % pctx.phasestr()
308 self.ui.write(
308 self.ui.write(
309 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label
309 columns[b'parent'] % scmutil.formatchangeid(pctx), label=label
310 )
310 )
311
311
312 if self.ui.debugflag:
312 if self.ui.debugflag:
313 mnode = ctx.manifestnode()
313 mnode = ctx.manifestnode()
314 if mnode is None:
314 if mnode is None:
315 mnode = wdirid
315 mnode = wdirid
316 mrev = wdirrev
316 mrev = wdirrev
317 else:
317 else:
318 mrev = self.repo.manifestlog.rev(mnode)
318 mrev = self.repo.manifestlog.rev(mnode)
319 self.ui.write(
319 self.ui.write(
320 columns[b'manifest']
320 columns[b'manifest']
321 % scmutil.formatrevnode(self.ui, mrev, mnode),
321 % scmutil.formatrevnode(self.ui, mrev, mnode),
322 label=b'ui.debug log.manifest',
322 label=b'ui.debug log.manifest',
323 )
323 )
324 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user')
324 self.ui.write(columns[b'user'] % ctx.user(), label=b'log.user')
325 self.ui.write(
325 self.ui.write(
326 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date'
326 columns[b'date'] % dateutil.datestr(ctx.date()), label=b'log.date'
327 )
327 )
328
328
329 if ctx.isunstable():
329 if ctx.isunstable():
330 instabilities = ctx.instabilities()
330 instabilities = ctx.instabilities()
331 self.ui.write(
331 self.ui.write(
332 columns[b'instability'] % b', '.join(instabilities),
332 columns[b'instability'] % b', '.join(instabilities),
333 label=b'log.instability',
333 label=b'log.instability',
334 )
334 )
335
335
336 elif ctx.obsolete():
336 elif ctx.obsolete():
337 self._showobsfate(ctx)
337 self._showobsfate(ctx)
338
338
339 self._exthook(ctx)
339 self._exthook(ctx)
340
340
341 if self.ui.debugflag:
341 if self.ui.debugflag:
342 files = ctx.p1().status(ctx)[:3]
342 files = ctx.p1().status(ctx)[:3]
343 for key, value in zip([b'files', b'files+', b'files-'], files):
343 for key, value in zip([b'files', b'files+', b'files-'], files):
344 if value:
344 if value:
345 self.ui.write(
345 self.ui.write(
346 columns[key] % b" ".join(value),
346 columns[key] % b" ".join(value),
347 label=b'ui.debug log.files',
347 label=b'ui.debug log.files',
348 )
348 )
349 elif ctx.files() and self.ui.verbose:
349 elif ctx.files() and self.ui.verbose:
350 self.ui.write(
350 self.ui.write(
351 columns[b'files'] % b" ".join(ctx.files()),
351 columns[b'files'] % b" ".join(ctx.files()),
352 label=b'ui.note log.files',
352 label=b'ui.note log.files',
353 )
353 )
354 if copies and self.ui.verbose:
354 if copies and self.ui.verbose:
355 copies = [b'%s (%s)' % c for c in copies]
355 copies = [b'%s (%s)' % c for c in copies]
356 self.ui.write(
356 self.ui.write(
357 columns[b'copies'] % b' '.join(copies),
357 columns[b'copies'] % b' '.join(copies),
358 label=b'ui.note log.copies',
358 label=b'ui.note log.copies',
359 )
359 )
360
360
361 extra = ctx.extra()
361 extra = ctx.extra()
362 if extra and self.ui.debugflag:
362 if extra and self.ui.debugflag:
363 for key, value in sorted(extra.items()):
363 for key, value in sorted(extra.items()):
364 self.ui.write(
364 self.ui.write(
365 columns[b'extra'] % (key, stringutil.escapestr(value)),
365 columns[b'extra'] % (key, stringutil.escapestr(value)),
366 label=b'ui.debug log.extra',
366 label=b'ui.debug log.extra',
367 )
367 )
368
368
369 description = ctx.description().strip()
369 description = ctx.description().strip()
370 if description:
370 if description:
371 if self.ui.verbose:
371 if self.ui.verbose:
372 self.ui.write(
372 self.ui.write(
373 _(b"description:\n"), label=b'ui.note log.description'
373 _(b"description:\n"), label=b'ui.note log.description'
374 )
374 )
375 self.ui.write(description, label=b'ui.note log.description')
375 self.ui.write(description, label=b'ui.note log.description')
376 self.ui.write(b"\n\n")
376 self.ui.write(b"\n\n")
377 else:
377 else:
378 self.ui.write(
378 self.ui.write(
379 columns[b'summary'] % description.splitlines()[0],
379 columns[b'summary'] % description.splitlines()[0],
380 label=b'log.summary',
380 label=b'log.summary',
381 )
381 )
382 self.ui.write(b"\n")
382 self.ui.write(b"\n")
383
383
384 self._showpatch(ctx, graphwidth)
384 self._showpatch(ctx, graphwidth)
385
385
386 def _showobsfate(self, ctx):
386 def _showobsfate(self, ctx):
387 # TODO: do not depend on templater
387 # TODO: do not depend on templater
388 tres = formatter.templateresources(self.repo.ui, self.repo)
388 tres = formatter.templateresources(self.repo.ui, self.repo)
389 t = formatter.maketemplater(
389 t = formatter.maketemplater(
390 self.repo.ui,
390 self.repo.ui,
391 b'{join(obsfate, "\n")}',
391 b'{join(obsfate, "\n")}',
392 defaults=templatekw.keywords,
392 defaults=templatekw.keywords,
393 resources=tres,
393 resources=tres,
394 )
394 )
395 obsfate = t.renderdefault({b'ctx': ctx}).splitlines()
395 obsfate = t.renderdefault({b'ctx': ctx}).splitlines()
396
396
397 if obsfate:
397 if obsfate:
398 for obsfateline in obsfate:
398 for obsfateline in obsfate:
399 self.ui.write(
399 self.ui.write(
400 self._columns[b'obsolete'] % obsfateline,
400 self._columns[b'obsolete'] % obsfateline,
401 label=b'log.obsfate',
401 label=b'log.obsfate',
402 )
402 )
403
403
404 def _exthook(self, ctx):
404 def _exthook(self, ctx):
405 '''empty method used by extension as a hook point
405 '''empty method used by extension as a hook point
406 '''
406 '''
407
407
408 def _showpatch(self, ctx, graphwidth=0):
408 def _showpatch(self, ctx, graphwidth=0):
409 if self._includestat:
409 if self._includestat:
410 self._differ.showdiff(
410 self._differ.showdiff(
411 self.ui, ctx, self._diffopts, graphwidth, stat=True
411 self.ui, ctx, self._diffopts, graphwidth, stat=True
412 )
412 )
413 if self._includestat and self._includediff:
413 if self._includestat and self._includediff:
414 self.ui.write(b"\n")
414 self.ui.write(b"\n")
415 if self._includediff:
415 if self._includediff:
416 self._differ.showdiff(
416 self._differ.showdiff(
417 self.ui, ctx, self._diffopts, graphwidth, stat=False
417 self.ui, ctx, self._diffopts, graphwidth, stat=False
418 )
418 )
419 if self._includestat or self._includediff:
419 if self._includestat or self._includediff:
420 self.ui.write(b"\n")
420 self.ui.write(b"\n")
421
421
422
422
423 class changesetformatter(changesetprinter):
423 class changesetformatter(changesetprinter):
424 """Format changeset information by generic formatter"""
424 """Format changeset information by generic formatter"""
425
425
426 def __init__(
426 def __init__(
427 self, ui, repo, fm, differ=None, diffopts=None, buffered=False
427 self, ui, repo, fm, differ=None, diffopts=None, buffered=False
428 ):
428 ):
429 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
429 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
430 self._diffopts = patch.difffeatureopts(ui, diffopts, git=True)
430 self._diffopts = patch.difffeatureopts(ui, diffopts, git=True)
431 self._fm = fm
431 self._fm = fm
432
432
433 def close(self):
433 def close(self):
434 self._fm.end()
434 self._fm.end()
435
435
436 def _show(self, ctx, copies, props):
436 def _show(self, ctx, copies, props):
437 '''show a single changeset or file revision'''
437 '''show a single changeset or file revision'''
438 fm = self._fm
438 fm = self._fm
439 fm.startitem()
439 fm.startitem()
440 fm.context(ctx=ctx)
440 fm.context(ctx=ctx)
441 fm.data(rev=scmutil.intrev(ctx), node=fm.hexfunc(scmutil.binnode(ctx)))
441 fm.data(rev=scmutil.intrev(ctx), node=fm.hexfunc(scmutil.binnode(ctx)))
442
442
443 if self.ui.quiet:
443 datahint = fm.datahint()
444 if self.ui.quiet and not datahint:
444 return
445 return
445
446
446 fm.data(
447 fm.data(
447 branch=ctx.branch(),
448 branch=ctx.branch(),
448 phase=ctx.phasestr(),
449 phase=ctx.phasestr(),
449 user=ctx.user(),
450 user=ctx.user(),
450 date=fm.formatdate(ctx.date()),
451 date=fm.formatdate(ctx.date()),
451 desc=ctx.description(),
452 desc=ctx.description(),
452 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'),
453 bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'),
453 tags=fm.formatlist(ctx.tags(), name=b'tag'),
454 tags=fm.formatlist(ctx.tags(), name=b'tag'),
454 parents=fm.formatlist(
455 parents=fm.formatlist(
455 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node'
456 [fm.hexfunc(c.node()) for c in ctx.parents()], name=b'node'
456 ),
457 ),
457 )
458 )
458
459
459 if self.ui.debugflag:
460 if self.ui.debugflag or b'manifest' in datahint:
460 fm.data(
461 fm.data(manifest=fm.hexfunc(ctx.manifestnode() or wdirid))
461 manifest=fm.hexfunc(ctx.manifestnode() or wdirid),
462 if self.ui.debugflag or b'extra' in datahint:
462 extra=fm.formatdict(ctx.extra()),
463 fm.data(extra=fm.formatdict(ctx.extra()))
463 )
464
464
465 if (
466 self.ui.debugflag
467 or b'modified' in datahint
468 or b'added' in datahint
469 or b'removed' in datahint
470 ):
465 files = ctx.p1().status(ctx)
471 files = ctx.p1().status(ctx)
466 fm.data(
472 fm.data(
467 modified=fm.formatlist(files[0], name=b'file'),
473 modified=fm.formatlist(files[0], name=b'file'),
468 added=fm.formatlist(files[1], name=b'file'),
474 added=fm.formatlist(files[1], name=b'file'),
469 removed=fm.formatlist(files[2], name=b'file'),
475 removed=fm.formatlist(files[2], name=b'file'),
470 )
476 )
471
477
472 elif self.ui.verbose:
478 verbose = not self.ui.debugflag and self.ui.verbose
479 if verbose or b'files' in datahint:
473 fm.data(files=fm.formatlist(ctx.files(), name=b'file'))
480 fm.data(files=fm.formatlist(ctx.files(), name=b'file'))
474 if copies:
481 if verbose and copies or b'copies' in datahint:
475 fm.data(
482 fm.data(
476 copies=fm.formatdict(copies, key=b'name', value=b'source')
483 copies=fm.formatdict(copies or {}, key=b'name', value=b'source')
477 )
484 )
478
485
479 if self._includestat:
486 if self._includestat or b'diffstat' in datahint:
480 self.ui.pushbuffer()
487 self.ui.pushbuffer()
481 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True)
488 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True)
482 fm.data(diffstat=self.ui.popbuffer())
489 fm.data(diffstat=self.ui.popbuffer())
483 if self._includediff:
490 if self._includediff or b'diff' in datahint:
484 self.ui.pushbuffer()
491 self.ui.pushbuffer()
485 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False)
492 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False)
486 fm.data(diff=self.ui.popbuffer())
493 fm.data(diff=self.ui.popbuffer())
487
494
488
495
489 class changesettemplater(changesetprinter):
496 class changesettemplater(changesetprinter):
490 '''format changeset information.
497 '''format changeset information.
491
498
492 Note: there are a variety of convenience functions to build a
499 Note: there are a variety of convenience functions to build a
493 changesettemplater for common cases. See functions such as:
500 changesettemplater for common cases. See functions such as:
494 maketemplater, changesetdisplayer, buildcommittemplate, or other
501 maketemplater, changesetdisplayer, buildcommittemplate, or other
495 functions that use changesest_templater.
502 functions that use changesest_templater.
496 '''
503 '''
497
504
498 # Arguments before "buffered" used to be positional. Consider not
505 # Arguments before "buffered" used to be positional. Consider not
499 # adding/removing arguments before "buffered" to not break callers.
506 # adding/removing arguments before "buffered" to not break callers.
500 def __init__(
507 def __init__(
501 self, ui, repo, tmplspec, differ=None, diffopts=None, buffered=False
508 self, ui, repo, tmplspec, differ=None, diffopts=None, buffered=False
502 ):
509 ):
503 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
510 changesetprinter.__init__(self, ui, repo, differ, diffopts, buffered)
504 # tres is shared with _graphnodeformatter()
511 # tres is shared with _graphnodeformatter()
505 self._tresources = tres = formatter.templateresources(ui, repo)
512 self._tresources = tres = formatter.templateresources(ui, repo)
506 self.t = formatter.loadtemplater(
513 self.t = formatter.loadtemplater(
507 ui,
514 ui,
508 tmplspec,
515 tmplspec,
509 defaults=templatekw.keywords,
516 defaults=templatekw.keywords,
510 resources=tres,
517 resources=tres,
511 cache=templatekw.defaulttempl,
518 cache=templatekw.defaulttempl,
512 )
519 )
513 self._counter = itertools.count()
520 self._counter = itertools.count()
514
521
515 self._tref = tmplspec.ref
522 self._tref = tmplspec.ref
516 self._parts = {
523 self._parts = {
517 b'header': b'',
524 b'header': b'',
518 b'footer': b'',
525 b'footer': b'',
519 tmplspec.ref: tmplspec.ref,
526 tmplspec.ref: tmplspec.ref,
520 b'docheader': b'',
527 b'docheader': b'',
521 b'docfooter': b'',
528 b'docfooter': b'',
522 b'separator': b'',
529 b'separator': b'',
523 }
530 }
524 if tmplspec.mapfile:
531 if tmplspec.mapfile:
525 # find correct templates for current mode, for backward
532 # find correct templates for current mode, for backward
526 # compatibility with 'log -v/-q/--debug' using a mapfile
533 # compatibility with 'log -v/-q/--debug' using a mapfile
527 tmplmodes = [
534 tmplmodes = [
528 (True, b''),
535 (True, b''),
529 (self.ui.verbose, b'_verbose'),
536 (self.ui.verbose, b'_verbose'),
530 (self.ui.quiet, b'_quiet'),
537 (self.ui.quiet, b'_quiet'),
531 (self.ui.debugflag, b'_debug'),
538 (self.ui.debugflag, b'_debug'),
532 ]
539 ]
533 for mode, postfix in tmplmodes:
540 for mode, postfix in tmplmodes:
534 for t in self._parts:
541 for t in self._parts:
535 cur = t + postfix
542 cur = t + postfix
536 if mode and cur in self.t:
543 if mode and cur in self.t:
537 self._parts[t] = cur
544 self._parts[t] = cur
538 else:
545 else:
539 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
546 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
540 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
547 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
541 self._parts.update(m)
548 self._parts.update(m)
542
549
543 if self._parts[b'docheader']:
550 if self._parts[b'docheader']:
544 self.ui.write(self.t.render(self._parts[b'docheader'], {}))
551 self.ui.write(self.t.render(self._parts[b'docheader'], {}))
545
552
546 def close(self):
553 def close(self):
547 if self._parts[b'docfooter']:
554 if self._parts[b'docfooter']:
548 if not self.footer:
555 if not self.footer:
549 self.footer = b""
556 self.footer = b""
550 self.footer += self.t.render(self._parts[b'docfooter'], {})
557 self.footer += self.t.render(self._parts[b'docfooter'], {})
551 return super(changesettemplater, self).close()
558 return super(changesettemplater, self).close()
552
559
553 def _show(self, ctx, copies, props):
560 def _show(self, ctx, copies, props):
554 '''show a single changeset or file revision'''
561 '''show a single changeset or file revision'''
555 props = props.copy()
562 props = props.copy()
556 props[b'ctx'] = ctx
563 props[b'ctx'] = ctx
557 props[b'index'] = index = next(self._counter)
564 props[b'index'] = index = next(self._counter)
558 props[b'revcache'] = {b'copies': copies}
565 props[b'revcache'] = {b'copies': copies}
559 graphwidth = props.get(b'graphwidth', 0)
566 graphwidth = props.get(b'graphwidth', 0)
560
567
561 # write separator, which wouldn't work well with the header part below
568 # write separator, which wouldn't work well with the header part below
562 # since there's inherently a conflict between header (across items) and
569 # since there's inherently a conflict between header (across items) and
563 # separator (per item)
570 # separator (per item)
564 if self._parts[b'separator'] and index > 0:
571 if self._parts[b'separator'] and index > 0:
565 self.ui.write(self.t.render(self._parts[b'separator'], {}))
572 self.ui.write(self.t.render(self._parts[b'separator'], {}))
566
573
567 # write header
574 # write header
568 if self._parts[b'header']:
575 if self._parts[b'header']:
569 h = self.t.render(self._parts[b'header'], props)
576 h = self.t.render(self._parts[b'header'], props)
570 if self.buffered:
577 if self.buffered:
571 self.header[ctx.rev()] = h
578 self.header[ctx.rev()] = h
572 else:
579 else:
573 if self.lastheader != h:
580 if self.lastheader != h:
574 self.lastheader = h
581 self.lastheader = h
575 self.ui.write(h)
582 self.ui.write(h)
576
583
577 # write changeset metadata, then patch if requested
584 # write changeset metadata, then patch if requested
578 key = self._parts[self._tref]
585 key = self._parts[self._tref]
579 self.ui.write(self.t.render(key, props))
586 self.ui.write(self.t.render(key, props))
580 self._showpatch(ctx, graphwidth)
587 self._showpatch(ctx, graphwidth)
581
588
582 if self._parts[b'footer']:
589 if self._parts[b'footer']:
583 if not self.footer:
590 if not self.footer:
584 self.footer = self.t.render(self._parts[b'footer'], props)
591 self.footer = self.t.render(self._parts[b'footer'], props)
585
592
586
593
587 def templatespec(tmpl, mapfile):
594 def templatespec(tmpl, mapfile):
588 if pycompat.ispy3:
595 if pycompat.ispy3:
589 assert not isinstance(tmpl, str), b'tmpl must not be a str'
596 assert not isinstance(tmpl, str), b'tmpl must not be a str'
590 if mapfile:
597 if mapfile:
591 return formatter.templatespec(b'changeset', tmpl, mapfile)
598 return formatter.templatespec(b'changeset', tmpl, mapfile)
592 else:
599 else:
593 return formatter.templatespec(b'', tmpl, None)
600 return formatter.templatespec(b'', tmpl, None)
594
601
595
602
596 def _lookuptemplate(ui, tmpl, style):
603 def _lookuptemplate(ui, tmpl, style):
597 """Find the template matching the given template spec or style
604 """Find the template matching the given template spec or style
598
605
599 See formatter.lookuptemplate() for details.
606 See formatter.lookuptemplate() for details.
600 """
607 """
601
608
602 # ui settings
609 # ui settings
603 if not tmpl and not style: # template are stronger than style
610 if not tmpl and not style: # template are stronger than style
604 tmpl = ui.config(b'ui', b'logtemplate')
611 tmpl = ui.config(b'ui', b'logtemplate')
605 if tmpl:
612 if tmpl:
606 return templatespec(templater.unquotestring(tmpl), None)
613 return templatespec(templater.unquotestring(tmpl), None)
607 else:
614 else:
608 style = util.expandpath(ui.config(b'ui', b'style'))
615 style = util.expandpath(ui.config(b'ui', b'style'))
609
616
610 if not tmpl and style:
617 if not tmpl and style:
611 mapfile = style
618 mapfile = style
612 if not os.path.split(mapfile)[0]:
619 if not os.path.split(mapfile)[0]:
613 mapname = templater.templatepath(
620 mapname = templater.templatepath(
614 b'map-cmdline.' + mapfile
621 b'map-cmdline.' + mapfile
615 ) or templater.templatepath(mapfile)
622 ) or templater.templatepath(mapfile)
616 if mapname:
623 if mapname:
617 mapfile = mapname
624 mapfile = mapname
618 return templatespec(None, mapfile)
625 return templatespec(None, mapfile)
619
626
620 return formatter.lookuptemplate(ui, b'changeset', tmpl)
627 return formatter.lookuptemplate(ui, b'changeset', tmpl)
621
628
622
629
623 def maketemplater(ui, repo, tmpl, buffered=False):
630 def maketemplater(ui, repo, tmpl, buffered=False):
624 """Create a changesettemplater from a literal template 'tmpl'
631 """Create a changesettemplater from a literal template 'tmpl'
625 byte-string."""
632 byte-string."""
626 spec = templatespec(tmpl, None)
633 spec = templatespec(tmpl, None)
627 return changesettemplater(ui, repo, spec, buffered=buffered)
634 return changesettemplater(ui, repo, spec, buffered=buffered)
628
635
629
636
630 def changesetdisplayer(ui, repo, opts, differ=None, buffered=False):
637 def changesetdisplayer(ui, repo, opts, differ=None, buffered=False):
631 """show one changeset using template or regular display.
638 """show one changeset using template or regular display.
632
639
633 Display format will be the first non-empty hit of:
640 Display format will be the first non-empty hit of:
634 1. option 'template'
641 1. option 'template'
635 2. option 'style'
642 2. option 'style'
636 3. [ui] setting 'logtemplate'
643 3. [ui] setting 'logtemplate'
637 4. [ui] setting 'style'
644 4. [ui] setting 'style'
638 If all of these values are either the unset or the empty string,
645 If all of these values are either the unset or the empty string,
639 regular display via changesetprinter() is done.
646 regular display via changesetprinter() is done.
640 """
647 """
641 postargs = (differ, opts, buffered)
648 postargs = (differ, opts, buffered)
642 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style'))
649 spec = _lookuptemplate(ui, opts.get(b'template'), opts.get(b'style'))
643
650
644 # machine-readable formats have slightly different keyword set than
651 # machine-readable formats have slightly different keyword set than
645 # plain templates, which are handled by changesetformatter.
652 # plain templates, which are handled by changesetformatter.
646 # note that {b'pickle', b'debug'} can also be added to the list if needed.
653 # note that {b'pickle', b'debug'} can also be added to the list if needed.
647 if spec.ref in {b'cbor', b'json'}:
654 if spec.ref in {b'cbor', b'json'}:
648 fm = ui.formatter(b'log', opts)
655 fm = ui.formatter(b'log', opts)
649 return changesetformatter(ui, repo, fm, *postargs)
656 return changesetformatter(ui, repo, fm, *postargs)
650
657
651 if not spec.ref and not spec.tmpl and not spec.mapfile:
658 if not spec.ref and not spec.tmpl and not spec.mapfile:
652 return changesetprinter(ui, repo, *postargs)
659 return changesetprinter(ui, repo, *postargs)
653
660
654 return changesettemplater(ui, repo, spec, *postargs)
661 return changesettemplater(ui, repo, spec, *postargs)
655
662
656
663
657 def _makematcher(repo, revs, pats, opts):
664 def _makematcher(repo, revs, pats, opts):
658 """Build matcher and expanded patterns from log options
665 """Build matcher and expanded patterns from log options
659
666
660 If --follow, revs are the revisions to follow from.
667 If --follow, revs are the revisions to follow from.
661
668
662 Returns (match, pats, slowpath) where
669 Returns (match, pats, slowpath) where
663 - match: a matcher built from the given pats and -I/-X opts
670 - match: a matcher built from the given pats and -I/-X opts
664 - pats: patterns used (globs are expanded on Windows)
671 - pats: patterns used (globs are expanded on Windows)
665 - slowpath: True if patterns aren't as simple as scanning filelogs
672 - slowpath: True if patterns aren't as simple as scanning filelogs
666 """
673 """
667 # pats/include/exclude are passed to match.match() directly in
674 # pats/include/exclude are passed to match.match() directly in
668 # _matchfiles() revset but walkchangerevs() builds its matcher with
675 # _matchfiles() revset but walkchangerevs() builds its matcher with
669 # scmutil.match(). The difference is input pats are globbed on
676 # scmutil.match(). The difference is input pats are globbed on
670 # platforms without shell expansion (windows).
677 # platforms without shell expansion (windows).
671 wctx = repo[None]
678 wctx = repo[None]
672 match, pats = scmutil.matchandpats(wctx, pats, opts)
679 match, pats = scmutil.matchandpats(wctx, pats, opts)
673 slowpath = match.anypats() or (not match.always() and opts.get(b'removed'))
680 slowpath = match.anypats() or (not match.always() and opts.get(b'removed'))
674 if not slowpath:
681 if not slowpath:
675 follow = opts.get(b'follow') or opts.get(b'follow_first')
682 follow = opts.get(b'follow') or opts.get(b'follow_first')
676 startctxs = []
683 startctxs = []
677 if follow and opts.get(b'rev'):
684 if follow and opts.get(b'rev'):
678 startctxs = [repo[r] for r in revs]
685 startctxs = [repo[r] for r in revs]
679 for f in match.files():
686 for f in match.files():
680 if follow and startctxs:
687 if follow and startctxs:
681 # No idea if the path was a directory at that revision, so
688 # No idea if the path was a directory at that revision, so
682 # take the slow path.
689 # take the slow path.
683 if any(f not in c for c in startctxs):
690 if any(f not in c for c in startctxs):
684 slowpath = True
691 slowpath = True
685 continue
692 continue
686 elif follow and f not in wctx:
693 elif follow and f not in wctx:
687 # If the file exists, it may be a directory, so let it
694 # If the file exists, it may be a directory, so let it
688 # take the slow path.
695 # take the slow path.
689 if os.path.exists(repo.wjoin(f)):
696 if os.path.exists(repo.wjoin(f)):
690 slowpath = True
697 slowpath = True
691 continue
698 continue
692 else:
699 else:
693 raise error.Abort(
700 raise error.Abort(
694 _(
701 _(
695 b'cannot follow file not in parent '
702 b'cannot follow file not in parent '
696 b'revision: "%s"'
703 b'revision: "%s"'
697 )
704 )
698 % f
705 % f
699 )
706 )
700 filelog = repo.file(f)
707 filelog = repo.file(f)
701 if not filelog:
708 if not filelog:
702 # A zero count may be a directory or deleted file, so
709 # A zero count may be a directory or deleted file, so
703 # try to find matching entries on the slow path.
710 # try to find matching entries on the slow path.
704 if follow:
711 if follow:
705 raise error.Abort(
712 raise error.Abort(
706 _(b'cannot follow nonexistent file: "%s"') % f
713 _(b'cannot follow nonexistent file: "%s"') % f
707 )
714 )
708 slowpath = True
715 slowpath = True
709
716
710 # We decided to fall back to the slowpath because at least one
717 # We decided to fall back to the slowpath because at least one
711 # of the paths was not a file. Check to see if at least one of them
718 # of the paths was not a file. Check to see if at least one of them
712 # existed in history - in that case, we'll continue down the
719 # existed in history - in that case, we'll continue down the
713 # slowpath; otherwise, we can turn off the slowpath
720 # slowpath; otherwise, we can turn off the slowpath
714 if slowpath:
721 if slowpath:
715 for path in match.files():
722 for path in match.files():
716 if path == b'.' or path in repo.store:
723 if path == b'.' or path in repo.store:
717 break
724 break
718 else:
725 else:
719 slowpath = False
726 slowpath = False
720
727
721 return match, pats, slowpath
728 return match, pats, slowpath
722
729
723
730
724 def _fileancestors(repo, revs, match, followfirst):
731 def _fileancestors(repo, revs, match, followfirst):
725 fctxs = []
732 fctxs = []
726 for r in revs:
733 for r in revs:
727 ctx = repo[r]
734 ctx = repo[r]
728 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
735 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
729
736
730 # When displaying a revision with --patch --follow FILE, we have
737 # When displaying a revision with --patch --follow FILE, we have
731 # to know which file of the revision must be diffed. With
738 # to know which file of the revision must be diffed. With
732 # --follow, we want the names of the ancestors of FILE in the
739 # --follow, we want the names of the ancestors of FILE in the
733 # revision, stored in "fcache". "fcache" is populated as a side effect
740 # revision, stored in "fcache". "fcache" is populated as a side effect
734 # of the graph traversal.
741 # of the graph traversal.
735 fcache = {}
742 fcache = {}
736
743
737 def filematcher(ctx):
744 def filematcher(ctx):
738 return scmutil.matchfiles(repo, fcache.get(ctx.rev(), []))
745 return scmutil.matchfiles(repo, fcache.get(ctx.rev(), []))
739
746
740 def revgen():
747 def revgen():
741 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
748 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
742 fcache[rev] = [c.path() for c in cs]
749 fcache[rev] = [c.path() for c in cs]
743 yield rev
750 yield rev
744
751
745 return smartset.generatorset(revgen(), iterasc=False), filematcher
752 return smartset.generatorset(revgen(), iterasc=False), filematcher
746
753
747
754
748 def _makenofollowfilematcher(repo, pats, opts):
755 def _makenofollowfilematcher(repo, pats, opts):
749 '''hook for extensions to override the filematcher for non-follow cases'''
756 '''hook for extensions to override the filematcher for non-follow cases'''
750 return None
757 return None
751
758
752
759
753 _opt2logrevset = {
760 _opt2logrevset = {
754 b'no_merges': (b'not merge()', None),
761 b'no_merges': (b'not merge()', None),
755 b'only_merges': (b'merge()', None),
762 b'only_merges': (b'merge()', None),
756 b'_matchfiles': (None, b'_matchfiles(%ps)'),
763 b'_matchfiles': (None, b'_matchfiles(%ps)'),
757 b'date': (b'date(%s)', None),
764 b'date': (b'date(%s)', None),
758 b'branch': (b'branch(%s)', b'%lr'),
765 b'branch': (b'branch(%s)', b'%lr'),
759 b'_patslog': (b'filelog(%s)', b'%lr'),
766 b'_patslog': (b'filelog(%s)', b'%lr'),
760 b'keyword': (b'keyword(%s)', b'%lr'),
767 b'keyword': (b'keyword(%s)', b'%lr'),
761 b'prune': (b'ancestors(%s)', b'not %lr'),
768 b'prune': (b'ancestors(%s)', b'not %lr'),
762 b'user': (b'user(%s)', b'%lr'),
769 b'user': (b'user(%s)', b'%lr'),
763 }
770 }
764
771
765
772
766 def _makerevset(repo, match, pats, slowpath, opts):
773 def _makerevset(repo, match, pats, slowpath, opts):
767 """Return a revset string built from log options and file patterns"""
774 """Return a revset string built from log options and file patterns"""
768 opts = dict(opts)
775 opts = dict(opts)
769 # follow or not follow?
776 # follow or not follow?
770 follow = opts.get(b'follow') or opts.get(b'follow_first')
777 follow = opts.get(b'follow') or opts.get(b'follow_first')
771
778
772 # branch and only_branch are really aliases and must be handled at
779 # branch and only_branch are really aliases and must be handled at
773 # the same time
780 # the same time
774 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', [])
781 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', [])
775 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']]
782 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']]
776
783
777 if slowpath:
784 if slowpath:
778 # See walkchangerevs() slow path.
785 # See walkchangerevs() slow path.
779 #
786 #
780 # pats/include/exclude cannot be represented as separate
787 # pats/include/exclude cannot be represented as separate
781 # revset expressions as their filtering logic applies at file
788 # revset expressions as their filtering logic applies at file
782 # level. For instance "-I a -X b" matches a revision touching
789 # level. For instance "-I a -X b" matches a revision touching
783 # "a" and "b" while "file(a) and not file(b)" does
790 # "a" and "b" while "file(a) and not file(b)" does
784 # not. Besides, filesets are evaluated against the working
791 # not. Besides, filesets are evaluated against the working
785 # directory.
792 # directory.
786 matchargs = [b'r:', b'd:relpath']
793 matchargs = [b'r:', b'd:relpath']
787 for p in pats:
794 for p in pats:
788 matchargs.append(b'p:' + p)
795 matchargs.append(b'p:' + p)
789 for p in opts.get(b'include', []):
796 for p in opts.get(b'include', []):
790 matchargs.append(b'i:' + p)
797 matchargs.append(b'i:' + p)
791 for p in opts.get(b'exclude', []):
798 for p in opts.get(b'exclude', []):
792 matchargs.append(b'x:' + p)
799 matchargs.append(b'x:' + p)
793 opts[b'_matchfiles'] = matchargs
800 opts[b'_matchfiles'] = matchargs
794 elif not follow:
801 elif not follow:
795 opts[b'_patslog'] = list(pats)
802 opts[b'_patslog'] = list(pats)
796
803
797 expr = []
804 expr = []
798 for op, val in sorted(opts.iteritems()):
805 for op, val in sorted(opts.iteritems()):
799 if not val:
806 if not val:
800 continue
807 continue
801 if op not in _opt2logrevset:
808 if op not in _opt2logrevset:
802 continue
809 continue
803 revop, listop = _opt2logrevset[op]
810 revop, listop = _opt2logrevset[op]
804 if revop and b'%' not in revop:
811 if revop and b'%' not in revop:
805 expr.append(revop)
812 expr.append(revop)
806 elif not listop:
813 elif not listop:
807 expr.append(revsetlang.formatspec(revop, val))
814 expr.append(revsetlang.formatspec(revop, val))
808 else:
815 else:
809 if revop:
816 if revop:
810 val = [revsetlang.formatspec(revop, v) for v in val]
817 val = [revsetlang.formatspec(revop, v) for v in val]
811 expr.append(revsetlang.formatspec(listop, val))
818 expr.append(revsetlang.formatspec(listop, val))
812
819
813 if expr:
820 if expr:
814 expr = b'(' + b' and '.join(expr) + b')'
821 expr = b'(' + b' and '.join(expr) + b')'
815 else:
822 else:
816 expr = None
823 expr = None
817 return expr
824 return expr
818
825
819
826
820 def _initialrevs(repo, opts):
827 def _initialrevs(repo, opts):
821 """Return the initial set of revisions to be filtered or followed"""
828 """Return the initial set of revisions to be filtered or followed"""
822 follow = opts.get(b'follow') or opts.get(b'follow_first')
829 follow = opts.get(b'follow') or opts.get(b'follow_first')
823 if opts.get(b'rev'):
830 if opts.get(b'rev'):
824 revs = scmutil.revrange(repo, opts[b'rev'])
831 revs = scmutil.revrange(repo, opts[b'rev'])
825 elif follow and repo.dirstate.p1() == nullid:
832 elif follow and repo.dirstate.p1() == nullid:
826 revs = smartset.baseset()
833 revs = smartset.baseset()
827 elif follow:
834 elif follow:
828 revs = repo.revs(b'.')
835 revs = repo.revs(b'.')
829 else:
836 else:
830 revs = smartset.spanset(repo)
837 revs = smartset.spanset(repo)
831 revs.reverse()
838 revs.reverse()
832 return revs
839 return revs
833
840
834
841
835 def getrevs(repo, pats, opts):
842 def getrevs(repo, pats, opts):
836 """Return (revs, differ) where revs is a smartset
843 """Return (revs, differ) where revs is a smartset
837
844
838 differ is a changesetdiffer with pre-configured file matcher.
845 differ is a changesetdiffer with pre-configured file matcher.
839 """
846 """
840 follow = opts.get(b'follow') or opts.get(b'follow_first')
847 follow = opts.get(b'follow') or opts.get(b'follow_first')
841 followfirst = opts.get(b'follow_first')
848 followfirst = opts.get(b'follow_first')
842 limit = getlimit(opts)
849 limit = getlimit(opts)
843 revs = _initialrevs(repo, opts)
850 revs = _initialrevs(repo, opts)
844 if not revs:
851 if not revs:
845 return smartset.baseset(), None
852 return smartset.baseset(), None
846 match, pats, slowpath = _makematcher(repo, revs, pats, opts)
853 match, pats, slowpath = _makematcher(repo, revs, pats, opts)
847 filematcher = None
854 filematcher = None
848 if follow:
855 if follow:
849 if slowpath or match.always():
856 if slowpath or match.always():
850 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
857 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
851 else:
858 else:
852 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
859 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
853 revs.reverse()
860 revs.reverse()
854 if filematcher is None:
861 if filematcher is None:
855 filematcher = _makenofollowfilematcher(repo, pats, opts)
862 filematcher = _makenofollowfilematcher(repo, pats, opts)
856 if filematcher is None:
863 if filematcher is None:
857
864
858 def filematcher(ctx):
865 def filematcher(ctx):
859 return match
866 return match
860
867
861 expr = _makerevset(repo, match, pats, slowpath, opts)
868 expr = _makerevset(repo, match, pats, slowpath, opts)
862 if opts.get(b'graph'):
869 if opts.get(b'graph'):
863 # User-specified revs might be unsorted, but don't sort before
870 # User-specified revs might be unsorted, but don't sort before
864 # _makerevset because it might depend on the order of revs
871 # _makerevset because it might depend on the order of revs
865 if repo.ui.configbool(b'experimental', b'log.topo'):
872 if repo.ui.configbool(b'experimental', b'log.topo'):
866 if not revs.istopo():
873 if not revs.istopo():
867 revs = dagop.toposort(revs, repo.changelog.parentrevs)
874 revs = dagop.toposort(revs, repo.changelog.parentrevs)
868 # TODO: try to iterate the set lazily
875 # TODO: try to iterate the set lazily
869 revs = revset.baseset(list(revs), istopo=True)
876 revs = revset.baseset(list(revs), istopo=True)
870 elif not (revs.isdescending() or revs.istopo()):
877 elif not (revs.isdescending() or revs.istopo()):
871 revs.sort(reverse=True)
878 revs.sort(reverse=True)
872 if expr:
879 if expr:
873 matcher = revset.match(None, expr)
880 matcher = revset.match(None, expr)
874 revs = matcher(repo, revs)
881 revs = matcher(repo, revs)
875 if limit is not None:
882 if limit is not None:
876 revs = revs.slice(0, limit)
883 revs = revs.slice(0, limit)
877
884
878 differ = changesetdiffer()
885 differ = changesetdiffer()
879 differ._makefilematcher = filematcher
886 differ._makefilematcher = filematcher
880 return revs, differ
887 return revs, differ
881
888
882
889
883 def _parselinerangeopt(repo, opts):
890 def _parselinerangeopt(repo, opts):
884 """Parse --line-range log option and return a list of tuples (filename,
891 """Parse --line-range log option and return a list of tuples (filename,
885 (fromline, toline)).
892 (fromline, toline)).
886 """
893 """
887 linerangebyfname = []
894 linerangebyfname = []
888 for pat in opts.get(b'line_range', []):
895 for pat in opts.get(b'line_range', []):
889 try:
896 try:
890 pat, linerange = pat.rsplit(b',', 1)
897 pat, linerange = pat.rsplit(b',', 1)
891 except ValueError:
898 except ValueError:
892 raise error.Abort(_(b'malformatted line-range pattern %s') % pat)
899 raise error.Abort(_(b'malformatted line-range pattern %s') % pat)
893 try:
900 try:
894 fromline, toline = map(int, linerange.split(b':'))
901 fromline, toline = map(int, linerange.split(b':'))
895 except ValueError:
902 except ValueError:
896 raise error.Abort(_(b"invalid line range for %s") % pat)
903 raise error.Abort(_(b"invalid line range for %s") % pat)
897 msg = _(b"line range pattern '%s' must match exactly one file") % pat
904 msg = _(b"line range pattern '%s' must match exactly one file") % pat
898 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
905 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
899 linerangebyfname.append(
906 linerangebyfname.append(
900 (fname, util.processlinerange(fromline, toline))
907 (fname, util.processlinerange(fromline, toline))
901 )
908 )
902 return linerangebyfname
909 return linerangebyfname
903
910
904
911
905 def getlinerangerevs(repo, userrevs, opts):
912 def getlinerangerevs(repo, userrevs, opts):
906 """Return (revs, differ).
913 """Return (revs, differ).
907
914
908 "revs" are revisions obtained by processing "line-range" log options and
915 "revs" are revisions obtained by processing "line-range" log options and
909 walking block ancestors of each specified file/line-range.
916 walking block ancestors of each specified file/line-range.
910
917
911 "differ" is a changesetdiffer with pre-configured file matcher and hunks
918 "differ" is a changesetdiffer with pre-configured file matcher and hunks
912 filter.
919 filter.
913 """
920 """
914 wctx = repo[None]
921 wctx = repo[None]
915
922
916 # Two-levels map of "rev -> file ctx -> [line range]".
923 # Two-levels map of "rev -> file ctx -> [line range]".
917 linerangesbyrev = {}
924 linerangesbyrev = {}
918 for fname, (fromline, toline) in _parselinerangeopt(repo, opts):
925 for fname, (fromline, toline) in _parselinerangeopt(repo, opts):
919 if fname not in wctx:
926 if fname not in wctx:
920 raise error.Abort(
927 raise error.Abort(
921 _(b'cannot follow file not in parent ' b'revision: "%s"')
928 _(b'cannot follow file not in parent ' b'revision: "%s"')
922 % fname
929 % fname
923 )
930 )
924 fctx = wctx.filectx(fname)
931 fctx = wctx.filectx(fname)
925 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
932 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
926 rev = fctx.introrev()
933 rev = fctx.introrev()
927 if rev not in userrevs:
934 if rev not in userrevs:
928 continue
935 continue
929 linerangesbyrev.setdefault(rev, {}).setdefault(
936 linerangesbyrev.setdefault(rev, {}).setdefault(
930 fctx.path(), []
937 fctx.path(), []
931 ).append(linerange)
938 ).append(linerange)
932
939
933 def nofilterhunksfn(fctx, hunks):
940 def nofilterhunksfn(fctx, hunks):
934 return hunks
941 return hunks
935
942
936 def hunksfilter(ctx):
943 def hunksfilter(ctx):
937 fctxlineranges = linerangesbyrev.get(ctx.rev())
944 fctxlineranges = linerangesbyrev.get(ctx.rev())
938 if fctxlineranges is None:
945 if fctxlineranges is None:
939 return nofilterhunksfn
946 return nofilterhunksfn
940
947
941 def filterfn(fctx, hunks):
948 def filterfn(fctx, hunks):
942 lineranges = fctxlineranges.get(fctx.path())
949 lineranges = fctxlineranges.get(fctx.path())
943 if lineranges is not None:
950 if lineranges is not None:
944 for hr, lines in hunks:
951 for hr, lines in hunks:
945 if hr is None: # binary
952 if hr is None: # binary
946 yield hr, lines
953 yield hr, lines
947 continue
954 continue
948 if any(mdiff.hunkinrange(hr[2:], lr) for lr in lineranges):
955 if any(mdiff.hunkinrange(hr[2:], lr) for lr in lineranges):
949 yield hr, lines
956 yield hr, lines
950 else:
957 else:
951 for hunk in hunks:
958 for hunk in hunks:
952 yield hunk
959 yield hunk
953
960
954 return filterfn
961 return filterfn
955
962
956 def filematcher(ctx):
963 def filematcher(ctx):
957 files = list(linerangesbyrev.get(ctx.rev(), []))
964 files = list(linerangesbyrev.get(ctx.rev(), []))
958 return scmutil.matchfiles(repo, files)
965 return scmutil.matchfiles(repo, files)
959
966
960 revs = sorted(linerangesbyrev, reverse=True)
967 revs = sorted(linerangesbyrev, reverse=True)
961
968
962 differ = changesetdiffer()
969 differ = changesetdiffer()
963 differ._makefilematcher = filematcher
970 differ._makefilematcher = filematcher
964 differ._makehunksfilter = hunksfilter
971 differ._makehunksfilter = hunksfilter
965 return revs, differ
972 return revs, differ
966
973
967
974
968 def _graphnodeformatter(ui, displayer):
975 def _graphnodeformatter(ui, displayer):
969 spec = ui.config(b'ui', b'graphnodetemplate')
976 spec = ui.config(b'ui', b'graphnodetemplate')
970 if not spec:
977 if not spec:
971 return templatekw.getgraphnode # fast path for "{graphnode}"
978 return templatekw.getgraphnode # fast path for "{graphnode}"
972
979
973 spec = templater.unquotestring(spec)
980 spec = templater.unquotestring(spec)
974 if isinstance(displayer, changesettemplater):
981 if isinstance(displayer, changesettemplater):
975 # reuse cache of slow templates
982 # reuse cache of slow templates
976 tres = displayer._tresources
983 tres = displayer._tresources
977 else:
984 else:
978 tres = formatter.templateresources(ui)
985 tres = formatter.templateresources(ui)
979 templ = formatter.maketemplater(
986 templ = formatter.maketemplater(
980 ui, spec, defaults=templatekw.keywords, resources=tres
987 ui, spec, defaults=templatekw.keywords, resources=tres
981 )
988 )
982
989
983 def formatnode(repo, ctx):
990 def formatnode(repo, ctx):
984 props = {b'ctx': ctx, b'repo': repo}
991 props = {b'ctx': ctx, b'repo': repo}
985 return templ.renderdefault(props)
992 return templ.renderdefault(props)
986
993
987 return formatnode
994 return formatnode
988
995
989
996
990 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None):
997 def displaygraph(ui, repo, dag, displayer, edgefn, getcopies=None, props=None):
991 props = props or {}
998 props = props or {}
992 formatnode = _graphnodeformatter(ui, displayer)
999 formatnode = _graphnodeformatter(ui, displayer)
993 state = graphmod.asciistate()
1000 state = graphmod.asciistate()
994 styles = state[b'styles']
1001 styles = state[b'styles']
995
1002
996 # only set graph styling if HGPLAIN is not set.
1003 # only set graph styling if HGPLAIN is not set.
997 if ui.plain(b'graph'):
1004 if ui.plain(b'graph'):
998 # set all edge styles to |, the default pre-3.8 behaviour
1005 # set all edge styles to |, the default pre-3.8 behaviour
999 styles.update(dict.fromkeys(styles, b'|'))
1006 styles.update(dict.fromkeys(styles, b'|'))
1000 else:
1007 else:
1001 edgetypes = {
1008 edgetypes = {
1002 b'parent': graphmod.PARENT,
1009 b'parent': graphmod.PARENT,
1003 b'grandparent': graphmod.GRANDPARENT,
1010 b'grandparent': graphmod.GRANDPARENT,
1004 b'missing': graphmod.MISSINGPARENT,
1011 b'missing': graphmod.MISSINGPARENT,
1005 }
1012 }
1006 for name, key in edgetypes.items():
1013 for name, key in edgetypes.items():
1007 # experimental config: experimental.graphstyle.*
1014 # experimental config: experimental.graphstyle.*
1008 styles[key] = ui.config(
1015 styles[key] = ui.config(
1009 b'experimental', b'graphstyle.%s' % name, styles[key]
1016 b'experimental', b'graphstyle.%s' % name, styles[key]
1010 )
1017 )
1011 if not styles[key]:
1018 if not styles[key]:
1012 styles[key] = None
1019 styles[key] = None
1013
1020
1014 # experimental config: experimental.graphshorten
1021 # experimental config: experimental.graphshorten
1015 state[b'graphshorten'] = ui.configbool(b'experimental', b'graphshorten')
1022 state[b'graphshorten'] = ui.configbool(b'experimental', b'graphshorten')
1016
1023
1017 for rev, type, ctx, parents in dag:
1024 for rev, type, ctx, parents in dag:
1018 char = formatnode(repo, ctx)
1025 char = formatnode(repo, ctx)
1019 copies = getcopies(ctx) if getcopies else None
1026 copies = getcopies(ctx) if getcopies else None
1020 edges = edgefn(type, char, state, rev, parents)
1027 edges = edgefn(type, char, state, rev, parents)
1021 firstedge = next(edges)
1028 firstedge = next(edges)
1022 width = firstedge[2]
1029 width = firstedge[2]
1023 displayer.show(
1030 displayer.show(
1024 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props)
1031 ctx, copies=copies, graphwidth=width, **pycompat.strkwargs(props)
1025 )
1032 )
1026 lines = displayer.hunk.pop(rev).split(b'\n')
1033 lines = displayer.hunk.pop(rev).split(b'\n')
1027 if not lines[-1]:
1034 if not lines[-1]:
1028 del lines[-1]
1035 del lines[-1]
1029 displayer.flush(ctx)
1036 displayer.flush(ctx)
1030 for type, char, width, coldata in itertools.chain([firstedge], edges):
1037 for type, char, width, coldata in itertools.chain([firstedge], edges):
1031 graphmod.ascii(ui, state, type, char, lines, coldata)
1038 graphmod.ascii(ui, state, type, char, lines, coldata)
1032 lines = []
1039 lines = []
1033 displayer.close()
1040 displayer.close()
1034
1041
1035
1042
1036 def displaygraphrevs(ui, repo, revs, displayer, getrenamed):
1043 def displaygraphrevs(ui, repo, revs, displayer, getrenamed):
1037 revdag = graphmod.dagwalker(repo, revs)
1044 revdag = graphmod.dagwalker(repo, revs)
1038 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed)
1045 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed)
1039
1046
1040
1047
1041 def displayrevs(ui, repo, revs, displayer, getcopies):
1048 def displayrevs(ui, repo, revs, displayer, getcopies):
1042 for rev in revs:
1049 for rev in revs:
1043 ctx = repo[rev]
1050 ctx = repo[rev]
1044 copies = getcopies(ctx) if getcopies else None
1051 copies = getcopies(ctx) if getcopies else None
1045 displayer.show(ctx, copies=copies)
1052 displayer.show(ctx, copies=copies)
1046 displayer.flush(ctx)
1053 displayer.flush(ctx)
1047 displayer.close()
1054 displayer.close()
1048
1055
1049
1056
1050 def checkunsupportedgraphflags(pats, opts):
1057 def checkunsupportedgraphflags(pats, opts):
1051 for op in [b"newest_first"]:
1058 for op in [b"newest_first"]:
1052 if op in opts and opts[op]:
1059 if op in opts and opts[op]:
1053 raise error.Abort(
1060 raise error.Abort(
1054 _(b"-G/--graph option is incompatible with --%s")
1061 _(b"-G/--graph option is incompatible with --%s")
1055 % op.replace(b"_", b"-")
1062 % op.replace(b"_", b"-")
1056 )
1063 )
1057
1064
1058
1065
1059 def graphrevs(repo, nodes, opts):
1066 def graphrevs(repo, nodes, opts):
1060 limit = getlimit(opts)
1067 limit = getlimit(opts)
1061 nodes.reverse()
1068 nodes.reverse()
1062 if limit is not None:
1069 if limit is not None:
1063 nodes = nodes[:limit]
1070 nodes = nodes[:limit]
1064 return graphmod.nodes(repo, nodes)
1071 return graphmod.nodes(repo, nodes)
@@ -1,1878 +1,1932 b''
1 Test template map files and styles
1 Test template map files and styles
2 ==================================
2 ==================================
3
3
4 $ hg init a
4 $ hg init a
5 $ cd a
5 $ cd a
6 $ echo a > a
6 $ echo a > a
7 $ hg add a
7 $ hg add a
8 $ echo line 1 > b
8 $ echo line 1 > b
9 $ echo line 2 >> b
9 $ echo line 2 >> b
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11
11
12 $ hg add b
12 $ hg add b
13 $ echo other 1 > c
13 $ echo other 1 > c
14 $ echo other 2 >> c
14 $ echo other 2 >> c
15 $ echo >> c
15 $ echo >> c
16 $ echo other 3 >> c
16 $ echo other 3 >> c
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18
18
19 $ hg add c
19 $ hg add c
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 $ echo c >> c
21 $ echo c >> c
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23
23
24 $ echo foo > .hg/branch
24 $ echo foo > .hg/branch
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26
26
27 $ hg co -q 3
27 $ hg co -q 3
28 $ echo other 4 >> d
28 $ echo other 4 >> d
29 $ hg add d
29 $ hg add d
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31
31
32 $ hg merge -q foo
32 $ hg merge -q foo
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34
34
35 Second branch starting at nullrev:
35 Second branch starting at nullrev:
36
36
37 $ hg update null
37 $ hg update null
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
39 $ echo second > second
39 $ echo second > second
40 $ hg add second
40 $ hg add second
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
42 created new head
42 created new head
43
43
44 $ echo third > third
44 $ echo third > third
45 $ hg add third
45 $ hg add third
46 $ hg mv second fourth
46 $ hg mv second fourth
47 $ hg commit -m third -d "2020-01-01 10:01"
47 $ hg commit -m third -d "2020-01-01 10:01"
48
48
49 Make sure user/global hgrc does not affect tests
49 Make sure user/global hgrc does not affect tests
50
50
51 $ echo '[ui]' > .hg/hgrc
51 $ echo '[ui]' > .hg/hgrc
52 $ echo 'logtemplate =' >> .hg/hgrc
52 $ echo 'logtemplate =' >> .hg/hgrc
53 $ echo 'style =' >> .hg/hgrc
53 $ echo 'style =' >> .hg/hgrc
54
54
55 Add some simple styles to settings
55 Add some simple styles to settings
56
56
57 $ cat <<'EOF' >> .hg/hgrc
57 $ cat <<'EOF' >> .hg/hgrc
58 > [templates]
58 > [templates]
59 > simple = "{rev}\n"
59 > simple = "{rev}\n"
60 > simple2 = {rev}\n
60 > simple2 = {rev}\n
61 > rev = "should not precede {rev} keyword\n"
61 > rev = "should not precede {rev} keyword\n"
62 > EOF
62 > EOF
63
63
64 $ hg log -l1 -Tsimple
64 $ hg log -l1 -Tsimple
65 8
65 8
66 $ hg log -l1 -Tsimple2
66 $ hg log -l1 -Tsimple2
67 8
67 8
68 $ hg log -l1 -Trev
68 $ hg log -l1 -Trev
69 should not precede 8 keyword
69 should not precede 8 keyword
70 $ hg log -l1 -T '{simple}'
70 $ hg log -l1 -T '{simple}'
71 8
71 8
72
72
73 Map file shouldn't see user templates:
73 Map file shouldn't see user templates:
74
74
75 $ cat <<EOF > tmpl
75 $ cat <<EOF > tmpl
76 > changeset = 'nothing expanded:{simple}\n'
76 > changeset = 'nothing expanded:{simple}\n'
77 > EOF
77 > EOF
78 $ hg log -l1 --style ./tmpl
78 $ hg log -l1 --style ./tmpl
79 nothing expanded:
79 nothing expanded:
80
80
81 Test templates and style maps in files:
81 Test templates and style maps in files:
82
82
83 $ echo "{rev}" > tmpl
83 $ echo "{rev}" > tmpl
84 $ hg log -l1 -T./tmpl
84 $ hg log -l1 -T./tmpl
85 8
85 8
86 $ hg log -l1 -Tblah/blah
86 $ hg log -l1 -Tblah/blah
87 blah/blah (no-eol)
87 blah/blah (no-eol)
88
88
89 $ printf 'changeset = "{rev}\\n"\n' > map-simple
89 $ printf 'changeset = "{rev}\\n"\n' > map-simple
90 $ hg log -l1 -T./map-simple
90 $ hg log -l1 -T./map-simple
91 8
91 8
92
92
93 a map file may have [templates] and [templatealias] sections:
93 a map file may have [templates] and [templatealias] sections:
94
94
95 $ cat <<'EOF' > map-simple
95 $ cat <<'EOF' > map-simple
96 > [templates]
96 > [templates]
97 > changeset = "{a}\n"
97 > changeset = "{a}\n"
98 > [templatealias]
98 > [templatealias]
99 > a = rev
99 > a = rev
100 > EOF
100 > EOF
101 $ hg log -l1 -T./map-simple
101 $ hg log -l1 -T./map-simple
102 8
102 8
103
103
104 so it can be included in hgrc
104 so it can be included in hgrc
105
105
106 $ cat <<EOF > myhgrc
106 $ cat <<EOF > myhgrc
107 > %include $HGRCPATH
107 > %include $HGRCPATH
108 > %include map-simple
108 > %include map-simple
109 > [templates]
109 > [templates]
110 > foo = "{changeset}"
110 > foo = "{changeset}"
111 > EOF
111 > EOF
112 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
112 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
113 8
113 8
114 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
114 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
115 8
115 8
116
116
117 Test template map inheritance
117 Test template map inheritance
118
118
119 $ echo "__base__ = map-cmdline.default" > map-simple
119 $ echo "__base__ = map-cmdline.default" > map-simple
120 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
120 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
121 $ hg log -l1 -T./map-simple
121 $ hg log -l1 -T./map-simple
122 changeset: ***8***
122 changeset: ***8***
123 tag: tip
123 tag: tip
124 user: test
124 user: test
125 date: Wed Jan 01 10:01:00 2020 +0000
125 date: Wed Jan 01 10:01:00 2020 +0000
126 summary: third
126 summary: third
127
127
128
128
129 Test docheader, docfooter and separator in template map
129 Test docheader, docfooter and separator in template map
130
130
131 $ cat <<'EOF' > map-myjson
131 $ cat <<'EOF' > map-myjson
132 > docheader = '\{\n'
132 > docheader = '\{\n'
133 > docfooter = '\n}\n'
133 > docfooter = '\n}\n'
134 > separator = ',\n'
134 > separator = ',\n'
135 > changeset = ' {dict(rev, node|short)|json}'
135 > changeset = ' {dict(rev, node|short)|json}'
136 > EOF
136 > EOF
137 $ hg log -l2 -T./map-myjson
137 $ hg log -l2 -T./map-myjson
138 {
138 {
139 {"node": "95c24699272e", "rev": 8},
139 {"node": "95c24699272e", "rev": 8},
140 {"node": "29114dbae42b", "rev": 7}
140 {"node": "29114dbae42b", "rev": 7}
141 }
141 }
142
142
143 Test docheader, docfooter and separator in [templates] section
143 Test docheader, docfooter and separator in [templates] section
144
144
145 $ cat <<'EOF' >> .hg/hgrc
145 $ cat <<'EOF' >> .hg/hgrc
146 > [templates]
146 > [templates]
147 > myjson = ' {dict(rev, node|short)|json}'
147 > myjson = ' {dict(rev, node|short)|json}'
148 > myjson:docheader = '\{\n'
148 > myjson:docheader = '\{\n'
149 > myjson:docfooter = '\n}\n'
149 > myjson:docfooter = '\n}\n'
150 > myjson:separator = ',\n'
150 > myjson:separator = ',\n'
151 > :docheader = 'should not be selected as a docheader for literal templates\n'
151 > :docheader = 'should not be selected as a docheader for literal templates\n'
152 > EOF
152 > EOF
153 $ hg log -l2 -Tmyjson
153 $ hg log -l2 -Tmyjson
154 {
154 {
155 {"node": "95c24699272e", "rev": 8},
155 {"node": "95c24699272e", "rev": 8},
156 {"node": "29114dbae42b", "rev": 7}
156 {"node": "29114dbae42b", "rev": 7}
157 }
157 }
158 $ hg log -l1 -T'{rev}\n'
158 $ hg log -l1 -T'{rev}\n'
159 8
159 8
160
160
161 Template should precede style option
161 Template should precede style option
162
162
163 $ hg log -l1 --style default -T '{rev}\n'
163 $ hg log -l1 --style default -T '{rev}\n'
164 8
164 8
165
165
166 Add a commit with empty description, to ensure that the templates
166 Add a commit with empty description, to ensure that the templates
167 below will omit the description line.
167 below will omit the description line.
168
168
169 $ echo c >> c
169 $ echo c >> c
170 $ hg add c
170 $ hg add c
171 $ hg commit -qm ' '
171 $ hg commit -qm ' '
172
172
173 Default style is like normal output. Phases style should be the same
173 Default style is like normal output. Phases style should be the same
174 as default style, except for extra phase lines.
174 as default style, except for extra phase lines.
175
175
176 $ hg log > log.out
176 $ hg log > log.out
177 $ hg log --style default > style.out
177 $ hg log --style default > style.out
178 $ cmp log.out style.out || diff -u log.out style.out
178 $ cmp log.out style.out || diff -u log.out style.out
179 $ hg log -T phases > phases.out
179 $ hg log -T phases > phases.out
180 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
180 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
181 +phase: draft
181 +phase: draft
182 +phase: draft
182 +phase: draft
183 +phase: draft
183 +phase: draft
184 +phase: draft
184 +phase: draft
185 +phase: draft
185 +phase: draft
186 +phase: draft
186 +phase: draft
187 +phase: draft
187 +phase: draft
188 +phase: draft
188 +phase: draft
189 +phase: draft
189 +phase: draft
190 +phase: draft
190 +phase: draft
191
191
192 $ hg log -v > log.out
192 $ hg log -v > log.out
193 $ hg log -v --style default > style.out
193 $ hg log -v --style default > style.out
194 $ cmp log.out style.out || diff -u log.out style.out
194 $ cmp log.out style.out || diff -u log.out style.out
195 $ hg log -v -T phases > phases.out
195 $ hg log -v -T phases > phases.out
196 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
196 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
197 +phase: draft
197 +phase: draft
198 +phase: draft
198 +phase: draft
199 +phase: draft
199 +phase: draft
200 +phase: draft
200 +phase: draft
201 +phase: draft
201 +phase: draft
202 +phase: draft
202 +phase: draft
203 +phase: draft
203 +phase: draft
204 +phase: draft
204 +phase: draft
205 +phase: draft
205 +phase: draft
206 +phase: draft
206 +phase: draft
207
207
208 $ hg log -q > log.out
208 $ hg log -q > log.out
209 $ hg log -q --style default > style.out
209 $ hg log -q --style default > style.out
210 $ cmp log.out style.out || diff -u log.out style.out
210 $ cmp log.out style.out || diff -u log.out style.out
211 $ hg log -q -T phases > phases.out
211 $ hg log -q -T phases > phases.out
212 $ cmp log.out phases.out || diff -u log.out phases.out
212 $ cmp log.out phases.out || diff -u log.out phases.out
213
213
214 $ hg log --debug > log.out
214 $ hg log --debug > log.out
215 $ hg log --debug --style default > style.out
215 $ hg log --debug --style default > style.out
216 $ cmp log.out style.out || diff -u log.out style.out
216 $ cmp log.out style.out || diff -u log.out style.out
217 $ hg log --debug -T phases > phases.out
217 $ hg log --debug -T phases > phases.out
218 $ cmp log.out phases.out || diff -u log.out phases.out
218 $ cmp log.out phases.out || diff -u log.out phases.out
219
219
220 Default style of working-directory revision should also be the same (but
220 Default style of working-directory revision should also be the same (but
221 date may change while running tests):
221 date may change while running tests):
222
222
223 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
223 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
224 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
224 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
225 $ cmp log.out style.out || diff -u log.out style.out
225 $ cmp log.out style.out || diff -u log.out style.out
226
226
227 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
227 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
228 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
228 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
229 $ cmp log.out style.out || diff -u log.out style.out
229 $ cmp log.out style.out || diff -u log.out style.out
230
230
231 $ hg log -r 'wdir()' -q > log.out
231 $ hg log -r 'wdir()' -q > log.out
232 $ hg log -r 'wdir()' -q --style default > style.out
232 $ hg log -r 'wdir()' -q --style default > style.out
233 $ cmp log.out style.out || diff -u log.out style.out
233 $ cmp log.out style.out || diff -u log.out style.out
234
234
235 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
235 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
236 $ hg log -r 'wdir()' --debug --style default \
236 $ hg log -r 'wdir()' --debug --style default \
237 > | sed 's|^date:.*|date:|' > style.out
237 > | sed 's|^date:.*|date:|' > style.out
238 $ cmp log.out style.out || diff -u log.out style.out
238 $ cmp log.out style.out || diff -u log.out style.out
239
239
240 Default style should also preserve color information (issue2866):
240 Default style should also preserve color information (issue2866):
241
241
242 $ cp $HGRCPATH $HGRCPATH-bak
242 $ cp $HGRCPATH $HGRCPATH-bak
243 $ cat <<EOF >> $HGRCPATH
243 $ cat <<EOF >> $HGRCPATH
244 > [extensions]
244 > [extensions]
245 > color=
245 > color=
246 > EOF
246 > EOF
247
247
248 $ hg --color=debug log > log.out
248 $ hg --color=debug log > log.out
249 $ hg --color=debug log --style default > style.out
249 $ hg --color=debug log --style default > style.out
250 $ cmp log.out style.out || diff -u log.out style.out
250 $ cmp log.out style.out || diff -u log.out style.out
251 $ hg --color=debug log -T phases > phases.out
251 $ hg --color=debug log -T phases > phases.out
252 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
252 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
253 +[log.phase|phase: draft]
253 +[log.phase|phase: draft]
254 +[log.phase|phase: draft]
254 +[log.phase|phase: draft]
255 +[log.phase|phase: draft]
255 +[log.phase|phase: draft]
256 +[log.phase|phase: draft]
256 +[log.phase|phase: draft]
257 +[log.phase|phase: draft]
257 +[log.phase|phase: draft]
258 +[log.phase|phase: draft]
258 +[log.phase|phase: draft]
259 +[log.phase|phase: draft]
259 +[log.phase|phase: draft]
260 +[log.phase|phase: draft]
260 +[log.phase|phase: draft]
261 +[log.phase|phase: draft]
261 +[log.phase|phase: draft]
262 +[log.phase|phase: draft]
262 +[log.phase|phase: draft]
263
263
264 $ hg --color=debug -v log > log.out
264 $ hg --color=debug -v log > log.out
265 $ hg --color=debug -v log --style default > style.out
265 $ hg --color=debug -v log --style default > style.out
266 $ cmp log.out style.out || diff -u log.out style.out
266 $ cmp log.out style.out || diff -u log.out style.out
267 $ hg --color=debug -v log -T phases > phases.out
267 $ hg --color=debug -v log -T phases > phases.out
268 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
268 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
269 +[log.phase|phase: draft]
269 +[log.phase|phase: draft]
270 +[log.phase|phase: draft]
270 +[log.phase|phase: draft]
271 +[log.phase|phase: draft]
271 +[log.phase|phase: draft]
272 +[log.phase|phase: draft]
272 +[log.phase|phase: draft]
273 +[log.phase|phase: draft]
273 +[log.phase|phase: draft]
274 +[log.phase|phase: draft]
274 +[log.phase|phase: draft]
275 +[log.phase|phase: draft]
275 +[log.phase|phase: draft]
276 +[log.phase|phase: draft]
276 +[log.phase|phase: draft]
277 +[log.phase|phase: draft]
277 +[log.phase|phase: draft]
278 +[log.phase|phase: draft]
278 +[log.phase|phase: draft]
279
279
280 $ hg --color=debug -q log > log.out
280 $ hg --color=debug -q log > log.out
281 $ hg --color=debug -q log --style default > style.out
281 $ hg --color=debug -q log --style default > style.out
282 $ cmp log.out style.out || diff -u log.out style.out
282 $ cmp log.out style.out || diff -u log.out style.out
283 $ hg --color=debug -q log -T phases > phases.out
283 $ hg --color=debug -q log -T phases > phases.out
284 $ cmp log.out phases.out || diff -u log.out phases.out
284 $ cmp log.out phases.out || diff -u log.out phases.out
285
285
286 $ hg --color=debug --debug log > log.out
286 $ hg --color=debug --debug log > log.out
287 $ hg --color=debug --debug log --style default > style.out
287 $ hg --color=debug --debug log --style default > style.out
288 $ cmp log.out style.out || diff -u log.out style.out
288 $ cmp log.out style.out || diff -u log.out style.out
289 $ hg --color=debug --debug log -T phases > phases.out
289 $ hg --color=debug --debug log -T phases > phases.out
290 $ cmp log.out phases.out || diff -u log.out phases.out
290 $ cmp log.out phases.out || diff -u log.out phases.out
291
291
292 $ mv $HGRCPATH-bak $HGRCPATH
292 $ mv $HGRCPATH-bak $HGRCPATH
293
293
294 Remove commit with empty commit message, so as to not pollute further
294 Remove commit with empty commit message, so as to not pollute further
295 tests.
295 tests.
296
296
297 $ hg --config extensions.strip= strip -q .
297 $ hg --config extensions.strip= strip -q .
298
298
299 Revision with no copies (used to print a traceback):
299 Revision with no copies (used to print a traceback):
300
300
301 $ hg tip -v --template '\n'
301 $ hg tip -v --template '\n'
302
302
303
303
304 Compact style works:
304 Compact style works:
305
305
306 $ hg log -Tcompact
306 $ hg log -Tcompact
307 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
307 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
308 third
308 third
309
309
310 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
310 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
311 second
311 second
312
312
313 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
313 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
314 merge
314 merge
315
315
316 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
316 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
317 new head
317 new head
318
318
319 4 bbe44766e73d 1970-01-17 04:53 +0000 person
319 4 bbe44766e73d 1970-01-17 04:53 +0000 person
320 new branch
320 new branch
321
321
322 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
322 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
323 no user, no domain
323 no user, no domain
324
324
325 2 97054abb4ab8 1970-01-14 21:20 +0000 other
325 2 97054abb4ab8 1970-01-14 21:20 +0000 other
326 no person
326 no person
327
327
328 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
328 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
329 other 1
329 other 1
330
330
331 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
331 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
332 line 1
332 line 1
333
333
334
334
335 $ hg log -v --style compact
335 $ hg log -v --style compact
336 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
336 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
337 third
337 third
338
338
339 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
339 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
340 second
340 second
341
341
342 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
342 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
343 merge
343 merge
344
344
345 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
345 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
346 new head
346 new head
347
347
348 4 bbe44766e73d 1970-01-17 04:53 +0000 person
348 4 bbe44766e73d 1970-01-17 04:53 +0000 person
349 new branch
349 new branch
350
350
351 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
351 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
352 no user, no domain
352 no user, no domain
353
353
354 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
354 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
355 no person
355 no person
356
356
357 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
357 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
358 other 1
358 other 1
359 other 2
359 other 2
360
360
361 other 3
361 other 3
362
362
363 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
363 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
364 line 1
364 line 1
365 line 2
365 line 2
366
366
367
367
368 $ hg log --debug --style compact
368 $ hg log --debug --style compact
369 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
369 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
370 third
370 third
371
371
372 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
372 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
373 second
373 second
374
374
375 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
375 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
376 merge
376 merge
377
377
378 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
378 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
379 new head
379 new head
380
380
381 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
381 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
382 new branch
382 new branch
383
383
384 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
384 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
385 no user, no domain
385 no user, no domain
386
386
387 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
387 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
388 no person
388 no person
389
389
390 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
390 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
391 other 1
391 other 1
392 other 2
392 other 2
393
393
394 other 3
394 other 3
395
395
396 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
396 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
397 line 1
397 line 1
398 line 2
398 line 2
399
399
400
400
401 Test xml styles:
401 Test xml styles:
402
402
403 $ hg log --style xml -r 'not all()'
403 $ hg log --style xml -r 'not all()'
404 <?xml version="1.0"?>
404 <?xml version="1.0"?>
405 <log>
405 <log>
406 </log>
406 </log>
407
407
408 $ hg log --style xml
408 $ hg log --style xml
409 <?xml version="1.0"?>
409 <?xml version="1.0"?>
410 <log>
410 <log>
411 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
411 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
412 <tag>tip</tag>
412 <tag>tip</tag>
413 <author email="test">test</author>
413 <author email="test">test</author>
414 <date>2020-01-01T10:01:00+00:00</date>
414 <date>2020-01-01T10:01:00+00:00</date>
415 <msg xml:space="preserve">third</msg>
415 <msg xml:space="preserve">third</msg>
416 </logentry>
416 </logentry>
417 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
417 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
418 <parent revision="-1" node="0000000000000000000000000000000000000000" />
418 <parent revision="-1" node="0000000000000000000000000000000000000000" />
419 <author email="user@hostname">User Name</author>
419 <author email="user@hostname">User Name</author>
420 <date>1970-01-12T13:46:40+00:00</date>
420 <date>1970-01-12T13:46:40+00:00</date>
421 <msg xml:space="preserve">second</msg>
421 <msg xml:space="preserve">second</msg>
422 </logentry>
422 </logentry>
423 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
423 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
424 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
424 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
425 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
425 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
426 <author email="person">person</author>
426 <author email="person">person</author>
427 <date>1970-01-18T08:40:01+00:00</date>
427 <date>1970-01-18T08:40:01+00:00</date>
428 <msg xml:space="preserve">merge</msg>
428 <msg xml:space="preserve">merge</msg>
429 </logentry>
429 </logentry>
430 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
430 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
431 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
431 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
432 <author email="person">person</author>
432 <author email="person">person</author>
433 <date>1970-01-18T08:40:00+00:00</date>
433 <date>1970-01-18T08:40:00+00:00</date>
434 <msg xml:space="preserve">new head</msg>
434 <msg xml:space="preserve">new head</msg>
435 </logentry>
435 </logentry>
436 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
436 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
437 <branch>foo</branch>
437 <branch>foo</branch>
438 <author email="person">person</author>
438 <author email="person">person</author>
439 <date>1970-01-17T04:53:20+00:00</date>
439 <date>1970-01-17T04:53:20+00:00</date>
440 <msg xml:space="preserve">new branch</msg>
440 <msg xml:space="preserve">new branch</msg>
441 </logentry>
441 </logentry>
442 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
442 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
443 <author email="person">person</author>
443 <author email="person">person</author>
444 <date>1970-01-16T01:06:40+00:00</date>
444 <date>1970-01-16T01:06:40+00:00</date>
445 <msg xml:space="preserve">no user, no domain</msg>
445 <msg xml:space="preserve">no user, no domain</msg>
446 </logentry>
446 </logentry>
447 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
447 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
448 <author email="other@place">other</author>
448 <author email="other@place">other</author>
449 <date>1970-01-14T21:20:00+00:00</date>
449 <date>1970-01-14T21:20:00+00:00</date>
450 <msg xml:space="preserve">no person</msg>
450 <msg xml:space="preserve">no person</msg>
451 </logentry>
451 </logentry>
452 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
452 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
453 <author email="other@place">A. N. Other</author>
453 <author email="other@place">A. N. Other</author>
454 <date>1970-01-13T17:33:20+00:00</date>
454 <date>1970-01-13T17:33:20+00:00</date>
455 <msg xml:space="preserve">other 1
455 <msg xml:space="preserve">other 1
456 other 2
456 other 2
457
457
458 other 3</msg>
458 other 3</msg>
459 </logentry>
459 </logentry>
460 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
460 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
461 <author email="user@hostname">User Name</author>
461 <author email="user@hostname">User Name</author>
462 <date>1970-01-12T13:46:40+00:00</date>
462 <date>1970-01-12T13:46:40+00:00</date>
463 <msg xml:space="preserve">line 1
463 <msg xml:space="preserve">line 1
464 line 2</msg>
464 line 2</msg>
465 </logentry>
465 </logentry>
466 </log>
466 </log>
467
467
468 $ hg log -v --style xml
468 $ hg log -v --style xml
469 <?xml version="1.0"?>
469 <?xml version="1.0"?>
470 <log>
470 <log>
471 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
471 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
472 <tag>tip</tag>
472 <tag>tip</tag>
473 <author email="test">test</author>
473 <author email="test">test</author>
474 <date>2020-01-01T10:01:00+00:00</date>
474 <date>2020-01-01T10:01:00+00:00</date>
475 <msg xml:space="preserve">third</msg>
475 <msg xml:space="preserve">third</msg>
476 <paths>
476 <paths>
477 <path action="A">fourth</path>
477 <path action="A">fourth</path>
478 <path action="A">third</path>
478 <path action="A">third</path>
479 <path action="R">second</path>
479 <path action="R">second</path>
480 </paths>
480 </paths>
481 <copies>
481 <copies>
482 <copy source="second">fourth</copy>
482 <copy source="second">fourth</copy>
483 </copies>
483 </copies>
484 </logentry>
484 </logentry>
485 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
485 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
486 <parent revision="-1" node="0000000000000000000000000000000000000000" />
486 <parent revision="-1" node="0000000000000000000000000000000000000000" />
487 <author email="user@hostname">User Name</author>
487 <author email="user@hostname">User Name</author>
488 <date>1970-01-12T13:46:40+00:00</date>
488 <date>1970-01-12T13:46:40+00:00</date>
489 <msg xml:space="preserve">second</msg>
489 <msg xml:space="preserve">second</msg>
490 <paths>
490 <paths>
491 <path action="A">second</path>
491 <path action="A">second</path>
492 </paths>
492 </paths>
493 </logentry>
493 </logentry>
494 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
494 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
495 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
495 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
496 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
496 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
497 <author email="person">person</author>
497 <author email="person">person</author>
498 <date>1970-01-18T08:40:01+00:00</date>
498 <date>1970-01-18T08:40:01+00:00</date>
499 <msg xml:space="preserve">merge</msg>
499 <msg xml:space="preserve">merge</msg>
500 <paths>
500 <paths>
501 </paths>
501 </paths>
502 </logentry>
502 </logentry>
503 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
503 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
504 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
504 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
505 <author email="person">person</author>
505 <author email="person">person</author>
506 <date>1970-01-18T08:40:00+00:00</date>
506 <date>1970-01-18T08:40:00+00:00</date>
507 <msg xml:space="preserve">new head</msg>
507 <msg xml:space="preserve">new head</msg>
508 <paths>
508 <paths>
509 <path action="A">d</path>
509 <path action="A">d</path>
510 </paths>
510 </paths>
511 </logentry>
511 </logentry>
512 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
512 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
513 <branch>foo</branch>
513 <branch>foo</branch>
514 <author email="person">person</author>
514 <author email="person">person</author>
515 <date>1970-01-17T04:53:20+00:00</date>
515 <date>1970-01-17T04:53:20+00:00</date>
516 <msg xml:space="preserve">new branch</msg>
516 <msg xml:space="preserve">new branch</msg>
517 <paths>
517 <paths>
518 </paths>
518 </paths>
519 </logentry>
519 </logentry>
520 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
520 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
521 <author email="person">person</author>
521 <author email="person">person</author>
522 <date>1970-01-16T01:06:40+00:00</date>
522 <date>1970-01-16T01:06:40+00:00</date>
523 <msg xml:space="preserve">no user, no domain</msg>
523 <msg xml:space="preserve">no user, no domain</msg>
524 <paths>
524 <paths>
525 <path action="M">c</path>
525 <path action="M">c</path>
526 </paths>
526 </paths>
527 </logentry>
527 </logentry>
528 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
528 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
529 <author email="other@place">other</author>
529 <author email="other@place">other</author>
530 <date>1970-01-14T21:20:00+00:00</date>
530 <date>1970-01-14T21:20:00+00:00</date>
531 <msg xml:space="preserve">no person</msg>
531 <msg xml:space="preserve">no person</msg>
532 <paths>
532 <paths>
533 <path action="A">c</path>
533 <path action="A">c</path>
534 </paths>
534 </paths>
535 </logentry>
535 </logentry>
536 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
536 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
537 <author email="other@place">A. N. Other</author>
537 <author email="other@place">A. N. Other</author>
538 <date>1970-01-13T17:33:20+00:00</date>
538 <date>1970-01-13T17:33:20+00:00</date>
539 <msg xml:space="preserve">other 1
539 <msg xml:space="preserve">other 1
540 other 2
540 other 2
541
541
542 other 3</msg>
542 other 3</msg>
543 <paths>
543 <paths>
544 <path action="A">b</path>
544 <path action="A">b</path>
545 </paths>
545 </paths>
546 </logentry>
546 </logentry>
547 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
547 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
548 <author email="user@hostname">User Name</author>
548 <author email="user@hostname">User Name</author>
549 <date>1970-01-12T13:46:40+00:00</date>
549 <date>1970-01-12T13:46:40+00:00</date>
550 <msg xml:space="preserve">line 1
550 <msg xml:space="preserve">line 1
551 line 2</msg>
551 line 2</msg>
552 <paths>
552 <paths>
553 <path action="A">a</path>
553 <path action="A">a</path>
554 </paths>
554 </paths>
555 </logentry>
555 </logentry>
556 </log>
556 </log>
557
557
558 $ hg log --debug --style xml
558 $ hg log --debug --style xml
559 <?xml version="1.0"?>
559 <?xml version="1.0"?>
560 <log>
560 <log>
561 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
561 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
562 <tag>tip</tag>
562 <tag>tip</tag>
563 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
563 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
564 <parent revision="-1" node="0000000000000000000000000000000000000000" />
564 <parent revision="-1" node="0000000000000000000000000000000000000000" />
565 <author email="test">test</author>
565 <author email="test">test</author>
566 <date>2020-01-01T10:01:00+00:00</date>
566 <date>2020-01-01T10:01:00+00:00</date>
567 <msg xml:space="preserve">third</msg>
567 <msg xml:space="preserve">third</msg>
568 <paths>
568 <paths>
569 <path action="A">fourth</path>
569 <path action="A">fourth</path>
570 <path action="A">third</path>
570 <path action="A">third</path>
571 <path action="R">second</path>
571 <path action="R">second</path>
572 </paths>
572 </paths>
573 <copies>
573 <copies>
574 <copy source="second">fourth</copy>
574 <copy source="second">fourth</copy>
575 </copies>
575 </copies>
576 <extra key="branch">default</extra>
576 <extra key="branch">default</extra>
577 </logentry>
577 </logentry>
578 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
578 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
579 <parent revision="-1" node="0000000000000000000000000000000000000000" />
579 <parent revision="-1" node="0000000000000000000000000000000000000000" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
580 <parent revision="-1" node="0000000000000000000000000000000000000000" />
581 <author email="user@hostname">User Name</author>
581 <author email="user@hostname">User Name</author>
582 <date>1970-01-12T13:46:40+00:00</date>
582 <date>1970-01-12T13:46:40+00:00</date>
583 <msg xml:space="preserve">second</msg>
583 <msg xml:space="preserve">second</msg>
584 <paths>
584 <paths>
585 <path action="A">second</path>
585 <path action="A">second</path>
586 </paths>
586 </paths>
587 <extra key="branch">default</extra>
587 <extra key="branch">default</extra>
588 </logentry>
588 </logentry>
589 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
589 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
590 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
590 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
591 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
591 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
592 <author email="person">person</author>
592 <author email="person">person</author>
593 <date>1970-01-18T08:40:01+00:00</date>
593 <date>1970-01-18T08:40:01+00:00</date>
594 <msg xml:space="preserve">merge</msg>
594 <msg xml:space="preserve">merge</msg>
595 <paths>
595 <paths>
596 </paths>
596 </paths>
597 <extra key="branch">default</extra>
597 <extra key="branch">default</extra>
598 </logentry>
598 </logentry>
599 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
599 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
600 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
600 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
601 <parent revision="-1" node="0000000000000000000000000000000000000000" />
601 <parent revision="-1" node="0000000000000000000000000000000000000000" />
602 <author email="person">person</author>
602 <author email="person">person</author>
603 <date>1970-01-18T08:40:00+00:00</date>
603 <date>1970-01-18T08:40:00+00:00</date>
604 <msg xml:space="preserve">new head</msg>
604 <msg xml:space="preserve">new head</msg>
605 <paths>
605 <paths>
606 <path action="A">d</path>
606 <path action="A">d</path>
607 </paths>
607 </paths>
608 <extra key="branch">default</extra>
608 <extra key="branch">default</extra>
609 </logentry>
609 </logentry>
610 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
610 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
611 <branch>foo</branch>
611 <branch>foo</branch>
612 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
612 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
613 <parent revision="-1" node="0000000000000000000000000000000000000000" />
613 <parent revision="-1" node="0000000000000000000000000000000000000000" />
614 <author email="person">person</author>
614 <author email="person">person</author>
615 <date>1970-01-17T04:53:20+00:00</date>
615 <date>1970-01-17T04:53:20+00:00</date>
616 <msg xml:space="preserve">new branch</msg>
616 <msg xml:space="preserve">new branch</msg>
617 <paths>
617 <paths>
618 </paths>
618 </paths>
619 <extra key="branch">foo</extra>
619 <extra key="branch">foo</extra>
620 </logentry>
620 </logentry>
621 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
621 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
622 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
622 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
623 <parent revision="-1" node="0000000000000000000000000000000000000000" />
623 <parent revision="-1" node="0000000000000000000000000000000000000000" />
624 <author email="person">person</author>
624 <author email="person">person</author>
625 <date>1970-01-16T01:06:40+00:00</date>
625 <date>1970-01-16T01:06:40+00:00</date>
626 <msg xml:space="preserve">no user, no domain</msg>
626 <msg xml:space="preserve">no user, no domain</msg>
627 <paths>
627 <paths>
628 <path action="M">c</path>
628 <path action="M">c</path>
629 </paths>
629 </paths>
630 <extra key="branch">default</extra>
630 <extra key="branch">default</extra>
631 </logentry>
631 </logentry>
632 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
632 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
633 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
633 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
634 <parent revision="-1" node="0000000000000000000000000000000000000000" />
634 <parent revision="-1" node="0000000000000000000000000000000000000000" />
635 <author email="other@place">other</author>
635 <author email="other@place">other</author>
636 <date>1970-01-14T21:20:00+00:00</date>
636 <date>1970-01-14T21:20:00+00:00</date>
637 <msg xml:space="preserve">no person</msg>
637 <msg xml:space="preserve">no person</msg>
638 <paths>
638 <paths>
639 <path action="A">c</path>
639 <path action="A">c</path>
640 </paths>
640 </paths>
641 <extra key="branch">default</extra>
641 <extra key="branch">default</extra>
642 </logentry>
642 </logentry>
643 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
643 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
644 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
644 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
645 <parent revision="-1" node="0000000000000000000000000000000000000000" />
645 <parent revision="-1" node="0000000000000000000000000000000000000000" />
646 <author email="other@place">A. N. Other</author>
646 <author email="other@place">A. N. Other</author>
647 <date>1970-01-13T17:33:20+00:00</date>
647 <date>1970-01-13T17:33:20+00:00</date>
648 <msg xml:space="preserve">other 1
648 <msg xml:space="preserve">other 1
649 other 2
649 other 2
650
650
651 other 3</msg>
651 other 3</msg>
652 <paths>
652 <paths>
653 <path action="A">b</path>
653 <path action="A">b</path>
654 </paths>
654 </paths>
655 <extra key="branch">default</extra>
655 <extra key="branch">default</extra>
656 </logentry>
656 </logentry>
657 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
657 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
658 <parent revision="-1" node="0000000000000000000000000000000000000000" />
658 <parent revision="-1" node="0000000000000000000000000000000000000000" />
659 <parent revision="-1" node="0000000000000000000000000000000000000000" />
659 <parent revision="-1" node="0000000000000000000000000000000000000000" />
660 <author email="user@hostname">User Name</author>
660 <author email="user@hostname">User Name</author>
661 <date>1970-01-12T13:46:40+00:00</date>
661 <date>1970-01-12T13:46:40+00:00</date>
662 <msg xml:space="preserve">line 1
662 <msg xml:space="preserve">line 1
663 line 2</msg>
663 line 2</msg>
664 <paths>
664 <paths>
665 <path action="A">a</path>
665 <path action="A">a</path>
666 </paths>
666 </paths>
667 <extra key="branch">default</extra>
667 <extra key="branch">default</extra>
668 </logentry>
668 </logentry>
669 </log>
669 </log>
670
670
671
671
672 test CBOR style:
672 test CBOR style:
673
673
674 $ cat <<'EOF' > "$TESTTMP/decodecborarray.py"
674 $ cat <<'EOF' > "$TESTTMP/decodecborarray.py"
675 > from __future__ import absolute_import
675 > from __future__ import absolute_import
676 > from mercurial import (
676 > from mercurial import (
677 > dispatch,
677 > dispatch,
678 > pycompat,
678 > pycompat,
679 > )
679 > )
680 > from mercurial.utils import (
680 > from mercurial.utils import (
681 > cborutil,
681 > cborutil,
682 > stringutil,
682 > stringutil,
683 > )
683 > )
684 > dispatch.initstdio()
684 > dispatch.initstdio()
685 > data = pycompat.stdin.read()
685 > data = pycompat.stdin.read()
686 > # our CBOR decoder doesn't support parsing indefinite-length arrays,
686 > # our CBOR decoder doesn't support parsing indefinite-length arrays,
687 > # but the log output is indefinite stream by nature.
687 > # but the log output is indefinite stream by nature.
688 > assert data[:1] == cborutil.BEGIN_INDEFINITE_ARRAY
688 > assert data[:1] == cborutil.BEGIN_INDEFINITE_ARRAY
689 > assert data[-1:] == cborutil.BREAK
689 > assert data[-1:] == cborutil.BREAK
690 > items = cborutil.decodeall(data[1:-1])
690 > items = cborutil.decodeall(data[1:-1])
691 > pycompat.stdout.write(stringutil.pprint(items, indent=1) + b'\n')
691 > pycompat.stdout.write(stringutil.pprint(items, indent=1) + b'\n')
692 > EOF
692 > EOF
693
693
694 $ hg log -k nosuch -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
694 $ hg log -k nosuch -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
695 []
695 []
696
696
697 $ hg log -qr0:1 -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
697 $ hg log -qr0:1 -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
698 [
698 [
699 {
699 {
700 'node': '1e4e1b8f71e05681d422154f5421e385fec3454f',
700 'node': '1e4e1b8f71e05681d422154f5421e385fec3454f',
701 'rev': 0
701 'rev': 0
702 },
702 },
703 {
703 {
704 'node': 'b608e9d1a3f0273ccf70fb85fd6866b3482bf965',
704 'node': 'b608e9d1a3f0273ccf70fb85fd6866b3482bf965',
705 'rev': 1
705 'rev': 1
706 }
706 }
707 ]
707 ]
708
708
709 $ hg log -vpr . -Tcbor --stat | "$PYTHON" "$TESTTMP/decodecborarray.py"
709 $ hg log -vpr . -Tcbor --stat | "$PYTHON" "$TESTTMP/decodecborarray.py"
710 [
710 [
711 {
711 {
712 'bookmarks': [],
712 'bookmarks': [],
713 'branch': 'default',
713 'branch': 'default',
714 'date': [
714 'date': [
715 1577872860,
715 1577872860,
716 0
716 0
717 ],
717 ],
718 'desc': 'third',
718 'desc': 'third',
719 'diff': 'diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n',
719 'diff': 'diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n',
720 'diffstat': ' fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n',
720 'diffstat': ' fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n',
721 'files': [
721 'files': [
722 'fourth',
722 'fourth',
723 'second',
723 'second',
724 'third'
724 'third'
725 ],
725 ],
726 'node': '95c24699272ef57d062b8bccc32c878bf841784a',
726 'node': '95c24699272ef57d062b8bccc32c878bf841784a',
727 'parents': [
727 'parents': [
728 '29114dbae42b9f078cf2714dbe3a86bba8ec7453'
728 '29114dbae42b9f078cf2714dbe3a86bba8ec7453'
729 ],
729 ],
730 'phase': 'draft',
730 'phase': 'draft',
731 'rev': 8,
731 'rev': 8,
732 'tags': [
732 'tags': [
733 'tip'
733 'tip'
734 ],
734 ],
735 'user': 'test'
735 'user': 'test'
736 }
736 }
737 ]
737 ]
738
738
739 $ hg log -r . -T'cbor(rev, node|short)' | "$PYTHON" "$TESTTMP/decodecborarray.py"
739 $ hg log -r . -T'cbor(rev, node|short)' | "$PYTHON" "$TESTTMP/decodecborarray.py"
740 [
740 [
741 {
741 {
742 'node': '95c24699272e',
742 'node': '95c24699272e',
743 'rev': 8
743 'rev': 8
744 }
744 }
745 ]
745 ]
746
746
747 $ hg log -r . -T'cbor()' | "$PYTHON" "$TESTTMP/decodecborarray.py"
747 $ hg log -r . -T'cbor()' | "$PYTHON" "$TESTTMP/decodecborarray.py"
748 [
748 [
749 {}
749 {}
750 ]
750 ]
751
751
752 Test JSON style:
752 Test JSON style:
753
753
754 $ hg log -k nosuch -Tjson
754 $ hg log -k nosuch -Tjson
755 [
755 [
756 ]
756 ]
757
757
758 $ hg log -qr . -Tjson
758 $ hg log -qr . -Tjson
759 [
759 [
760 {
760 {
761 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
761 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
762 "rev": 8
762 "rev": 8
763 }
763 }
764 ]
764 ]
765
765
766 $ hg log -vpr . -Tjson --stat
766 $ hg log -vpr . -Tjson --stat
767 [
767 [
768 {
768 {
769 "bookmarks": [],
769 "bookmarks": [],
770 "branch": "default",
770 "branch": "default",
771 "date": [1577872860, 0],
771 "date": [1577872860, 0],
772 "desc": "third",
772 "desc": "third",
773 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n",
773 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n",
774 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
774 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
775 "files": ["fourth", "second", "third"],
775 "files": ["fourth", "second", "third"],
776 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
776 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
777 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
777 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
778 "phase": "draft",
778 "phase": "draft",
779 "rev": 8,
779 "rev": 8,
780 "tags": ["tip"],
780 "tags": ["tip"],
781 "user": "test"
781 "user": "test"
782 }
782 }
783 ]
783 ]
784
784
785 honor --git but not format-breaking diffopts
785 honor --git but not format-breaking diffopts
786 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
786 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
787 [
787 [
788 {
788 {
789 "bookmarks": [],
789 "bookmarks": [],
790 "branch": "default",
790 "branch": "default",
791 "date": [1577872860, 0],
791 "date": [1577872860, 0],
792 "desc": "third",
792 "desc": "third",
793 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n",
793 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n",
794 "files": ["fourth", "second", "third"],
794 "files": ["fourth", "second", "third"],
795 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
795 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
796 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
796 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
797 "phase": "draft",
797 "phase": "draft",
798 "rev": 8,
798 "rev": 8,
799 "tags": ["tip"],
799 "tags": ["tip"],
800 "user": "test"
800 "user": "test"
801 }
801 }
802 ]
802 ]
803
803
804 $ hg log -T json
804 $ hg log -T json
805 [
805 [
806 {
806 {
807 "bookmarks": [],
807 "bookmarks": [],
808 "branch": "default",
808 "branch": "default",
809 "date": [1577872860, 0],
809 "date": [1577872860, 0],
810 "desc": "third",
810 "desc": "third",
811 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
811 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
812 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
812 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
813 "phase": "draft",
813 "phase": "draft",
814 "rev": 8,
814 "rev": 8,
815 "tags": ["tip"],
815 "tags": ["tip"],
816 "user": "test"
816 "user": "test"
817 },
817 },
818 {
818 {
819 "bookmarks": [],
819 "bookmarks": [],
820 "branch": "default",
820 "branch": "default",
821 "date": [1000000, 0],
821 "date": [1000000, 0],
822 "desc": "second",
822 "desc": "second",
823 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
823 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
824 "parents": ["0000000000000000000000000000000000000000"],
824 "parents": ["0000000000000000000000000000000000000000"],
825 "phase": "draft",
825 "phase": "draft",
826 "rev": 7,
826 "rev": 7,
827 "tags": [],
827 "tags": [],
828 "user": "User Name <user@hostname>"
828 "user": "User Name <user@hostname>"
829 },
829 },
830 {
830 {
831 "bookmarks": [],
831 "bookmarks": [],
832 "branch": "default",
832 "branch": "default",
833 "date": [1500001, 0],
833 "date": [1500001, 0],
834 "desc": "merge",
834 "desc": "merge",
835 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
835 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
836 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
836 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
837 "phase": "draft",
837 "phase": "draft",
838 "rev": 6,
838 "rev": 6,
839 "tags": [],
839 "tags": [],
840 "user": "person"
840 "user": "person"
841 },
841 },
842 {
842 {
843 "bookmarks": [],
843 "bookmarks": [],
844 "branch": "default",
844 "branch": "default",
845 "date": [1500000, 0],
845 "date": [1500000, 0],
846 "desc": "new head",
846 "desc": "new head",
847 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
847 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
848 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
848 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
849 "phase": "draft",
849 "phase": "draft",
850 "rev": 5,
850 "rev": 5,
851 "tags": [],
851 "tags": [],
852 "user": "person"
852 "user": "person"
853 },
853 },
854 {
854 {
855 "bookmarks": [],
855 "bookmarks": [],
856 "branch": "foo",
856 "branch": "foo",
857 "date": [1400000, 0],
857 "date": [1400000, 0],
858 "desc": "new branch",
858 "desc": "new branch",
859 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
859 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
860 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
860 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
861 "phase": "draft",
861 "phase": "draft",
862 "rev": 4,
862 "rev": 4,
863 "tags": [],
863 "tags": [],
864 "user": "person"
864 "user": "person"
865 },
865 },
866 {
866 {
867 "bookmarks": [],
867 "bookmarks": [],
868 "branch": "default",
868 "branch": "default",
869 "date": [1300000, 0],
869 "date": [1300000, 0],
870 "desc": "no user, no domain",
870 "desc": "no user, no domain",
871 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
871 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
872 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
872 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
873 "phase": "draft",
873 "phase": "draft",
874 "rev": 3,
874 "rev": 3,
875 "tags": [],
875 "tags": [],
876 "user": "person"
876 "user": "person"
877 },
877 },
878 {
878 {
879 "bookmarks": [],
879 "bookmarks": [],
880 "branch": "default",
880 "branch": "default",
881 "date": [1200000, 0],
881 "date": [1200000, 0],
882 "desc": "no person",
882 "desc": "no person",
883 "node": "97054abb4ab824450e9164180baf491ae0078465",
883 "node": "97054abb4ab824450e9164180baf491ae0078465",
884 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
884 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
885 "phase": "draft",
885 "phase": "draft",
886 "rev": 2,
886 "rev": 2,
887 "tags": [],
887 "tags": [],
888 "user": "other@place"
888 "user": "other@place"
889 },
889 },
890 {
890 {
891 "bookmarks": [],
891 "bookmarks": [],
892 "branch": "default",
892 "branch": "default",
893 "date": [1100000, 0],
893 "date": [1100000, 0],
894 "desc": "other 1\nother 2\n\nother 3",
894 "desc": "other 1\nother 2\n\nother 3",
895 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
895 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
896 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
896 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
897 "phase": "draft",
897 "phase": "draft",
898 "rev": 1,
898 "rev": 1,
899 "tags": [],
899 "tags": [],
900 "user": "A. N. Other <other@place>"
900 "user": "A. N. Other <other@place>"
901 },
901 },
902 {
902 {
903 "bookmarks": [],
903 "bookmarks": [],
904 "branch": "default",
904 "branch": "default",
905 "date": [1000000, 0],
905 "date": [1000000, 0],
906 "desc": "line 1\nline 2",
906 "desc": "line 1\nline 2",
907 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
907 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
908 "parents": ["0000000000000000000000000000000000000000"],
908 "parents": ["0000000000000000000000000000000000000000"],
909 "phase": "draft",
909 "phase": "draft",
910 "rev": 0,
910 "rev": 0,
911 "tags": [],
911 "tags": [],
912 "user": "User Name <user@hostname>"
912 "user": "User Name <user@hostname>"
913 }
913 }
914 ]
914 ]
915
915
916 $ hg heads -v -Tjson
916 $ hg heads -v -Tjson
917 [
917 [
918 {
918 {
919 "bookmarks": [],
919 "bookmarks": [],
920 "branch": "default",
920 "branch": "default",
921 "date": [1577872860, 0],
921 "date": [1577872860, 0],
922 "desc": "third",
922 "desc": "third",
923 "files": ["fourth", "second", "third"],
923 "files": ["fourth", "second", "third"],
924 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
924 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
925 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
925 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
926 "phase": "draft",
926 "phase": "draft",
927 "rev": 8,
927 "rev": 8,
928 "tags": ["tip"],
928 "tags": ["tip"],
929 "user": "test"
929 "user": "test"
930 },
930 },
931 {
931 {
932 "bookmarks": [],
932 "bookmarks": [],
933 "branch": "default",
933 "branch": "default",
934 "date": [1500001, 0],
934 "date": [1500001, 0],
935 "desc": "merge",
935 "desc": "merge",
936 "files": [],
936 "files": [],
937 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
937 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
938 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
938 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
939 "phase": "draft",
939 "phase": "draft",
940 "rev": 6,
940 "rev": 6,
941 "tags": [],
941 "tags": [],
942 "user": "person"
942 "user": "person"
943 },
943 },
944 {
944 {
945 "bookmarks": [],
945 "bookmarks": [],
946 "branch": "foo",
946 "branch": "foo",
947 "date": [1400000, 0],
947 "date": [1400000, 0],
948 "desc": "new branch",
948 "desc": "new branch",
949 "files": [],
949 "files": [],
950 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
950 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
951 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
951 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
952 "phase": "draft",
952 "phase": "draft",
953 "rev": 4,
953 "rev": 4,
954 "tags": [],
954 "tags": [],
955 "user": "person"
955 "user": "person"
956 }
956 }
957 ]
957 ]
958
958
959 $ hg log --debug -Tjson
959 $ hg log --debug -Tjson
960 [
960 [
961 {
961 {
962 "added": ["fourth", "third"],
962 "added": ["fourth", "third"],
963 "bookmarks": [],
963 "bookmarks": [],
964 "branch": "default",
964 "branch": "default",
965 "date": [1577872860, 0],
965 "date": [1577872860, 0],
966 "desc": "third",
966 "desc": "third",
967 "extra": {"branch": "default"},
967 "extra": {"branch": "default"},
968 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
968 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
969 "modified": [],
969 "modified": [],
970 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
970 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
971 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
971 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
972 "phase": "draft",
972 "phase": "draft",
973 "removed": ["second"],
973 "removed": ["second"],
974 "rev": 8,
974 "rev": 8,
975 "tags": ["tip"],
975 "tags": ["tip"],
976 "user": "test"
976 "user": "test"
977 },
977 },
978 {
978 {
979 "added": ["second"],
979 "added": ["second"],
980 "bookmarks": [],
980 "bookmarks": [],
981 "branch": "default",
981 "branch": "default",
982 "date": [1000000, 0],
982 "date": [1000000, 0],
983 "desc": "second",
983 "desc": "second",
984 "extra": {"branch": "default"},
984 "extra": {"branch": "default"},
985 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
985 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
986 "modified": [],
986 "modified": [],
987 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
987 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
988 "parents": ["0000000000000000000000000000000000000000"],
988 "parents": ["0000000000000000000000000000000000000000"],
989 "phase": "draft",
989 "phase": "draft",
990 "removed": [],
990 "removed": [],
991 "rev": 7,
991 "rev": 7,
992 "tags": [],
992 "tags": [],
993 "user": "User Name <user@hostname>"
993 "user": "User Name <user@hostname>"
994 },
994 },
995 {
995 {
996 "added": [],
996 "added": [],
997 "bookmarks": [],
997 "bookmarks": [],
998 "branch": "default",
998 "branch": "default",
999 "date": [1500001, 0],
999 "date": [1500001, 0],
1000 "desc": "merge",
1000 "desc": "merge",
1001 "extra": {"branch": "default"},
1001 "extra": {"branch": "default"},
1002 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1002 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1003 "modified": [],
1003 "modified": [],
1004 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1004 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1005 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1005 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1006 "phase": "draft",
1006 "phase": "draft",
1007 "removed": [],
1007 "removed": [],
1008 "rev": 6,
1008 "rev": 6,
1009 "tags": [],
1009 "tags": [],
1010 "user": "person"
1010 "user": "person"
1011 },
1011 },
1012 {
1012 {
1013 "added": ["d"],
1013 "added": ["d"],
1014 "bookmarks": [],
1014 "bookmarks": [],
1015 "branch": "default",
1015 "branch": "default",
1016 "date": [1500000, 0],
1016 "date": [1500000, 0],
1017 "desc": "new head",
1017 "desc": "new head",
1018 "extra": {"branch": "default"},
1018 "extra": {"branch": "default"},
1019 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1019 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1020 "modified": [],
1020 "modified": [],
1021 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1021 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1022 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1022 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1023 "phase": "draft",
1023 "phase": "draft",
1024 "removed": [],
1024 "removed": [],
1025 "rev": 5,
1025 "rev": 5,
1026 "tags": [],
1026 "tags": [],
1027 "user": "person"
1027 "user": "person"
1028 },
1028 },
1029 {
1029 {
1030 "added": [],
1030 "added": [],
1031 "bookmarks": [],
1031 "bookmarks": [],
1032 "branch": "foo",
1032 "branch": "foo",
1033 "date": [1400000, 0],
1033 "date": [1400000, 0],
1034 "desc": "new branch",
1034 "desc": "new branch",
1035 "extra": {"branch": "foo"},
1035 "extra": {"branch": "foo"},
1036 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1036 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1037 "modified": [],
1037 "modified": [],
1038 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1038 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1039 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1039 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1040 "phase": "draft",
1040 "phase": "draft",
1041 "removed": [],
1041 "removed": [],
1042 "rev": 4,
1042 "rev": 4,
1043 "tags": [],
1043 "tags": [],
1044 "user": "person"
1044 "user": "person"
1045 },
1045 },
1046 {
1046 {
1047 "added": [],
1047 "added": [],
1048 "bookmarks": [],
1048 "bookmarks": [],
1049 "branch": "default",
1049 "branch": "default",
1050 "date": [1300000, 0],
1050 "date": [1300000, 0],
1051 "desc": "no user, no domain",
1051 "desc": "no user, no domain",
1052 "extra": {"branch": "default"},
1052 "extra": {"branch": "default"},
1053 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1053 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1054 "modified": ["c"],
1054 "modified": ["c"],
1055 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1055 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1056 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1056 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1057 "phase": "draft",
1057 "phase": "draft",
1058 "removed": [],
1058 "removed": [],
1059 "rev": 3,
1059 "rev": 3,
1060 "tags": [],
1060 "tags": [],
1061 "user": "person"
1061 "user": "person"
1062 },
1062 },
1063 {
1063 {
1064 "added": ["c"],
1064 "added": ["c"],
1065 "bookmarks": [],
1065 "bookmarks": [],
1066 "branch": "default",
1066 "branch": "default",
1067 "date": [1200000, 0],
1067 "date": [1200000, 0],
1068 "desc": "no person",
1068 "desc": "no person",
1069 "extra": {"branch": "default"},
1069 "extra": {"branch": "default"},
1070 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1070 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1071 "modified": [],
1071 "modified": [],
1072 "node": "97054abb4ab824450e9164180baf491ae0078465",
1072 "node": "97054abb4ab824450e9164180baf491ae0078465",
1073 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1073 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1074 "phase": "draft",
1074 "phase": "draft",
1075 "removed": [],
1075 "removed": [],
1076 "rev": 2,
1076 "rev": 2,
1077 "tags": [],
1077 "tags": [],
1078 "user": "other@place"
1078 "user": "other@place"
1079 },
1079 },
1080 {
1080 {
1081 "added": ["b"],
1081 "added": ["b"],
1082 "bookmarks": [],
1082 "bookmarks": [],
1083 "branch": "default",
1083 "branch": "default",
1084 "date": [1100000, 0],
1084 "date": [1100000, 0],
1085 "desc": "other 1\nother 2\n\nother 3",
1085 "desc": "other 1\nother 2\n\nother 3",
1086 "extra": {"branch": "default"},
1086 "extra": {"branch": "default"},
1087 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1087 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1088 "modified": [],
1088 "modified": [],
1089 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1089 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1090 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1090 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1091 "phase": "draft",
1091 "phase": "draft",
1092 "removed": [],
1092 "removed": [],
1093 "rev": 1,
1093 "rev": 1,
1094 "tags": [],
1094 "tags": [],
1095 "user": "A. N. Other <other@place>"
1095 "user": "A. N. Other <other@place>"
1096 },
1096 },
1097 {
1097 {
1098 "added": ["a"],
1098 "added": ["a"],
1099 "bookmarks": [],
1099 "bookmarks": [],
1100 "branch": "default",
1100 "branch": "default",
1101 "date": [1000000, 0],
1101 "date": [1000000, 0],
1102 "desc": "line 1\nline 2",
1102 "desc": "line 1\nline 2",
1103 "extra": {"branch": "default"},
1103 "extra": {"branch": "default"},
1104 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1104 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1105 "modified": [],
1105 "modified": [],
1106 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1106 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1107 "parents": ["0000000000000000000000000000000000000000"],
1107 "parents": ["0000000000000000000000000000000000000000"],
1108 "phase": "draft",
1108 "phase": "draft",
1109 "removed": [],
1109 "removed": [],
1110 "rev": 0,
1110 "rev": 0,
1111 "tags": [],
1111 "tags": [],
1112 "user": "User Name <user@hostname>"
1112 "user": "User Name <user@hostname>"
1113 }
1113 }
1114 ]
1114 ]
1115
1115
1116 $ hg log -l2 -T'json(rev, parents)'
1116 $ hg log -l2 -T'json(rev, parents)'
1117 [
1117 [
1118 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8},
1118 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8},
1119 {"parents": ["0000000000000000000000000000000000000000"], "rev": 7}
1119 {"parents": ["0000000000000000000000000000000000000000"], "rev": 7}
1120 ]
1120 ]
1121
1121
1122 $ hg log -qr. -T'json(rev, parents)'
1123 [
1124 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8}
1125 ]
1126
1127 $ hg log -r. -T'json(diff)'
1128 [
1129 {"diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"}
1130 ]
1131
1132 $ hg log -r. -T'json(diffstat)'
1133 [
1134 {"diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n"}
1135 ]
1136
1137 $ hg log -r. -T'json(manifest)'
1138 [
1139 {"manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64"}
1140 ]
1141
1142 $ hg log -r. -T'json(extra)'
1143 [
1144 {"extra": {"branch": "default"}}
1145 ]
1146
1147 $ hg log -r3 -T'json(modified)'
1148 [
1149 {"modified": ["c"]}
1150 ]
1151
1152 $ hg log -r. -T'json(added)'
1153 [
1154 {"added": ["fourth", "third"]}
1155 ]
1156
1157 $ hg log -r. -T'json(removed)'
1158 [
1159 {"removed": ["second"]}
1160 ]
1161
1162 $ hg log -r. -T'json(files)'
1163 [
1164 {"files": ["fourth", "second", "third"]}
1165 ]
1166
1167 --copies is the exception. copies dict is built only when --copies switch
1168 is on:
1169
1170 $ hg log -r'.^:' -T'json(copies)' --copies
1171 [
1172 {"copies": {}},
1173 {"copies": {"fourth": "second"}}
1174 ]
1175
1122 $ hg log -r. -T'json()'
1176 $ hg log -r. -T'json()'
1123 [
1177 [
1124 {}
1178 {}
1125 ]
1179 ]
1126
1180
1127 Other unsupported formatter styles:
1181 Other unsupported formatter styles:
1128
1182
1129 $ hg log -qr . -Tpickle
1183 $ hg log -qr . -Tpickle
1130 abort: "pickle" not in template map
1184 abort: "pickle" not in template map
1131 [255]
1185 [255]
1132 $ hg log -qr . -Tdebug
1186 $ hg log -qr . -Tdebug
1133 abort: "debug" not in template map
1187 abort: "debug" not in template map
1134 [255]
1188 [255]
1135
1189
1136 Unparsable function-style references:
1190 Unparsable function-style references:
1137
1191
1138 $ hg log -qr . -T'json(-)'
1192 $ hg log -qr . -T'json(-)'
1139 hg: parse error at 6: not a prefix: )
1193 hg: parse error at 6: not a prefix: )
1140 (json(-)
1194 (json(-)
1141 ^ here)
1195 ^ here)
1142 [255]
1196 [255]
1143
1197
1144 For backward compatibility, the following examples are not parsed as
1198 For backward compatibility, the following examples are not parsed as
1145 function-style references:
1199 function-style references:
1146
1200
1147 $ hg log -qr . -T'cbor(rev'
1201 $ hg log -qr . -T'cbor(rev'
1148 cbor(rev (no-eol)
1202 cbor(rev (no-eol)
1149 $ hg log -qr . -T'json (rev)'
1203 $ hg log -qr . -T'json (rev)'
1150 json (rev) (no-eol)
1204 json (rev) (no-eol)
1151 $ hg log -qr . -T'json(x="{rev}")'
1205 $ hg log -qr . -T'json(x="{rev}")'
1152 json(x="8") (no-eol)
1206 json(x="8") (no-eol)
1153
1207
1154 Error if style not readable:
1208 Error if style not readable:
1155
1209
1156 #if unix-permissions no-root
1210 #if unix-permissions no-root
1157 $ touch q
1211 $ touch q
1158 $ chmod 0 q
1212 $ chmod 0 q
1159 $ hg log --style ./q
1213 $ hg log --style ./q
1160 abort: Permission denied: './q'
1214 abort: Permission denied: './q'
1161 [255]
1215 [255]
1162 #endif
1216 #endif
1163
1217
1164 Error if no style:
1218 Error if no style:
1165
1219
1166 $ hg log --style notexist
1220 $ hg log --style notexist
1167 abort: style 'notexist' not found
1221 abort: style 'notexist' not found
1168 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1222 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1169 [255]
1223 [255]
1170
1224
1171 $ hg log -T list
1225 $ hg log -T list
1172 available styles: bisect, changelog, compact, default, phases, show, status, xml
1226 available styles: bisect, changelog, compact, default, phases, show, status, xml
1173 abort: specify a template
1227 abort: specify a template
1174 [255]
1228 [255]
1175
1229
1176 Error if style missing key:
1230 Error if style missing key:
1177
1231
1178 $ echo 'q = q' > t
1232 $ echo 'q = q' > t
1179 $ hg log --style ./t
1233 $ hg log --style ./t
1180 abort: "changeset" not in template map
1234 abort: "changeset" not in template map
1181 [255]
1235 [255]
1182
1236
1183 Error if style missing value:
1237 Error if style missing value:
1184
1238
1185 $ echo 'changeset =' > t
1239 $ echo 'changeset =' > t
1186 $ hg log --style t
1240 $ hg log --style t
1187 hg: parse error at t:1: missing value
1241 hg: parse error at t:1: missing value
1188 [255]
1242 [255]
1189
1243
1190 Error if include fails:
1244 Error if include fails:
1191
1245
1192 $ echo 'changeset = q' >> t
1246 $ echo 'changeset = q' >> t
1193 #if unix-permissions no-root
1247 #if unix-permissions no-root
1194 $ hg log --style ./t
1248 $ hg log --style ./t
1195 abort: template file ./q: Permission denied
1249 abort: template file ./q: Permission denied
1196 [255]
1250 [255]
1197 $ rm -f q
1251 $ rm -f q
1198 #endif
1252 #endif
1199
1253
1200 Include works:
1254 Include works:
1201
1255
1202 $ echo '{rev}' > q
1256 $ echo '{rev}' > q
1203 $ hg log --style ./t
1257 $ hg log --style ./t
1204 8
1258 8
1205 7
1259 7
1206 6
1260 6
1207 5
1261 5
1208 4
1262 4
1209 3
1263 3
1210 2
1264 2
1211 1
1265 1
1212 0
1266 0
1213
1267
1214 $ hg phase -r 5 --public
1268 $ hg phase -r 5 --public
1215 $ hg phase -r 7 --secret --force
1269 $ hg phase -r 7 --secret --force
1216
1270
1217 Missing non-standard names give no error (backward compatibility):
1271 Missing non-standard names give no error (backward compatibility):
1218
1272
1219 $ echo "changeset = '{c}'" > t
1273 $ echo "changeset = '{c}'" > t
1220 $ hg log --style ./t
1274 $ hg log --style ./t
1221
1275
1222 Defining non-standard name works:
1276 Defining non-standard name works:
1223
1277
1224 $ cat <<EOF > t
1278 $ cat <<EOF > t
1225 > changeset = '{c}'
1279 > changeset = '{c}'
1226 > c = q
1280 > c = q
1227 > EOF
1281 > EOF
1228 $ hg log --style ./t
1282 $ hg log --style ./t
1229 8
1283 8
1230 7
1284 7
1231 6
1285 6
1232 5
1286 5
1233 4
1287 4
1234 3
1288 3
1235 2
1289 2
1236 1
1290 1
1237 0
1291 0
1238
1292
1239 ui.style works:
1293 ui.style works:
1240
1294
1241 $ echo '[ui]' > .hg/hgrc
1295 $ echo '[ui]' > .hg/hgrc
1242 $ echo 'style = t' >> .hg/hgrc
1296 $ echo 'style = t' >> .hg/hgrc
1243 $ hg log
1297 $ hg log
1244 8
1298 8
1245 7
1299 7
1246 6
1300 6
1247 5
1301 5
1248 4
1302 4
1249 3
1303 3
1250 2
1304 2
1251 1
1305 1
1252 0
1306 0
1253
1307
1254 Issue338:
1308 Issue338:
1255
1309
1256 $ hg log --style=changelog > changelog
1310 $ hg log --style=changelog > changelog
1257
1311
1258 $ cat changelog
1312 $ cat changelog
1259 2020-01-01 test <test>
1313 2020-01-01 test <test>
1260
1314
1261 * fourth, second, third:
1315 * fourth, second, third:
1262 third
1316 third
1263 [95c24699272e] [tip]
1317 [95c24699272e] [tip]
1264
1318
1265 1970-01-12 User Name <user@hostname>
1319 1970-01-12 User Name <user@hostname>
1266
1320
1267 * second:
1321 * second:
1268 second
1322 second
1269 [29114dbae42b]
1323 [29114dbae42b]
1270
1324
1271 1970-01-18 person <person>
1325 1970-01-18 person <person>
1272
1326
1273 * merge
1327 * merge
1274 [d41e714fe50d]
1328 [d41e714fe50d]
1275
1329
1276 * d:
1330 * d:
1277 new head
1331 new head
1278 [13207e5a10d9]
1332 [13207e5a10d9]
1279
1333
1280 1970-01-17 person <person>
1334 1970-01-17 person <person>
1281
1335
1282 * new branch
1336 * new branch
1283 [bbe44766e73d] <foo>
1337 [bbe44766e73d] <foo>
1284
1338
1285 1970-01-16 person <person>
1339 1970-01-16 person <person>
1286
1340
1287 * c:
1341 * c:
1288 no user, no domain
1342 no user, no domain
1289 [10e46f2dcbf4]
1343 [10e46f2dcbf4]
1290
1344
1291 1970-01-14 other <other@place>
1345 1970-01-14 other <other@place>
1292
1346
1293 * c:
1347 * c:
1294 no person
1348 no person
1295 [97054abb4ab8]
1349 [97054abb4ab8]
1296
1350
1297 1970-01-13 A. N. Other <other@place>
1351 1970-01-13 A. N. Other <other@place>
1298
1352
1299 * b:
1353 * b:
1300 other 1 other 2
1354 other 1 other 2
1301
1355
1302 other 3
1356 other 3
1303 [b608e9d1a3f0]
1357 [b608e9d1a3f0]
1304
1358
1305 1970-01-12 User Name <user@hostname>
1359 1970-01-12 User Name <user@hostname>
1306
1360
1307 * a:
1361 * a:
1308 line 1 line 2
1362 line 1 line 2
1309 [1e4e1b8f71e0]
1363 [1e4e1b8f71e0]
1310
1364
1311
1365
1312 Issue2130: xml output for 'hg heads' is malformed
1366 Issue2130: xml output for 'hg heads' is malformed
1313
1367
1314 $ hg heads --style changelog
1368 $ hg heads --style changelog
1315 2020-01-01 test <test>
1369 2020-01-01 test <test>
1316
1370
1317 * fourth, second, third:
1371 * fourth, second, third:
1318 third
1372 third
1319 [95c24699272e] [tip]
1373 [95c24699272e] [tip]
1320
1374
1321 1970-01-18 person <person>
1375 1970-01-18 person <person>
1322
1376
1323 * merge
1377 * merge
1324 [d41e714fe50d]
1378 [d41e714fe50d]
1325
1379
1326 1970-01-17 person <person>
1380 1970-01-17 person <person>
1327
1381
1328 * new branch
1382 * new branch
1329 [bbe44766e73d] <foo>
1383 [bbe44766e73d] <foo>
1330
1384
1331
1385
1332 Add a dummy commit to make up for the instability of the above:
1386 Add a dummy commit to make up for the instability of the above:
1333
1387
1334 $ echo a > a
1388 $ echo a > a
1335 $ hg add a
1389 $ hg add a
1336 $ hg ci -m future
1390 $ hg ci -m future
1337
1391
1338 Add a commit that does all possible modifications at once
1392 Add a commit that does all possible modifications at once
1339
1393
1340 $ echo modify >> third
1394 $ echo modify >> third
1341 $ touch b
1395 $ touch b
1342 $ hg add b
1396 $ hg add b
1343 $ hg mv fourth fifth
1397 $ hg mv fourth fifth
1344 $ hg rm a
1398 $ hg rm a
1345 $ hg ci -m "Modify, add, remove, rename"
1399 $ hg ci -m "Modify, add, remove, rename"
1346
1400
1347 Check the status template
1401 Check the status template
1348
1402
1349 $ cat <<EOF >> $HGRCPATH
1403 $ cat <<EOF >> $HGRCPATH
1350 > [extensions]
1404 > [extensions]
1351 > color=
1405 > color=
1352 > EOF
1406 > EOF
1353
1407
1354 $ hg log -T status -r 10
1408 $ hg log -T status -r 10
1355 changeset: 10:0f9759ec227a
1409 changeset: 10:0f9759ec227a
1356 tag: tip
1410 tag: tip
1357 user: test
1411 user: test
1358 date: Thu Jan 01 00:00:00 1970 +0000
1412 date: Thu Jan 01 00:00:00 1970 +0000
1359 summary: Modify, add, remove, rename
1413 summary: Modify, add, remove, rename
1360 files:
1414 files:
1361 M third
1415 M third
1362 A b
1416 A b
1363 A fifth
1417 A fifth
1364 R a
1418 R a
1365 R fourth
1419 R fourth
1366
1420
1367 $ hg log -T status -C -r 10
1421 $ hg log -T status -C -r 10
1368 changeset: 10:0f9759ec227a
1422 changeset: 10:0f9759ec227a
1369 tag: tip
1423 tag: tip
1370 user: test
1424 user: test
1371 date: Thu Jan 01 00:00:00 1970 +0000
1425 date: Thu Jan 01 00:00:00 1970 +0000
1372 summary: Modify, add, remove, rename
1426 summary: Modify, add, remove, rename
1373 files:
1427 files:
1374 M third
1428 M third
1375 A b
1429 A b
1376 A fifth
1430 A fifth
1377 fourth
1431 fourth
1378 R a
1432 R a
1379 R fourth
1433 R fourth
1380
1434
1381 $ hg log -T status -C -r 10 -v
1435 $ hg log -T status -C -r 10 -v
1382 changeset: 10:0f9759ec227a
1436 changeset: 10:0f9759ec227a
1383 tag: tip
1437 tag: tip
1384 user: test
1438 user: test
1385 date: Thu Jan 01 00:00:00 1970 +0000
1439 date: Thu Jan 01 00:00:00 1970 +0000
1386 description:
1440 description:
1387 Modify, add, remove, rename
1441 Modify, add, remove, rename
1388
1442
1389 files:
1443 files:
1390 M third
1444 M third
1391 A b
1445 A b
1392 A fifth
1446 A fifth
1393 fourth
1447 fourth
1394 R a
1448 R a
1395 R fourth
1449 R fourth
1396
1450
1397 $ hg log -T status -C -r 10 --debug
1451 $ hg log -T status -C -r 10 --debug
1398 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
1452 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
1399 tag: tip
1453 tag: tip
1400 phase: secret
1454 phase: secret
1401 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
1455 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
1402 parent: -1:0000000000000000000000000000000000000000
1456 parent: -1:0000000000000000000000000000000000000000
1403 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
1457 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
1404 user: test
1458 user: test
1405 date: Thu Jan 01 00:00:00 1970 +0000
1459 date: Thu Jan 01 00:00:00 1970 +0000
1406 extra: branch=default
1460 extra: branch=default
1407 description:
1461 description:
1408 Modify, add, remove, rename
1462 Modify, add, remove, rename
1409
1463
1410 files:
1464 files:
1411 M third
1465 M third
1412 A b
1466 A b
1413 A fifth
1467 A fifth
1414 fourth
1468 fourth
1415 R a
1469 R a
1416 R fourth
1470 R fourth
1417
1471
1418 $ hg log -T status -C -r 10 --quiet
1472 $ hg log -T status -C -r 10 --quiet
1419 10:0f9759ec227a
1473 10:0f9759ec227a
1420 $ hg --color=debug log -T status -r 10
1474 $ hg --color=debug log -T status -r 10
1421 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1475 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1422 [log.tag|tag: tip]
1476 [log.tag|tag: tip]
1423 [log.user|user: test]
1477 [log.user|user: test]
1424 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1478 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1425 [log.summary|summary: Modify, add, remove, rename]
1479 [log.summary|summary: Modify, add, remove, rename]
1426 [ui.note log.files|files:]
1480 [ui.note log.files|files:]
1427 [status.modified|M third]
1481 [status.modified|M third]
1428 [status.added|A b]
1482 [status.added|A b]
1429 [status.added|A fifth]
1483 [status.added|A fifth]
1430 [status.removed|R a]
1484 [status.removed|R a]
1431 [status.removed|R fourth]
1485 [status.removed|R fourth]
1432
1486
1433 $ hg --color=debug log -T status -C -r 10
1487 $ hg --color=debug log -T status -C -r 10
1434 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1488 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1435 [log.tag|tag: tip]
1489 [log.tag|tag: tip]
1436 [log.user|user: test]
1490 [log.user|user: test]
1437 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1491 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1438 [log.summary|summary: Modify, add, remove, rename]
1492 [log.summary|summary: Modify, add, remove, rename]
1439 [ui.note log.files|files:]
1493 [ui.note log.files|files:]
1440 [status.modified|M third]
1494 [status.modified|M third]
1441 [status.added|A b]
1495 [status.added|A b]
1442 [status.added|A fifth]
1496 [status.added|A fifth]
1443 [status.copied| fourth]
1497 [status.copied| fourth]
1444 [status.removed|R a]
1498 [status.removed|R a]
1445 [status.removed|R fourth]
1499 [status.removed|R fourth]
1446
1500
1447 $ hg --color=debug log -T status -C -r 10 -v
1501 $ hg --color=debug log -T status -C -r 10 -v
1448 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1502 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1449 [log.tag|tag: tip]
1503 [log.tag|tag: tip]
1450 [log.user|user: test]
1504 [log.user|user: test]
1451 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1505 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1452 [ui.note log.description|description:]
1506 [ui.note log.description|description:]
1453 [ui.note log.description|Modify, add, remove, rename]
1507 [ui.note log.description|Modify, add, remove, rename]
1454
1508
1455 [ui.note log.files|files:]
1509 [ui.note log.files|files:]
1456 [status.modified|M third]
1510 [status.modified|M third]
1457 [status.added|A b]
1511 [status.added|A b]
1458 [status.added|A fifth]
1512 [status.added|A fifth]
1459 [status.copied| fourth]
1513 [status.copied| fourth]
1460 [status.removed|R a]
1514 [status.removed|R a]
1461 [status.removed|R fourth]
1515 [status.removed|R fourth]
1462
1516
1463 $ hg --color=debug log -T status -C -r 10 --debug
1517 $ hg --color=debug log -T status -C -r 10 --debug
1464 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
1518 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
1465 [log.tag|tag: tip]
1519 [log.tag|tag: tip]
1466 [log.phase|phase: secret]
1520 [log.phase|phase: secret]
1467 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
1521 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
1468 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1522 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1469 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
1523 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
1470 [log.user|user: test]
1524 [log.user|user: test]
1471 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1525 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1472 [ui.debug log.extra|extra: branch=default]
1526 [ui.debug log.extra|extra: branch=default]
1473 [ui.note log.description|description:]
1527 [ui.note log.description|description:]
1474 [ui.note log.description|Modify, add, remove, rename]
1528 [ui.note log.description|Modify, add, remove, rename]
1475
1529
1476 [ui.note log.files|files:]
1530 [ui.note log.files|files:]
1477 [status.modified|M third]
1531 [status.modified|M third]
1478 [status.added|A b]
1532 [status.added|A b]
1479 [status.added|A fifth]
1533 [status.added|A fifth]
1480 [status.copied| fourth]
1534 [status.copied| fourth]
1481 [status.removed|R a]
1535 [status.removed|R a]
1482 [status.removed|R fourth]
1536 [status.removed|R fourth]
1483
1537
1484 $ hg --color=debug log -T status -C -r 10 --quiet
1538 $ hg --color=debug log -T status -C -r 10 --quiet
1485 [log.node|10:0f9759ec227a]
1539 [log.node|10:0f9759ec227a]
1486
1540
1487 Check the bisect template
1541 Check the bisect template
1488
1542
1489 $ hg bisect -g 1
1543 $ hg bisect -g 1
1490 $ hg bisect -b 3 --noupdate
1544 $ hg bisect -b 3 --noupdate
1491 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
1545 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
1492 $ hg log -T bisect -r 0:4
1546 $ hg log -T bisect -r 0:4
1493 changeset: 0:1e4e1b8f71e0
1547 changeset: 0:1e4e1b8f71e0
1494 bisect: good (implicit)
1548 bisect: good (implicit)
1495 user: User Name <user@hostname>
1549 user: User Name <user@hostname>
1496 date: Mon Jan 12 13:46:40 1970 +0000
1550 date: Mon Jan 12 13:46:40 1970 +0000
1497 summary: line 1
1551 summary: line 1
1498
1552
1499 changeset: 1:b608e9d1a3f0
1553 changeset: 1:b608e9d1a3f0
1500 bisect: good
1554 bisect: good
1501 user: A. N. Other <other@place>
1555 user: A. N. Other <other@place>
1502 date: Tue Jan 13 17:33:20 1970 +0000
1556 date: Tue Jan 13 17:33:20 1970 +0000
1503 summary: other 1
1557 summary: other 1
1504
1558
1505 changeset: 2:97054abb4ab8
1559 changeset: 2:97054abb4ab8
1506 bisect: untested
1560 bisect: untested
1507 user: other@place
1561 user: other@place
1508 date: Wed Jan 14 21:20:00 1970 +0000
1562 date: Wed Jan 14 21:20:00 1970 +0000
1509 summary: no person
1563 summary: no person
1510
1564
1511 changeset: 3:10e46f2dcbf4
1565 changeset: 3:10e46f2dcbf4
1512 bisect: bad
1566 bisect: bad
1513 user: person
1567 user: person
1514 date: Fri Jan 16 01:06:40 1970 +0000
1568 date: Fri Jan 16 01:06:40 1970 +0000
1515 summary: no user, no domain
1569 summary: no user, no domain
1516
1570
1517 changeset: 4:bbe44766e73d
1571 changeset: 4:bbe44766e73d
1518 bisect: bad (implicit)
1572 bisect: bad (implicit)
1519 branch: foo
1573 branch: foo
1520 user: person
1574 user: person
1521 date: Sat Jan 17 04:53:20 1970 +0000
1575 date: Sat Jan 17 04:53:20 1970 +0000
1522 summary: new branch
1576 summary: new branch
1523
1577
1524 $ hg log --debug -T bisect -r 0:4
1578 $ hg log --debug -T bisect -r 0:4
1525 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1579 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1526 bisect: good (implicit)
1580 bisect: good (implicit)
1527 phase: public
1581 phase: public
1528 parent: -1:0000000000000000000000000000000000000000
1582 parent: -1:0000000000000000000000000000000000000000
1529 parent: -1:0000000000000000000000000000000000000000
1583 parent: -1:0000000000000000000000000000000000000000
1530 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1584 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1531 user: User Name <user@hostname>
1585 user: User Name <user@hostname>
1532 date: Mon Jan 12 13:46:40 1970 +0000
1586 date: Mon Jan 12 13:46:40 1970 +0000
1533 files+: a
1587 files+: a
1534 extra: branch=default
1588 extra: branch=default
1535 description:
1589 description:
1536 line 1
1590 line 1
1537 line 2
1591 line 2
1538
1592
1539
1593
1540 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1594 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1541 bisect: good
1595 bisect: good
1542 phase: public
1596 phase: public
1543 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1597 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1544 parent: -1:0000000000000000000000000000000000000000
1598 parent: -1:0000000000000000000000000000000000000000
1545 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1599 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1546 user: A. N. Other <other@place>
1600 user: A. N. Other <other@place>
1547 date: Tue Jan 13 17:33:20 1970 +0000
1601 date: Tue Jan 13 17:33:20 1970 +0000
1548 files+: b
1602 files+: b
1549 extra: branch=default
1603 extra: branch=default
1550 description:
1604 description:
1551 other 1
1605 other 1
1552 other 2
1606 other 2
1553
1607
1554 other 3
1608 other 3
1555
1609
1556
1610
1557 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
1611 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
1558 bisect: untested
1612 bisect: untested
1559 phase: public
1613 phase: public
1560 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1614 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1561 parent: -1:0000000000000000000000000000000000000000
1615 parent: -1:0000000000000000000000000000000000000000
1562 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1616 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1563 user: other@place
1617 user: other@place
1564 date: Wed Jan 14 21:20:00 1970 +0000
1618 date: Wed Jan 14 21:20:00 1970 +0000
1565 files+: c
1619 files+: c
1566 extra: branch=default
1620 extra: branch=default
1567 description:
1621 description:
1568 no person
1622 no person
1569
1623
1570
1624
1571 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1625 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1572 bisect: bad
1626 bisect: bad
1573 phase: public
1627 phase: public
1574 parent: 2:97054abb4ab824450e9164180baf491ae0078465
1628 parent: 2:97054abb4ab824450e9164180baf491ae0078465
1575 parent: -1:0000000000000000000000000000000000000000
1629 parent: -1:0000000000000000000000000000000000000000
1576 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1630 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1577 user: person
1631 user: person
1578 date: Fri Jan 16 01:06:40 1970 +0000
1632 date: Fri Jan 16 01:06:40 1970 +0000
1579 files: c
1633 files: c
1580 extra: branch=default
1634 extra: branch=default
1581 description:
1635 description:
1582 no user, no domain
1636 no user, no domain
1583
1637
1584
1638
1585 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1639 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1586 bisect: bad (implicit)
1640 bisect: bad (implicit)
1587 branch: foo
1641 branch: foo
1588 phase: draft
1642 phase: draft
1589 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1643 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1590 parent: -1:0000000000000000000000000000000000000000
1644 parent: -1:0000000000000000000000000000000000000000
1591 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1645 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1592 user: person
1646 user: person
1593 date: Sat Jan 17 04:53:20 1970 +0000
1647 date: Sat Jan 17 04:53:20 1970 +0000
1594 extra: branch=foo
1648 extra: branch=foo
1595 description:
1649 description:
1596 new branch
1650 new branch
1597
1651
1598
1652
1599 $ hg log -v -T bisect -r 0:4
1653 $ hg log -v -T bisect -r 0:4
1600 changeset: 0:1e4e1b8f71e0
1654 changeset: 0:1e4e1b8f71e0
1601 bisect: good (implicit)
1655 bisect: good (implicit)
1602 user: User Name <user@hostname>
1656 user: User Name <user@hostname>
1603 date: Mon Jan 12 13:46:40 1970 +0000
1657 date: Mon Jan 12 13:46:40 1970 +0000
1604 files: a
1658 files: a
1605 description:
1659 description:
1606 line 1
1660 line 1
1607 line 2
1661 line 2
1608
1662
1609
1663
1610 changeset: 1:b608e9d1a3f0
1664 changeset: 1:b608e9d1a3f0
1611 bisect: good
1665 bisect: good
1612 user: A. N. Other <other@place>
1666 user: A. N. Other <other@place>
1613 date: Tue Jan 13 17:33:20 1970 +0000
1667 date: Tue Jan 13 17:33:20 1970 +0000
1614 files: b
1668 files: b
1615 description:
1669 description:
1616 other 1
1670 other 1
1617 other 2
1671 other 2
1618
1672
1619 other 3
1673 other 3
1620
1674
1621
1675
1622 changeset: 2:97054abb4ab8
1676 changeset: 2:97054abb4ab8
1623 bisect: untested
1677 bisect: untested
1624 user: other@place
1678 user: other@place
1625 date: Wed Jan 14 21:20:00 1970 +0000
1679 date: Wed Jan 14 21:20:00 1970 +0000
1626 files: c
1680 files: c
1627 description:
1681 description:
1628 no person
1682 no person
1629
1683
1630
1684
1631 changeset: 3:10e46f2dcbf4
1685 changeset: 3:10e46f2dcbf4
1632 bisect: bad
1686 bisect: bad
1633 user: person
1687 user: person
1634 date: Fri Jan 16 01:06:40 1970 +0000
1688 date: Fri Jan 16 01:06:40 1970 +0000
1635 files: c
1689 files: c
1636 description:
1690 description:
1637 no user, no domain
1691 no user, no domain
1638
1692
1639
1693
1640 changeset: 4:bbe44766e73d
1694 changeset: 4:bbe44766e73d
1641 bisect: bad (implicit)
1695 bisect: bad (implicit)
1642 branch: foo
1696 branch: foo
1643 user: person
1697 user: person
1644 date: Sat Jan 17 04:53:20 1970 +0000
1698 date: Sat Jan 17 04:53:20 1970 +0000
1645 description:
1699 description:
1646 new branch
1700 new branch
1647
1701
1648
1702
1649 $ hg --color=debug log -T bisect -r 0:4
1703 $ hg --color=debug log -T bisect -r 0:4
1650 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1704 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1651 [log.bisect bisect.good|bisect: good (implicit)]
1705 [log.bisect bisect.good|bisect: good (implicit)]
1652 [log.user|user: User Name <user@hostname>]
1706 [log.user|user: User Name <user@hostname>]
1653 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1707 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1654 [log.summary|summary: line 1]
1708 [log.summary|summary: line 1]
1655
1709
1656 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1710 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1657 [log.bisect bisect.good|bisect: good]
1711 [log.bisect bisect.good|bisect: good]
1658 [log.user|user: A. N. Other <other@place>]
1712 [log.user|user: A. N. Other <other@place>]
1659 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1713 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1660 [log.summary|summary: other 1]
1714 [log.summary|summary: other 1]
1661
1715
1662 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1716 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1663 [log.bisect bisect.untested|bisect: untested]
1717 [log.bisect bisect.untested|bisect: untested]
1664 [log.user|user: other@place]
1718 [log.user|user: other@place]
1665 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1719 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1666 [log.summary|summary: no person]
1720 [log.summary|summary: no person]
1667
1721
1668 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1722 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1669 [log.bisect bisect.bad|bisect: bad]
1723 [log.bisect bisect.bad|bisect: bad]
1670 [log.user|user: person]
1724 [log.user|user: person]
1671 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1725 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1672 [log.summary|summary: no user, no domain]
1726 [log.summary|summary: no user, no domain]
1673
1727
1674 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1728 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1675 [log.bisect bisect.bad|bisect: bad (implicit)]
1729 [log.bisect bisect.bad|bisect: bad (implicit)]
1676 [log.branch|branch: foo]
1730 [log.branch|branch: foo]
1677 [log.user|user: person]
1731 [log.user|user: person]
1678 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1732 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1679 [log.summary|summary: new branch]
1733 [log.summary|summary: new branch]
1680
1734
1681 $ hg --color=debug log --debug -T bisect -r 0:4
1735 $ hg --color=debug log --debug -T bisect -r 0:4
1682 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1736 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1683 [log.bisect bisect.good|bisect: good (implicit)]
1737 [log.bisect bisect.good|bisect: good (implicit)]
1684 [log.phase|phase: public]
1738 [log.phase|phase: public]
1685 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1739 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1686 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1740 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1687 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
1741 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
1688 [log.user|user: User Name <user@hostname>]
1742 [log.user|user: User Name <user@hostname>]
1689 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1743 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1690 [ui.debug log.files|files+: a]
1744 [ui.debug log.files|files+: a]
1691 [ui.debug log.extra|extra: branch=default]
1745 [ui.debug log.extra|extra: branch=default]
1692 [ui.note log.description|description:]
1746 [ui.note log.description|description:]
1693 [ui.note log.description|line 1
1747 [ui.note log.description|line 1
1694 line 2]
1748 line 2]
1695
1749
1696
1750
1697 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1751 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1698 [log.bisect bisect.good|bisect: good]
1752 [log.bisect bisect.good|bisect: good]
1699 [log.phase|phase: public]
1753 [log.phase|phase: public]
1700 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1754 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1701 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1755 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1702 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
1756 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
1703 [log.user|user: A. N. Other <other@place>]
1757 [log.user|user: A. N. Other <other@place>]
1704 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1758 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1705 [ui.debug log.files|files+: b]
1759 [ui.debug log.files|files+: b]
1706 [ui.debug log.extra|extra: branch=default]
1760 [ui.debug log.extra|extra: branch=default]
1707 [ui.note log.description|description:]
1761 [ui.note log.description|description:]
1708 [ui.note log.description|other 1
1762 [ui.note log.description|other 1
1709 other 2
1763 other 2
1710
1764
1711 other 3]
1765 other 3]
1712
1766
1713
1767
1714 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
1768 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
1715 [log.bisect bisect.untested|bisect: untested]
1769 [log.bisect bisect.untested|bisect: untested]
1716 [log.phase|phase: public]
1770 [log.phase|phase: public]
1717 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1771 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1718 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1772 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1719 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
1773 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
1720 [log.user|user: other@place]
1774 [log.user|user: other@place]
1721 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1775 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1722 [ui.debug log.files|files+: c]
1776 [ui.debug log.files|files+: c]
1723 [ui.debug log.extra|extra: branch=default]
1777 [ui.debug log.extra|extra: branch=default]
1724 [ui.note log.description|description:]
1778 [ui.note log.description|description:]
1725 [ui.note log.description|no person]
1779 [ui.note log.description|no person]
1726
1780
1727
1781
1728 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1782 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1729 [log.bisect bisect.bad|bisect: bad]
1783 [log.bisect bisect.bad|bisect: bad]
1730 [log.phase|phase: public]
1784 [log.phase|phase: public]
1731 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
1785 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
1732 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1786 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1733 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1787 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1734 [log.user|user: person]
1788 [log.user|user: person]
1735 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1789 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1736 [ui.debug log.files|files: c]
1790 [ui.debug log.files|files: c]
1737 [ui.debug log.extra|extra: branch=default]
1791 [ui.debug log.extra|extra: branch=default]
1738 [ui.note log.description|description:]
1792 [ui.note log.description|description:]
1739 [ui.note log.description|no user, no domain]
1793 [ui.note log.description|no user, no domain]
1740
1794
1741
1795
1742 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
1796 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
1743 [log.bisect bisect.bad|bisect: bad (implicit)]
1797 [log.bisect bisect.bad|bisect: bad (implicit)]
1744 [log.branch|branch: foo]
1798 [log.branch|branch: foo]
1745 [log.phase|phase: draft]
1799 [log.phase|phase: draft]
1746 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1800 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1747 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1801 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1748 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1802 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1749 [log.user|user: person]
1803 [log.user|user: person]
1750 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1804 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1751 [ui.debug log.extra|extra: branch=foo]
1805 [ui.debug log.extra|extra: branch=foo]
1752 [ui.note log.description|description:]
1806 [ui.note log.description|description:]
1753 [ui.note log.description|new branch]
1807 [ui.note log.description|new branch]
1754
1808
1755
1809
1756 $ hg --color=debug log -v -T bisect -r 0:4
1810 $ hg --color=debug log -v -T bisect -r 0:4
1757 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1811 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1758 [log.bisect bisect.good|bisect: good (implicit)]
1812 [log.bisect bisect.good|bisect: good (implicit)]
1759 [log.user|user: User Name <user@hostname>]
1813 [log.user|user: User Name <user@hostname>]
1760 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1814 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1761 [ui.note log.files|files: a]
1815 [ui.note log.files|files: a]
1762 [ui.note log.description|description:]
1816 [ui.note log.description|description:]
1763 [ui.note log.description|line 1
1817 [ui.note log.description|line 1
1764 line 2]
1818 line 2]
1765
1819
1766
1820
1767 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1821 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1768 [log.bisect bisect.good|bisect: good]
1822 [log.bisect bisect.good|bisect: good]
1769 [log.user|user: A. N. Other <other@place>]
1823 [log.user|user: A. N. Other <other@place>]
1770 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1824 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1771 [ui.note log.files|files: b]
1825 [ui.note log.files|files: b]
1772 [ui.note log.description|description:]
1826 [ui.note log.description|description:]
1773 [ui.note log.description|other 1
1827 [ui.note log.description|other 1
1774 other 2
1828 other 2
1775
1829
1776 other 3]
1830 other 3]
1777
1831
1778
1832
1779 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1833 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1780 [log.bisect bisect.untested|bisect: untested]
1834 [log.bisect bisect.untested|bisect: untested]
1781 [log.user|user: other@place]
1835 [log.user|user: other@place]
1782 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1836 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1783 [ui.note log.files|files: c]
1837 [ui.note log.files|files: c]
1784 [ui.note log.description|description:]
1838 [ui.note log.description|description:]
1785 [ui.note log.description|no person]
1839 [ui.note log.description|no person]
1786
1840
1787
1841
1788 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1842 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1789 [log.bisect bisect.bad|bisect: bad]
1843 [log.bisect bisect.bad|bisect: bad]
1790 [log.user|user: person]
1844 [log.user|user: person]
1791 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1845 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1792 [ui.note log.files|files: c]
1846 [ui.note log.files|files: c]
1793 [ui.note log.description|description:]
1847 [ui.note log.description|description:]
1794 [ui.note log.description|no user, no domain]
1848 [ui.note log.description|no user, no domain]
1795
1849
1796
1850
1797 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1851 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1798 [log.bisect bisect.bad|bisect: bad (implicit)]
1852 [log.bisect bisect.bad|bisect: bad (implicit)]
1799 [log.branch|branch: foo]
1853 [log.branch|branch: foo]
1800 [log.user|user: person]
1854 [log.user|user: person]
1801 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1855 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1802 [ui.note log.description|description:]
1856 [ui.note log.description|description:]
1803 [ui.note log.description|new branch]
1857 [ui.note log.description|new branch]
1804
1858
1805
1859
1806 $ hg bisect --reset
1860 $ hg bisect --reset
1807
1861
1808 $ cd ..
1862 $ cd ..
1809
1863
1810 Set up latesttag repository:
1864 Set up latesttag repository:
1811
1865
1812 $ hg init latesttag
1866 $ hg init latesttag
1813 $ cd latesttag
1867 $ cd latesttag
1814
1868
1815 $ echo a > file
1869 $ echo a > file
1816 $ hg ci -Am a -d '0 0'
1870 $ hg ci -Am a -d '0 0'
1817 adding file
1871 adding file
1818
1872
1819 $ echo b >> file
1873 $ echo b >> file
1820 $ hg ci -m b -d '1 0'
1874 $ hg ci -m b -d '1 0'
1821
1875
1822 $ echo c >> head1
1876 $ echo c >> head1
1823 $ hg ci -Am h1c -d '2 0'
1877 $ hg ci -Am h1c -d '2 0'
1824 adding head1
1878 adding head1
1825
1879
1826 $ hg update -q 1
1880 $ hg update -q 1
1827 $ echo d >> head2
1881 $ echo d >> head2
1828 $ hg ci -Am h2d -d '3 0'
1882 $ hg ci -Am h2d -d '3 0'
1829 adding head2
1883 adding head2
1830 created new head
1884 created new head
1831
1885
1832 $ echo e >> head2
1886 $ echo e >> head2
1833 $ hg ci -m h2e -d '4 0'
1887 $ hg ci -m h2e -d '4 0'
1834
1888
1835 $ hg merge -q
1889 $ hg merge -q
1836 $ hg ci -m merge -d '5 -3600'
1890 $ hg ci -m merge -d '5 -3600'
1837
1891
1838 $ hg tag -r 1 -m t1 -d '6 0' t1
1892 $ hg tag -r 1 -m t1 -d '6 0' t1
1839 $ hg tag -r 2 -m t2 -d '7 0' t2
1893 $ hg tag -r 2 -m t2 -d '7 0' t2
1840 $ hg tag -r 3 -m t3 -d '8 0' t3
1894 $ hg tag -r 3 -m t3 -d '8 0' t3
1841 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
1895 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
1842 $ hg tag -r 5 -m t5 -d '9 0' t5
1896 $ hg tag -r 5 -m t5 -d '9 0' t5
1843 $ hg tag -r 3 -m at3 -d '10 0' at3
1897 $ hg tag -r 3 -m at3 -d '10 0' at3
1844
1898
1845 $ cd ..
1899 $ cd ..
1846
1900
1847 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1901 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1848 if it is a relative path
1902 if it is a relative path
1849
1903
1850 $ mkdir -p home/styles
1904 $ mkdir -p home/styles
1851
1905
1852 $ cat > home/styles/teststyle <<EOF
1906 $ cat > home/styles/teststyle <<EOF
1853 > changeset = 'test {rev}:{node|short}\n'
1907 > changeset = 'test {rev}:{node|short}\n'
1854 > EOF
1908 > EOF
1855
1909
1856 $ HOME=`pwd`/home; export HOME
1910 $ HOME=`pwd`/home; export HOME
1857
1911
1858 $ cat > latesttag/.hg/hgrc <<EOF
1912 $ cat > latesttag/.hg/hgrc <<EOF
1859 > [ui]
1913 > [ui]
1860 > style = ~/styles/teststyle
1914 > style = ~/styles/teststyle
1861 > EOF
1915 > EOF
1862
1916
1863 $ hg -R latesttag tip
1917 $ hg -R latesttag tip
1864 test 11:97e5943b523a
1918 test 11:97e5943b523a
1865
1919
1866 Test recursive showlist template (issue1989):
1920 Test recursive showlist template (issue1989):
1867
1921
1868 $ cat > style1989 <<EOF
1922 $ cat > style1989 <<EOF
1869 > changeset = '{file_mods}{manifest}{extras}'
1923 > changeset = '{file_mods}{manifest}{extras}'
1870 > file_mod = 'M|{author|person}\n'
1924 > file_mod = 'M|{author|person}\n'
1871 > manifest = '{rev},{author}\n'
1925 > manifest = '{rev},{author}\n'
1872 > extra = '{key}: {author}\n'
1926 > extra = '{key}: {author}\n'
1873 > EOF
1927 > EOF
1874
1928
1875 $ hg -R latesttag log -r tip --style=style1989
1929 $ hg -R latesttag log -r tip --style=style1989
1876 M|test
1930 M|test
1877 11,
1931 11,
1878 branch: test
1932 branch: test
General Comments 0
You need to be logged in to leave comments. Login now