##// END OF EJS Templates
command line templates: add formatnode filter...
Alexis S. L. Carvalho -
r4352:051fb8c2 default
parent child Browse files
Show More
@@ -1,776 +1,780 b''
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from demandload import demandload
8 from demandload import demandload
9 from node import *
9 from node import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 demandload(globals(), 'os sys')
11 demandload(globals(), 'os sys')
12 demandload(globals(), 'mdiff util templater patch')
12 demandload(globals(), 'mdiff util templater patch')
13
13
14 revrangesep = ':'
14 revrangesep = ':'
15
15
16 def revpair(repo, revs):
16 def revpair(repo, revs):
17 '''return pair of nodes, given list of revisions. second item can
17 '''return pair of nodes, given list of revisions. second item can
18 be None, meaning use working dir.'''
18 be None, meaning use working dir.'''
19
19
20 def revfix(repo, val, defval):
20 def revfix(repo, val, defval):
21 if not val and val != 0 and defval is not None:
21 if not val and val != 0 and defval is not None:
22 val = defval
22 val = defval
23 return repo.lookup(val)
23 return repo.lookup(val)
24
24
25 if not revs:
25 if not revs:
26 return repo.dirstate.parents()[0], None
26 return repo.dirstate.parents()[0], None
27 end = None
27 end = None
28 if len(revs) == 1:
28 if len(revs) == 1:
29 if revrangesep in revs[0]:
29 if revrangesep in revs[0]:
30 start, end = revs[0].split(revrangesep, 1)
30 start, end = revs[0].split(revrangesep, 1)
31 start = revfix(repo, start, 0)
31 start = revfix(repo, start, 0)
32 end = revfix(repo, end, repo.changelog.count() - 1)
32 end = revfix(repo, end, repo.changelog.count() - 1)
33 else:
33 else:
34 start = revfix(repo, revs[0], None)
34 start = revfix(repo, revs[0], None)
35 elif len(revs) == 2:
35 elif len(revs) == 2:
36 if revrangesep in revs[0] or revrangesep in revs[1]:
36 if revrangesep in revs[0] or revrangesep in revs[1]:
37 raise util.Abort(_('too many revisions specified'))
37 raise util.Abort(_('too many revisions specified'))
38 start = revfix(repo, revs[0], None)
38 start = revfix(repo, revs[0], None)
39 end = revfix(repo, revs[1], None)
39 end = revfix(repo, revs[1], None)
40 else:
40 else:
41 raise util.Abort(_('too many revisions specified'))
41 raise util.Abort(_('too many revisions specified'))
42 return start, end
42 return start, end
43
43
44 def revrange(repo, revs):
44 def revrange(repo, revs):
45 """Yield revision as strings from a list of revision specifications."""
45 """Yield revision as strings from a list of revision specifications."""
46
46
47 def revfix(repo, val, defval):
47 def revfix(repo, val, defval):
48 if not val and val != 0 and defval is not None:
48 if not val and val != 0 and defval is not None:
49 return defval
49 return defval
50 return repo.changelog.rev(repo.lookup(val))
50 return repo.changelog.rev(repo.lookup(val))
51
51
52 seen, l = {}, []
52 seen, l = {}, []
53 for spec in revs:
53 for spec in revs:
54 if revrangesep in spec:
54 if revrangesep in spec:
55 start, end = spec.split(revrangesep, 1)
55 start, end = spec.split(revrangesep, 1)
56 start = revfix(repo, start, 0)
56 start = revfix(repo, start, 0)
57 end = revfix(repo, end, repo.changelog.count() - 1)
57 end = revfix(repo, end, repo.changelog.count() - 1)
58 step = start > end and -1 or 1
58 step = start > end and -1 or 1
59 for rev in xrange(start, end+step, step):
59 for rev in xrange(start, end+step, step):
60 if rev in seen:
60 if rev in seen:
61 continue
61 continue
62 seen[rev] = 1
62 seen[rev] = 1
63 l.append(rev)
63 l.append(rev)
64 else:
64 else:
65 rev = revfix(repo, spec, None)
65 rev = revfix(repo, spec, None)
66 if rev in seen:
66 if rev in seen:
67 continue
67 continue
68 seen[rev] = 1
68 seen[rev] = 1
69 l.append(rev)
69 l.append(rev)
70
70
71 return l
71 return l
72
72
73 def make_filename(repo, pat, node,
73 def make_filename(repo, pat, node,
74 total=None, seqno=None, revwidth=None, pathname=None):
74 total=None, seqno=None, revwidth=None, pathname=None):
75 node_expander = {
75 node_expander = {
76 'H': lambda: hex(node),
76 'H': lambda: hex(node),
77 'R': lambda: str(repo.changelog.rev(node)),
77 'R': lambda: str(repo.changelog.rev(node)),
78 'h': lambda: short(node),
78 'h': lambda: short(node),
79 }
79 }
80 expander = {
80 expander = {
81 '%': lambda: '%',
81 '%': lambda: '%',
82 'b': lambda: os.path.basename(repo.root),
82 'b': lambda: os.path.basename(repo.root),
83 }
83 }
84
84
85 try:
85 try:
86 if node:
86 if node:
87 expander.update(node_expander)
87 expander.update(node_expander)
88 if node and revwidth is not None:
88 if node and revwidth is not None:
89 expander['r'] = (lambda:
89 expander['r'] = (lambda:
90 str(repo.changelog.rev(node)).zfill(revwidth))
90 str(repo.changelog.rev(node)).zfill(revwidth))
91 if total is not None:
91 if total is not None:
92 expander['N'] = lambda: str(total)
92 expander['N'] = lambda: str(total)
93 if seqno is not None:
93 if seqno is not None:
94 expander['n'] = lambda: str(seqno)
94 expander['n'] = lambda: str(seqno)
95 if total is not None and seqno is not None:
95 if total is not None and seqno is not None:
96 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
96 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
97 if pathname is not None:
97 if pathname is not None:
98 expander['s'] = lambda: os.path.basename(pathname)
98 expander['s'] = lambda: os.path.basename(pathname)
99 expander['d'] = lambda: os.path.dirname(pathname) or '.'
99 expander['d'] = lambda: os.path.dirname(pathname) or '.'
100 expander['p'] = lambda: pathname
100 expander['p'] = lambda: pathname
101
101
102 newname = []
102 newname = []
103 patlen = len(pat)
103 patlen = len(pat)
104 i = 0
104 i = 0
105 while i < patlen:
105 while i < patlen:
106 c = pat[i]
106 c = pat[i]
107 if c == '%':
107 if c == '%':
108 i += 1
108 i += 1
109 c = pat[i]
109 c = pat[i]
110 c = expander[c]()
110 c = expander[c]()
111 newname.append(c)
111 newname.append(c)
112 i += 1
112 i += 1
113 return ''.join(newname)
113 return ''.join(newname)
114 except KeyError, inst:
114 except KeyError, inst:
115 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
115 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
116 inst.args[0])
116 inst.args[0])
117
117
118 def make_file(repo, pat, node=None,
118 def make_file(repo, pat, node=None,
119 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
119 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
120 if not pat or pat == '-':
120 if not pat or pat == '-':
121 return 'w' in mode and sys.stdout or sys.stdin
121 return 'w' in mode and sys.stdout or sys.stdin
122 if hasattr(pat, 'write') and 'w' in mode:
122 if hasattr(pat, 'write') and 'w' in mode:
123 return pat
123 return pat
124 if hasattr(pat, 'read') and 'r' in mode:
124 if hasattr(pat, 'read') and 'r' in mode:
125 return pat
125 return pat
126 return open(make_filename(repo, pat, node, total, seqno, revwidth,
126 return open(make_filename(repo, pat, node, total, seqno, revwidth,
127 pathname),
127 pathname),
128 mode)
128 mode)
129
129
130 def matchpats(repo, pats=[], opts={}, head='', globbed=False):
130 def matchpats(repo, pats=[], opts={}, head='', globbed=False):
131 cwd = repo.getcwd()
131 cwd = repo.getcwd()
132 if not pats and cwd:
132 if not pats and cwd:
133 opts['include'] = [os.path.join(cwd, i)
133 opts['include'] = [os.path.join(cwd, i)
134 for i in opts.get('include', [])]
134 for i in opts.get('include', [])]
135 opts['exclude'] = [os.path.join(cwd, x)
135 opts['exclude'] = [os.path.join(cwd, x)
136 for x in opts.get('exclude', [])]
136 for x in opts.get('exclude', [])]
137 cwd = ''
137 cwd = ''
138 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
138 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
139 opts.get('exclude'), head, globbed=globbed)
139 opts.get('exclude'), head, globbed=globbed)
140
140
141 def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None,
141 def walk(repo, pats=[], opts={}, node=None, head='', badmatch=None,
142 globbed=False):
142 globbed=False):
143 files, matchfn, anypats = matchpats(repo, pats, opts, head,
143 files, matchfn, anypats = matchpats(repo, pats, opts, head,
144 globbed=globbed)
144 globbed=globbed)
145 exact = dict.fromkeys(files)
145 exact = dict.fromkeys(files)
146 for src, fn in repo.walk(node=node, files=files, match=matchfn,
146 for src, fn in repo.walk(node=node, files=files, match=matchfn,
147 badmatch=badmatch):
147 badmatch=badmatch):
148 yield src, fn, util.pathto(repo.root, repo.getcwd(), fn), fn in exact
148 yield src, fn, util.pathto(repo.root, repo.getcwd(), fn), fn in exact
149
149
150 def findrenames(repo, added=None, removed=None, threshold=0.5):
150 def findrenames(repo, added=None, removed=None, threshold=0.5):
151 if added is None or removed is None:
151 if added is None or removed is None:
152 added, removed = repo.status()[1:3]
152 added, removed = repo.status()[1:3]
153 changes = repo.changelog.read(repo.dirstate.parents()[0])
153 changes = repo.changelog.read(repo.dirstate.parents()[0])
154 mf = repo.manifest.read(changes[0])
154 mf = repo.manifest.read(changes[0])
155 for a in added:
155 for a in added:
156 aa = repo.wread(a)
156 aa = repo.wread(a)
157 bestscore, bestname = None, None
157 bestscore, bestname = None, None
158 for r in removed:
158 for r in removed:
159 rr = repo.file(r).read(mf[r])
159 rr = repo.file(r).read(mf[r])
160 delta = mdiff.textdiff(aa, rr)
160 delta = mdiff.textdiff(aa, rr)
161 if len(delta) < len(aa):
161 if len(delta) < len(aa):
162 myscore = 1.0 - (float(len(delta)) / len(aa))
162 myscore = 1.0 - (float(len(delta)) / len(aa))
163 if bestscore is None or myscore > bestscore:
163 if bestscore is None or myscore > bestscore:
164 bestscore, bestname = myscore, r
164 bestscore, bestname = myscore, r
165 if bestname and bestscore >= threshold:
165 if bestname and bestscore >= threshold:
166 yield bestname, a, bestscore
166 yield bestname, a, bestscore
167
167
168 def addremove(repo, pats=[], opts={}, wlock=None, dry_run=None,
168 def addremove(repo, pats=[], opts={}, wlock=None, dry_run=None,
169 similarity=None):
169 similarity=None):
170 if dry_run is None:
170 if dry_run is None:
171 dry_run = opts.get('dry_run')
171 dry_run = opts.get('dry_run')
172 if similarity is None:
172 if similarity is None:
173 similarity = float(opts.get('similarity') or 0)
173 similarity = float(opts.get('similarity') or 0)
174 add, remove = [], []
174 add, remove = [], []
175 mapping = {}
175 mapping = {}
176 for src, abs, rel, exact in walk(repo, pats, opts):
176 for src, abs, rel, exact in walk(repo, pats, opts):
177 if src == 'f' and repo.dirstate.state(abs) == '?':
177 if src == 'f' and repo.dirstate.state(abs) == '?':
178 add.append(abs)
178 add.append(abs)
179 mapping[abs] = rel, exact
179 mapping[abs] = rel, exact
180 if repo.ui.verbose or not exact:
180 if repo.ui.verbose or not exact:
181 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
181 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
182 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
182 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
183 remove.append(abs)
183 remove.append(abs)
184 mapping[abs] = rel, exact
184 mapping[abs] = rel, exact
185 if repo.ui.verbose or not exact:
185 if repo.ui.verbose or not exact:
186 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
186 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
187 if not dry_run:
187 if not dry_run:
188 repo.add(add, wlock=wlock)
188 repo.add(add, wlock=wlock)
189 repo.remove(remove, wlock=wlock)
189 repo.remove(remove, wlock=wlock)
190 if similarity > 0:
190 if similarity > 0:
191 for old, new, score in findrenames(repo, add, remove, similarity):
191 for old, new, score in findrenames(repo, add, remove, similarity):
192 oldrel, oldexact = mapping[old]
192 oldrel, oldexact = mapping[old]
193 newrel, newexact = mapping[new]
193 newrel, newexact = mapping[new]
194 if repo.ui.verbose or not oldexact or not newexact:
194 if repo.ui.verbose or not oldexact or not newexact:
195 repo.ui.status(_('recording removal of %s as rename to %s '
195 repo.ui.status(_('recording removal of %s as rename to %s '
196 '(%d%% similar)\n') %
196 '(%d%% similar)\n') %
197 (oldrel, newrel, score * 100))
197 (oldrel, newrel, score * 100))
198 if not dry_run:
198 if not dry_run:
199 repo.copy(old, new, wlock=wlock)
199 repo.copy(old, new, wlock=wlock)
200
200
201 class changeset_printer(object):
201 class changeset_printer(object):
202 '''show changeset information when templating not requested.'''
202 '''show changeset information when templating not requested.'''
203
203
204 def __init__(self, ui, repo, patch, brinfo, buffered):
204 def __init__(self, ui, repo, patch, brinfo, buffered):
205 self.ui = ui
205 self.ui = ui
206 self.repo = repo
206 self.repo = repo
207 self.buffered = buffered
207 self.buffered = buffered
208 self.patch = patch
208 self.patch = patch
209 self.brinfo = brinfo
209 self.brinfo = brinfo
210 self.header = {}
210 self.header = {}
211 self.hunk = {}
211 self.hunk = {}
212 self.lastheader = None
212 self.lastheader = None
213
213
214 def flush(self, rev):
214 def flush(self, rev):
215 if rev in self.header:
215 if rev in self.header:
216 h = self.header[rev]
216 h = self.header[rev]
217 if h != self.lastheader:
217 if h != self.lastheader:
218 self.lastheader = h
218 self.lastheader = h
219 self.ui.write(h)
219 self.ui.write(h)
220 del self.header[rev]
220 del self.header[rev]
221 if rev in self.hunk:
221 if rev in self.hunk:
222 self.ui.write(self.hunk[rev])
222 self.ui.write(self.hunk[rev])
223 del self.hunk[rev]
223 del self.hunk[rev]
224 return 1
224 return 1
225 return 0
225 return 0
226
226
227 def show(self, rev=0, changenode=None, copies=(), **props):
227 def show(self, rev=0, changenode=None, copies=(), **props):
228 if self.buffered:
228 if self.buffered:
229 self.ui.pushbuffer()
229 self.ui.pushbuffer()
230 self._show(rev, changenode, copies, props)
230 self._show(rev, changenode, copies, props)
231 self.hunk[rev] = self.ui.popbuffer()
231 self.hunk[rev] = self.ui.popbuffer()
232 else:
232 else:
233 self._show(rev, changenode, copies, props)
233 self._show(rev, changenode, copies, props)
234
234
235 def _show(self, rev, changenode, copies, props):
235 def _show(self, rev, changenode, copies, props):
236 '''show a single changeset or file revision'''
236 '''show a single changeset or file revision'''
237 log = self.repo.changelog
237 log = self.repo.changelog
238 if changenode is None:
238 if changenode is None:
239 changenode = log.node(rev)
239 changenode = log.node(rev)
240 elif not rev:
240 elif not rev:
241 rev = log.rev(changenode)
241 rev = log.rev(changenode)
242
242
243 if self.ui.quiet:
243 if self.ui.quiet:
244 self.ui.write("%d:%s\n" % (rev, short(changenode)))
244 self.ui.write("%d:%s\n" % (rev, short(changenode)))
245 return
245 return
246
246
247 changes = log.read(changenode)
247 changes = log.read(changenode)
248 date = util.datestr(changes[2])
248 date = util.datestr(changes[2])
249 extra = changes[5]
249 extra = changes[5]
250 branch = extra.get("branch")
250 branch = extra.get("branch")
251
251
252 hexfunc = self.ui.debugflag and hex or short
252 hexfunc = self.ui.debugflag and hex or short
253
253
254 parents = log.parentrevs(rev)
254 parents = log.parentrevs(rev)
255 if not self.ui.debugflag:
255 if not self.ui.debugflag:
256 if parents[1] == nullrev:
256 if parents[1] == nullrev:
257 if parents[0] >= rev - 1:
257 if parents[0] >= rev - 1:
258 parents = []
258 parents = []
259 else:
259 else:
260 parents = [parents[0]]
260 parents = [parents[0]]
261 parents = [(p, hexfunc(log.node(p))) for p in parents]
261 parents = [(p, hexfunc(log.node(p))) for p in parents]
262
262
263 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
263 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
264
264
265 # don't show the default branch name
265 # don't show the default branch name
266 if branch != 'default':
266 if branch != 'default':
267 branch = util.tolocal(branch)
267 branch = util.tolocal(branch)
268 self.ui.write(_("branch: %s\n") % branch)
268 self.ui.write(_("branch: %s\n") % branch)
269 for tag in self.repo.nodetags(changenode):
269 for tag in self.repo.nodetags(changenode):
270 self.ui.write(_("tag: %s\n") % tag)
270 self.ui.write(_("tag: %s\n") % tag)
271 for parent in parents:
271 for parent in parents:
272 self.ui.write(_("parent: %d:%s\n") % parent)
272 self.ui.write(_("parent: %d:%s\n") % parent)
273
273
274 if self.brinfo:
274 if self.brinfo:
275 br = self.repo.branchlookup([changenode])
275 br = self.repo.branchlookup([changenode])
276 if br:
276 if br:
277 self.ui.write(_("branch: %s\n") % " ".join(br[changenode]))
277 self.ui.write(_("branch: %s\n") % " ".join(br[changenode]))
278
278
279 if self.ui.debugflag:
279 if self.ui.debugflag:
280 self.ui.write(_("manifest: %d:%s\n") %
280 self.ui.write(_("manifest: %d:%s\n") %
281 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
281 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
282 self.ui.write(_("user: %s\n") % changes[1])
282 self.ui.write(_("user: %s\n") % changes[1])
283 self.ui.write(_("date: %s\n") % date)
283 self.ui.write(_("date: %s\n") % date)
284
284
285 if self.ui.debugflag:
285 if self.ui.debugflag:
286 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
286 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
287 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
287 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
288 files):
288 files):
289 if value:
289 if value:
290 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
290 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
291 elif changes[3] and self.ui.verbose:
291 elif changes[3] and self.ui.verbose:
292 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
292 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
293 if copies and self.ui.verbose:
293 if copies and self.ui.verbose:
294 copies = ['%s (%s)' % c for c in copies]
294 copies = ['%s (%s)' % c for c in copies]
295 self.ui.write(_("copies: %s\n") % ' '.join(copies))
295 self.ui.write(_("copies: %s\n") % ' '.join(copies))
296
296
297 if extra and self.ui.debugflag:
297 if extra and self.ui.debugflag:
298 extraitems = extra.items()
298 extraitems = extra.items()
299 extraitems.sort()
299 extraitems.sort()
300 for key, value in extraitems:
300 for key, value in extraitems:
301 self.ui.write(_("extra: %s=%s\n")
301 self.ui.write(_("extra: %s=%s\n")
302 % (key, value.encode('string_escape')))
302 % (key, value.encode('string_escape')))
303
303
304 description = changes[4].strip()
304 description = changes[4].strip()
305 if description:
305 if description:
306 if self.ui.verbose:
306 if self.ui.verbose:
307 self.ui.write(_("description:\n"))
307 self.ui.write(_("description:\n"))
308 self.ui.write(description)
308 self.ui.write(description)
309 self.ui.write("\n\n")
309 self.ui.write("\n\n")
310 else:
310 else:
311 self.ui.write(_("summary: %s\n") %
311 self.ui.write(_("summary: %s\n") %
312 description.splitlines()[0])
312 description.splitlines()[0])
313 self.ui.write("\n")
313 self.ui.write("\n")
314
314
315 self.showpatch(changenode)
315 self.showpatch(changenode)
316
316
317 def showpatch(self, node):
317 def showpatch(self, node):
318 if self.patch:
318 if self.patch:
319 prev = self.repo.changelog.parents(node)[0]
319 prev = self.repo.changelog.parents(node)[0]
320 patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui)
320 patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui)
321 self.ui.write("\n")
321 self.ui.write("\n")
322
322
323 class changeset_templater(changeset_printer):
323 class changeset_templater(changeset_printer):
324 '''format changeset information.'''
324 '''format changeset information.'''
325
325
326 def __init__(self, ui, repo, patch, brinfo, mapfile, buffered):
326 def __init__(self, ui, repo, patch, brinfo, mapfile, buffered):
327 changeset_printer.__init__(self, ui, repo, patch, brinfo, buffered)
327 changeset_printer.__init__(self, ui, repo, patch, brinfo, buffered)
328 self.t = templater.templater(mapfile, templater.common_filters,
328 filters = templater.common_filters.copy()
329 cache={'parent': '{rev}:{node|short} ',
329 filters['formatnode'] = (ui.debugflag and (lambda x: x)
330 'manifest': '{rev}:{node|short}',
330 or (lambda x: x[:12]))
331 'filecopy': '{name} ({source})'})
331 self.t = templater.templater(mapfile, filters,
332 cache={
333 'parent': '{rev}:{node|formatnode} ',
334 'manifest': '{rev}:{node|formatnode}',
335 'filecopy': '{name} ({source})'})
332
336
333 def use_template(self, t):
337 def use_template(self, t):
334 '''set template string to use'''
338 '''set template string to use'''
335 self.t.cache['changeset'] = t
339 self.t.cache['changeset'] = t
336
340
337 def _show(self, rev, changenode, copies, props):
341 def _show(self, rev, changenode, copies, props):
338 '''show a single changeset or file revision'''
342 '''show a single changeset or file revision'''
339 log = self.repo.changelog
343 log = self.repo.changelog
340 if changenode is None:
344 if changenode is None:
341 changenode = log.node(rev)
345 changenode = log.node(rev)
342 elif not rev:
346 elif not rev:
343 rev = log.rev(changenode)
347 rev = log.rev(changenode)
344
348
345 changes = log.read(changenode)
349 changes = log.read(changenode)
346
350
347 def showlist(name, values, plural=None, **args):
351 def showlist(name, values, plural=None, **args):
348 '''expand set of values.
352 '''expand set of values.
349 name is name of key in template map.
353 name is name of key in template map.
350 values is list of strings or dicts.
354 values is list of strings or dicts.
351 plural is plural of name, if not simply name + 's'.
355 plural is plural of name, if not simply name + 's'.
352
356
353 expansion works like this, given name 'foo'.
357 expansion works like this, given name 'foo'.
354
358
355 if values is empty, expand 'no_foos'.
359 if values is empty, expand 'no_foos'.
356
360
357 if 'foo' not in template map, return values as a string,
361 if 'foo' not in template map, return values as a string,
358 joined by space.
362 joined by space.
359
363
360 expand 'start_foos'.
364 expand 'start_foos'.
361
365
362 for each value, expand 'foo'. if 'last_foo' in template
366 for each value, expand 'foo'. if 'last_foo' in template
363 map, expand it instead of 'foo' for last key.
367 map, expand it instead of 'foo' for last key.
364
368
365 expand 'end_foos'.
369 expand 'end_foos'.
366 '''
370 '''
367 if plural: names = plural
371 if plural: names = plural
368 else: names = name + 's'
372 else: names = name + 's'
369 if not values:
373 if not values:
370 noname = 'no_' + names
374 noname = 'no_' + names
371 if noname in self.t:
375 if noname in self.t:
372 yield self.t(noname, **args)
376 yield self.t(noname, **args)
373 return
377 return
374 if name not in self.t:
378 if name not in self.t:
375 if isinstance(values[0], str):
379 if isinstance(values[0], str):
376 yield ' '.join(values)
380 yield ' '.join(values)
377 else:
381 else:
378 for v in values:
382 for v in values:
379 yield dict(v, **args)
383 yield dict(v, **args)
380 return
384 return
381 startname = 'start_' + names
385 startname = 'start_' + names
382 if startname in self.t:
386 if startname in self.t:
383 yield self.t(startname, **args)
387 yield self.t(startname, **args)
384 vargs = args.copy()
388 vargs = args.copy()
385 def one(v, tag=name):
389 def one(v, tag=name):
386 try:
390 try:
387 vargs.update(v)
391 vargs.update(v)
388 except (AttributeError, ValueError):
392 except (AttributeError, ValueError):
389 try:
393 try:
390 for a, b in v:
394 for a, b in v:
391 vargs[a] = b
395 vargs[a] = b
392 except ValueError:
396 except ValueError:
393 vargs[name] = v
397 vargs[name] = v
394 return self.t(tag, **vargs)
398 return self.t(tag, **vargs)
395 lastname = 'last_' + name
399 lastname = 'last_' + name
396 if lastname in self.t:
400 if lastname in self.t:
397 last = values.pop()
401 last = values.pop()
398 else:
402 else:
399 last = None
403 last = None
400 for v in values:
404 for v in values:
401 yield one(v)
405 yield one(v)
402 if last is not None:
406 if last is not None:
403 yield one(last, tag=lastname)
407 yield one(last, tag=lastname)
404 endname = 'end_' + names
408 endname = 'end_' + names
405 if endname in self.t:
409 if endname in self.t:
406 yield self.t(endname, **args)
410 yield self.t(endname, **args)
407
411
408 def showbranches(**args):
412 def showbranches(**args):
409 branch = changes[5].get("branch")
413 branch = changes[5].get("branch")
410 if branch != 'default':
414 if branch != 'default':
411 branch = util.tolocal(branch)
415 branch = util.tolocal(branch)
412 return showlist('branch', [branch], plural='branches', **args)
416 return showlist('branch', [branch], plural='branches', **args)
413 # add old style branches if requested
417 # add old style branches if requested
414 if self.brinfo:
418 if self.brinfo:
415 br = self.repo.branchlookup([changenode])
419 br = self.repo.branchlookup([changenode])
416 if changenode in br:
420 if changenode in br:
417 return showlist('branch', br[changenode],
421 return showlist('branch', br[changenode],
418 plural='branches', **args)
422 plural='branches', **args)
419
423
420 def showparents(**args):
424 def showparents(**args):
421 parents = [[('rev', log.rev(p)), ('node', hex(p))]
425 parents = [[('rev', log.rev(p)), ('node', hex(p))]
422 for p in log.parents(changenode)
426 for p in log.parents(changenode)
423 if self.ui.debugflag or p != nullid]
427 if self.ui.debugflag or p != nullid]
424 if (not self.ui.debugflag and len(parents) == 1 and
428 if (not self.ui.debugflag and len(parents) == 1 and
425 parents[0][0][1] == rev - 1):
429 parents[0][0][1] == rev - 1):
426 return
430 return
427 return showlist('parent', parents, **args)
431 return showlist('parent', parents, **args)
428
432
429 def showtags(**args):
433 def showtags(**args):
430 return showlist('tag', self.repo.nodetags(changenode), **args)
434 return showlist('tag', self.repo.nodetags(changenode), **args)
431
435
432 def showextras(**args):
436 def showextras(**args):
433 extras = changes[5].items()
437 extras = changes[5].items()
434 extras.sort()
438 extras.sort()
435 for key, value in extras:
439 for key, value in extras:
436 args = args.copy()
440 args = args.copy()
437 args.update(dict(key=key, value=value))
441 args.update(dict(key=key, value=value))
438 yield self.t('extra', **args)
442 yield self.t('extra', **args)
439
443
440 def showcopies(**args):
444 def showcopies(**args):
441 c = [{'name': x[0], 'source': x[1]} for x in copies]
445 c = [{'name': x[0], 'source': x[1]} for x in copies]
442 return showlist('file_copy', c, plural='file_copies', **args)
446 return showlist('file_copy', c, plural='file_copies', **args)
443
447
444 if self.ui.debugflag:
448 if self.ui.debugflag:
445 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
449 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
446 def showfiles(**args):
450 def showfiles(**args):
447 return showlist('file', files[0], **args)
451 return showlist('file', files[0], **args)
448 def showadds(**args):
452 def showadds(**args):
449 return showlist('file_add', files[1], **args)
453 return showlist('file_add', files[1], **args)
450 def showdels(**args):
454 def showdels(**args):
451 return showlist('file_del', files[2], **args)
455 return showlist('file_del', files[2], **args)
452 def showmanifest(**args):
456 def showmanifest(**args):
453 args = args.copy()
457 args = args.copy()
454 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
458 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
455 node=hex(changes[0])))
459 node=hex(changes[0])))
456 return self.t('manifest', **args)
460 return self.t('manifest', **args)
457 else:
461 else:
458 def showfiles(**args):
462 def showfiles(**args):
459 return showlist('file', changes[3], **args)
463 return showlist('file', changes[3], **args)
460 showadds = ''
464 showadds = ''
461 showdels = ''
465 showdels = ''
462 showmanifest = ''
466 showmanifest = ''
463
467
464 defprops = {
468 defprops = {
465 'author': changes[1],
469 'author': changes[1],
466 'branches': showbranches,
470 'branches': showbranches,
467 'date': changes[2],
471 'date': changes[2],
468 'desc': changes[4],
472 'desc': changes[4],
469 'file_adds': showadds,
473 'file_adds': showadds,
470 'file_dels': showdels,
474 'file_dels': showdels,
471 'files': showfiles,
475 'files': showfiles,
472 'file_copies': showcopies,
476 'file_copies': showcopies,
473 'manifest': showmanifest,
477 'manifest': showmanifest,
474 'node': hex(changenode),
478 'node': hex(changenode),
475 'parents': showparents,
479 'parents': showparents,
476 'rev': rev,
480 'rev': rev,
477 'tags': showtags,
481 'tags': showtags,
478 'extras': showextras,
482 'extras': showextras,
479 }
483 }
480 props = props.copy()
484 props = props.copy()
481 props.update(defprops)
485 props.update(defprops)
482
486
483 try:
487 try:
484 if self.ui.debugflag and 'header_debug' in self.t:
488 if self.ui.debugflag and 'header_debug' in self.t:
485 key = 'header_debug'
489 key = 'header_debug'
486 elif self.ui.quiet and 'header_quiet' in self.t:
490 elif self.ui.quiet and 'header_quiet' in self.t:
487 key = 'header_quiet'
491 key = 'header_quiet'
488 elif self.ui.verbose and 'header_verbose' in self.t:
492 elif self.ui.verbose and 'header_verbose' in self.t:
489 key = 'header_verbose'
493 key = 'header_verbose'
490 elif 'header' in self.t:
494 elif 'header' in self.t:
491 key = 'header'
495 key = 'header'
492 else:
496 else:
493 key = ''
497 key = ''
494 if key:
498 if key:
495 h = templater.stringify(self.t(key, **props))
499 h = templater.stringify(self.t(key, **props))
496 if self.buffered:
500 if self.buffered:
497 self.header[rev] = h
501 self.header[rev] = h
498 else:
502 else:
499 self.ui.write(h)
503 self.ui.write(h)
500 if self.ui.debugflag and 'changeset_debug' in self.t:
504 if self.ui.debugflag and 'changeset_debug' in self.t:
501 key = 'changeset_debug'
505 key = 'changeset_debug'
502 elif self.ui.quiet and 'changeset_quiet' in self.t:
506 elif self.ui.quiet and 'changeset_quiet' in self.t:
503 key = 'changeset_quiet'
507 key = 'changeset_quiet'
504 elif self.ui.verbose and 'changeset_verbose' in self.t:
508 elif self.ui.verbose and 'changeset_verbose' in self.t:
505 key = 'changeset_verbose'
509 key = 'changeset_verbose'
506 else:
510 else:
507 key = 'changeset'
511 key = 'changeset'
508 self.ui.write(templater.stringify(self.t(key, **props)))
512 self.ui.write(templater.stringify(self.t(key, **props)))
509 self.showpatch(changenode)
513 self.showpatch(changenode)
510 except KeyError, inst:
514 except KeyError, inst:
511 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
515 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
512 inst.args[0]))
516 inst.args[0]))
513 except SyntaxError, inst:
517 except SyntaxError, inst:
514 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
518 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
515
519
516 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
520 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
517 """show one changeset using template or regular display.
521 """show one changeset using template or regular display.
518
522
519 Display format will be the first non-empty hit of:
523 Display format will be the first non-empty hit of:
520 1. option 'template'
524 1. option 'template'
521 2. option 'style'
525 2. option 'style'
522 3. [ui] setting 'logtemplate'
526 3. [ui] setting 'logtemplate'
523 4. [ui] setting 'style'
527 4. [ui] setting 'style'
524 If all of these values are either the unset or the empty string,
528 If all of these values are either the unset or the empty string,
525 regular display via changeset_printer() is done.
529 regular display via changeset_printer() is done.
526 """
530 """
527 # options
531 # options
528 patch = False
532 patch = False
529 if opts.get('patch'):
533 if opts.get('patch'):
530 patch = matchfn or util.always
534 patch = matchfn or util.always
531
535
532 br = None
536 br = None
533 if opts.get('branches'):
537 if opts.get('branches'):
534 ui.warn(_("the --branches option is deprecated, "
538 ui.warn(_("the --branches option is deprecated, "
535 "please use 'hg branches' instead\n"))
539 "please use 'hg branches' instead\n"))
536 br = True
540 br = True
537 tmpl = opts.get('template')
541 tmpl = opts.get('template')
538 mapfile = None
542 mapfile = None
539 if tmpl:
543 if tmpl:
540 tmpl = templater.parsestring(tmpl, quoted=False)
544 tmpl = templater.parsestring(tmpl, quoted=False)
541 else:
545 else:
542 mapfile = opts.get('style')
546 mapfile = opts.get('style')
543 # ui settings
547 # ui settings
544 if not mapfile:
548 if not mapfile:
545 tmpl = ui.config('ui', 'logtemplate')
549 tmpl = ui.config('ui', 'logtemplate')
546 if tmpl:
550 if tmpl:
547 tmpl = templater.parsestring(tmpl)
551 tmpl = templater.parsestring(tmpl)
548 else:
552 else:
549 mapfile = ui.config('ui', 'style')
553 mapfile = ui.config('ui', 'style')
550
554
551 if tmpl or mapfile:
555 if tmpl or mapfile:
552 if mapfile:
556 if mapfile:
553 if not os.path.split(mapfile)[0]:
557 if not os.path.split(mapfile)[0]:
554 mapname = (templater.templatepath('map-cmdline.' + mapfile)
558 mapname = (templater.templatepath('map-cmdline.' + mapfile)
555 or templater.templatepath(mapfile))
559 or templater.templatepath(mapfile))
556 if mapname: mapfile = mapname
560 if mapname: mapfile = mapname
557 try:
561 try:
558 t = changeset_templater(ui, repo, patch, br, mapfile, buffered)
562 t = changeset_templater(ui, repo, patch, br, mapfile, buffered)
559 except SyntaxError, inst:
563 except SyntaxError, inst:
560 raise util.Abort(inst.args[0])
564 raise util.Abort(inst.args[0])
561 if tmpl: t.use_template(tmpl)
565 if tmpl: t.use_template(tmpl)
562 return t
566 return t
563 return changeset_printer(ui, repo, patch, br, buffered)
567 return changeset_printer(ui, repo, patch, br, buffered)
564
568
565 def finddate(ui, repo, date):
569 def finddate(ui, repo, date):
566 """Find the tipmost changeset that matches the given date spec"""
570 """Find the tipmost changeset that matches the given date spec"""
567 df = util.matchdate(date + " to " + date)
571 df = util.matchdate(date + " to " + date)
568 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
572 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
569 changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None})
573 changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None})
570 results = {}
574 results = {}
571 for st, rev, fns in changeiter:
575 for st, rev, fns in changeiter:
572 if st == 'add':
576 if st == 'add':
573 d = get(rev)[2]
577 d = get(rev)[2]
574 if df(d[0]):
578 if df(d[0]):
575 results[rev] = d
579 results[rev] = d
576 elif st == 'iter':
580 elif st == 'iter':
577 if rev in results:
581 if rev in results:
578 ui.status("Found revision %s from %s\n" %
582 ui.status("Found revision %s from %s\n" %
579 (rev, util.datestr(results[rev])))
583 (rev, util.datestr(results[rev])))
580 return str(rev)
584 return str(rev)
581
585
582 raise util.Abort(_("revision matching date not found"))
586 raise util.Abort(_("revision matching date not found"))
583
587
584 def walkchangerevs(ui, repo, pats, change, opts):
588 def walkchangerevs(ui, repo, pats, change, opts):
585 '''Iterate over files and the revs they changed in.
589 '''Iterate over files and the revs they changed in.
586
590
587 Callers most commonly need to iterate backwards over the history
591 Callers most commonly need to iterate backwards over the history
588 it is interested in. Doing so has awful (quadratic-looking)
592 it is interested in. Doing so has awful (quadratic-looking)
589 performance, so we use iterators in a "windowed" way.
593 performance, so we use iterators in a "windowed" way.
590
594
591 We walk a window of revisions in the desired order. Within the
595 We walk a window of revisions in the desired order. Within the
592 window, we first walk forwards to gather data, then in the desired
596 window, we first walk forwards to gather data, then in the desired
593 order (usually backwards) to display it.
597 order (usually backwards) to display it.
594
598
595 This function returns an (iterator, matchfn) tuple. The iterator
599 This function returns an (iterator, matchfn) tuple. The iterator
596 yields 3-tuples. They will be of one of the following forms:
600 yields 3-tuples. They will be of one of the following forms:
597
601
598 "window", incrementing, lastrev: stepping through a window,
602 "window", incrementing, lastrev: stepping through a window,
599 positive if walking forwards through revs, last rev in the
603 positive if walking forwards through revs, last rev in the
600 sequence iterated over - use to reset state for the current window
604 sequence iterated over - use to reset state for the current window
601
605
602 "add", rev, fns: out-of-order traversal of the given file names
606 "add", rev, fns: out-of-order traversal of the given file names
603 fns, which changed during revision rev - use to gather data for
607 fns, which changed during revision rev - use to gather data for
604 possible display
608 possible display
605
609
606 "iter", rev, None: in-order traversal of the revs earlier iterated
610 "iter", rev, None: in-order traversal of the revs earlier iterated
607 over with "add" - use to display data'''
611 over with "add" - use to display data'''
608
612
609 def increasing_windows(start, end, windowsize=8, sizelimit=512):
613 def increasing_windows(start, end, windowsize=8, sizelimit=512):
610 if start < end:
614 if start < end:
611 while start < end:
615 while start < end:
612 yield start, min(windowsize, end-start)
616 yield start, min(windowsize, end-start)
613 start += windowsize
617 start += windowsize
614 if windowsize < sizelimit:
618 if windowsize < sizelimit:
615 windowsize *= 2
619 windowsize *= 2
616 else:
620 else:
617 while start > end:
621 while start > end:
618 yield start, min(windowsize, start-end-1)
622 yield start, min(windowsize, start-end-1)
619 start -= windowsize
623 start -= windowsize
620 if windowsize < sizelimit:
624 if windowsize < sizelimit:
621 windowsize *= 2
625 windowsize *= 2
622
626
623 files, matchfn, anypats = matchpats(repo, pats, opts)
627 files, matchfn, anypats = matchpats(repo, pats, opts)
624 follow = opts.get('follow') or opts.get('follow_first')
628 follow = opts.get('follow') or opts.get('follow_first')
625
629
626 if repo.changelog.count() == 0:
630 if repo.changelog.count() == 0:
627 return [], matchfn
631 return [], matchfn
628
632
629 if follow:
633 if follow:
630 defrange = '%s:0' % repo.changectx().rev()
634 defrange = '%s:0' % repo.changectx().rev()
631 else:
635 else:
632 defrange = 'tip:0'
636 defrange = 'tip:0'
633 revs = revrange(repo, opts['rev'] or [defrange])
637 revs = revrange(repo, opts['rev'] or [defrange])
634 wanted = {}
638 wanted = {}
635 slowpath = anypats or opts.get('removed')
639 slowpath = anypats or opts.get('removed')
636 fncache = {}
640 fncache = {}
637
641
638 if not slowpath and not files:
642 if not slowpath and not files:
639 # No files, no patterns. Display all revs.
643 # No files, no patterns. Display all revs.
640 wanted = dict.fromkeys(revs)
644 wanted = dict.fromkeys(revs)
641 copies = []
645 copies = []
642 if not slowpath:
646 if not slowpath:
643 # Only files, no patterns. Check the history of each file.
647 # Only files, no patterns. Check the history of each file.
644 def filerevgen(filelog, node):
648 def filerevgen(filelog, node):
645 cl_count = repo.changelog.count()
649 cl_count = repo.changelog.count()
646 if node is None:
650 if node is None:
647 last = filelog.count() - 1
651 last = filelog.count() - 1
648 else:
652 else:
649 last = filelog.rev(node)
653 last = filelog.rev(node)
650 for i, window in increasing_windows(last, nullrev):
654 for i, window in increasing_windows(last, nullrev):
651 revs = []
655 revs = []
652 for j in xrange(i - window, i + 1):
656 for j in xrange(i - window, i + 1):
653 n = filelog.node(j)
657 n = filelog.node(j)
654 revs.append((filelog.linkrev(n),
658 revs.append((filelog.linkrev(n),
655 follow and filelog.renamed(n)))
659 follow and filelog.renamed(n)))
656 revs.reverse()
660 revs.reverse()
657 for rev in revs:
661 for rev in revs:
658 # only yield rev for which we have the changelog, it can
662 # only yield rev for which we have the changelog, it can
659 # happen while doing "hg log" during a pull or commit
663 # happen while doing "hg log" during a pull or commit
660 if rev[0] < cl_count:
664 if rev[0] < cl_count:
661 yield rev
665 yield rev
662 def iterfiles():
666 def iterfiles():
663 for filename in files:
667 for filename in files:
664 yield filename, None
668 yield filename, None
665 for filename_node in copies:
669 for filename_node in copies:
666 yield filename_node
670 yield filename_node
667 minrev, maxrev = min(revs), max(revs)
671 minrev, maxrev = min(revs), max(revs)
668 for file_, node in iterfiles():
672 for file_, node in iterfiles():
669 filelog = repo.file(file_)
673 filelog = repo.file(file_)
670 # A zero count may be a directory or deleted file, so
674 # A zero count may be a directory or deleted file, so
671 # try to find matching entries on the slow path.
675 # try to find matching entries on the slow path.
672 if filelog.count() == 0:
676 if filelog.count() == 0:
673 slowpath = True
677 slowpath = True
674 break
678 break
675 for rev, copied in filerevgen(filelog, node):
679 for rev, copied in filerevgen(filelog, node):
676 if rev <= maxrev:
680 if rev <= maxrev:
677 if rev < minrev:
681 if rev < minrev:
678 break
682 break
679 fncache.setdefault(rev, [])
683 fncache.setdefault(rev, [])
680 fncache[rev].append(file_)
684 fncache[rev].append(file_)
681 wanted[rev] = 1
685 wanted[rev] = 1
682 if follow and copied:
686 if follow and copied:
683 copies.append(copied)
687 copies.append(copied)
684 if slowpath:
688 if slowpath:
685 if follow:
689 if follow:
686 raise util.Abort(_('can only follow copies/renames for explicit '
690 raise util.Abort(_('can only follow copies/renames for explicit '
687 'file names'))
691 'file names'))
688
692
689 # The slow path checks files modified in every changeset.
693 # The slow path checks files modified in every changeset.
690 def changerevgen():
694 def changerevgen():
691 for i, window in increasing_windows(repo.changelog.count()-1,
695 for i, window in increasing_windows(repo.changelog.count()-1,
692 nullrev):
696 nullrev):
693 for j in xrange(i - window, i + 1):
697 for j in xrange(i - window, i + 1):
694 yield j, change(j)[3]
698 yield j, change(j)[3]
695
699
696 for rev, changefiles in changerevgen():
700 for rev, changefiles in changerevgen():
697 matches = filter(matchfn, changefiles)
701 matches = filter(matchfn, changefiles)
698 if matches:
702 if matches:
699 fncache[rev] = matches
703 fncache[rev] = matches
700 wanted[rev] = 1
704 wanted[rev] = 1
701
705
702 class followfilter:
706 class followfilter:
703 def __init__(self, onlyfirst=False):
707 def __init__(self, onlyfirst=False):
704 self.startrev = nullrev
708 self.startrev = nullrev
705 self.roots = []
709 self.roots = []
706 self.onlyfirst = onlyfirst
710 self.onlyfirst = onlyfirst
707
711
708 def match(self, rev):
712 def match(self, rev):
709 def realparents(rev):
713 def realparents(rev):
710 if self.onlyfirst:
714 if self.onlyfirst:
711 return repo.changelog.parentrevs(rev)[0:1]
715 return repo.changelog.parentrevs(rev)[0:1]
712 else:
716 else:
713 return filter(lambda x: x != nullrev,
717 return filter(lambda x: x != nullrev,
714 repo.changelog.parentrevs(rev))
718 repo.changelog.parentrevs(rev))
715
719
716 if self.startrev == nullrev:
720 if self.startrev == nullrev:
717 self.startrev = rev
721 self.startrev = rev
718 return True
722 return True
719
723
720 if rev > self.startrev:
724 if rev > self.startrev:
721 # forward: all descendants
725 # forward: all descendants
722 if not self.roots:
726 if not self.roots:
723 self.roots.append(self.startrev)
727 self.roots.append(self.startrev)
724 for parent in realparents(rev):
728 for parent in realparents(rev):
725 if parent in self.roots:
729 if parent in self.roots:
726 self.roots.append(rev)
730 self.roots.append(rev)
727 return True
731 return True
728 else:
732 else:
729 # backwards: all parents
733 # backwards: all parents
730 if not self.roots:
734 if not self.roots:
731 self.roots.extend(realparents(self.startrev))
735 self.roots.extend(realparents(self.startrev))
732 if rev in self.roots:
736 if rev in self.roots:
733 self.roots.remove(rev)
737 self.roots.remove(rev)
734 self.roots.extend(realparents(rev))
738 self.roots.extend(realparents(rev))
735 return True
739 return True
736
740
737 return False
741 return False
738
742
739 # it might be worthwhile to do this in the iterator if the rev range
743 # it might be worthwhile to do this in the iterator if the rev range
740 # is descending and the prune args are all within that range
744 # is descending and the prune args are all within that range
741 for rev in opts.get('prune', ()):
745 for rev in opts.get('prune', ()):
742 rev = repo.changelog.rev(repo.lookup(rev))
746 rev = repo.changelog.rev(repo.lookup(rev))
743 ff = followfilter()
747 ff = followfilter()
744 stop = min(revs[0], revs[-1])
748 stop = min(revs[0], revs[-1])
745 for x in xrange(rev, stop-1, -1):
749 for x in xrange(rev, stop-1, -1):
746 if ff.match(x) and x in wanted:
750 if ff.match(x) and x in wanted:
747 del wanted[x]
751 del wanted[x]
748
752
749 def iterate():
753 def iterate():
750 if follow and not files:
754 if follow and not files:
751 ff = followfilter(onlyfirst=opts.get('follow_first'))
755 ff = followfilter(onlyfirst=opts.get('follow_first'))
752 def want(rev):
756 def want(rev):
753 if ff.match(rev) and rev in wanted:
757 if ff.match(rev) and rev in wanted:
754 return True
758 return True
755 return False
759 return False
756 else:
760 else:
757 def want(rev):
761 def want(rev):
758 return rev in wanted
762 return rev in wanted
759
763
760 for i, window in increasing_windows(0, len(revs)):
764 for i, window in increasing_windows(0, len(revs)):
761 yield 'window', revs[0] < revs[-1], revs[-1]
765 yield 'window', revs[0] < revs[-1], revs[-1]
762 nrevs = [rev for rev in revs[i:i+window] if want(rev)]
766 nrevs = [rev for rev in revs[i:i+window] if want(rev)]
763 srevs = list(nrevs)
767 srevs = list(nrevs)
764 srevs.sort()
768 srevs.sort()
765 for rev in srevs:
769 for rev in srevs:
766 fns = fncache.get(rev)
770 fns = fncache.get(rev)
767 if not fns:
771 if not fns:
768 def fns_generator():
772 def fns_generator():
769 for f in change(rev)[3]:
773 for f in change(rev)[3]:
770 if matchfn(f):
774 if matchfn(f):
771 yield f
775 yield f
772 fns = fns_generator()
776 fns = fns_generator()
773 yield 'add', rev, fns
777 yield 'add', rev, fns
774 for rev in nrevs:
778 for rev in nrevs:
775 yield 'iter', rev, None
779 yield 'iter', rev, None
776 return iterate(), matchfn
780 return iterate(), matchfn
@@ -1,22 +1,21 b''
1 changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{short_parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
1 changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
2 changeset_quiet = '{rev}:{node|short}\n'
2 changeset_quiet = '{rev}:{node|short}\n'
3 changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{files}{file_adds}{file_dels}{file_copies}description:\n{desc|strip}\n\n\n'
3 changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{files}{file_adds}{file_dels}{file_copies}description:\n{desc|strip}\n\n\n'
4 changeset_debug = 'changeset: {rev}:{node}\n{branches}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{files}{file_adds}{file_dels}{file_copies}{extras}description:\n{desc|strip}\n\n\n'
4 changeset_debug = 'changeset: {rev}:{node}\n{branches}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{files}{file_adds}{file_dels}{file_copies}{extras}description:\n{desc|strip}\n\n\n'
5 start_files = 'files: '
5 start_files = 'files: '
6 file = ' {file}'
6 file = ' {file}'
7 end_files = '\n'
7 end_files = '\n'
8 start_file_adds = 'files+: '
8 start_file_adds = 'files+: '
9 file_add = ' {file_add}'
9 file_add = ' {file_add}'
10 end_file_adds = '\n'
10 end_file_adds = '\n'
11 start_file_dels = 'files-: '
11 start_file_dels = 'files-: '
12 file_del = ' {file_del}'
12 file_del = ' {file_del}'
13 end_file_dels = '\n'
13 end_file_dels = '\n'
14 start_file_copies = 'copies: '
14 start_file_copies = 'copies: '
15 file_copy = ' {name} ({source})'
15 file_copy = ' {name} ({source})'
16 end_file_copies = '\n'
16 end_file_copies = '\n'
17 short_parent = 'parent: {rev}:{node|short}\n'
17 parent = 'parent: {rev}:{node|formatnode}\n'
18 parent = 'parent: {rev}:{node}\n'
19 manifest = 'manifest: {rev}:{node}\n'
18 manifest = 'manifest: {rev}:{node}\n'
20 branch = 'branch: {branch}\n'
19 branch = 'branch: {branch}\n'
21 tag = 'tag: {tag}\n'
20 tag = 'tag: {tag}\n'
22 extra = 'extra: {key}={value|stringescape}\n'
21 extra = 'extra: {key}={value|stringescape}\n'
@@ -1,103 +1,113 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init a
3 hg init a
4 cd a
4 cd a
5 echo a > a
5 echo a > a
6 hg add a
6 hg add a
7 echo line 1 > b
7 echo line 1 > b
8 echo line 2 >> b
8 echo line 2 >> b
9 hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
9 hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
10 hg add b
10 hg add b
11 echo other 1 > c
11 echo other 1 > c
12 echo other 2 >> c
12 echo other 2 >> c
13 echo >> c
13 echo >> c
14 echo other 3 >> c
14 echo other 3 >> c
15 hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15 hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
16 hg add c
16 hg add c
17 hg commit -m 'no person' -d '1200000 0' -u 'other@place'
17 hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 echo c >> c
18 echo c >> c
19 hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
19 hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20 echo foo > .hg/branch
20 echo foo > .hg/branch
21 hg commit -m 'new branch' -d '1400000 0' -u 'person'
21 hg commit -m 'new branch' -d '1400000 0' -u 'person'
22
22
23 # make sure user/global hgrc does not affect tests
23 # make sure user/global hgrc does not affect tests
24 echo '[ui]' > .hg/hgrc
24 echo '[ui]' > .hg/hgrc
25 echo 'logtemplate =' >> .hg/hgrc
25 echo 'logtemplate =' >> .hg/hgrc
26 echo 'style =' >> .hg/hgrc
26 echo 'style =' >> .hg/hgrc
27
27
28 echo '# default style is like normal output'
28 echo '# default style is like normal output'
29 echo '# normal'
29 echo '# normal'
30 hg log > log.out
30 hg log > log.out
31 hg log --style default > style.out
31 hg log --style default > style.out
32 diff log.out style.out
32 diff log.out style.out
33 echo '# verbose'
33 echo '# verbose'
34 hg log -v > log.out
34 hg log -v > log.out
35 hg log -v --style default > style.out
35 hg log -v --style default > style.out
36 diff log.out style.out
36 diff log.out style.out
37 echo '# debug'
37 echo '# debug'
38 hg log --debug > log.out
38 hg log --debug > log.out
39 hg log --debug --style default > style.out
39 hg log --debug --style default > style.out
40 diff log.out style.out
40 diff log.out style.out
41
41
42 echo '# revision with no copies (used to print a traceback)'
42 echo '# revision with no copies (used to print a traceback)'
43 hg tip -v --template '\n'
43 hg tip -v --template '\n'
44
44
45 echo '# compact style works'
45 echo '# compact style works'
46 hg log --style compact
46 hg log --style compact
47 hg log -v --style compact
47 hg log -v --style compact
48 hg log --debug --style compact
48 hg log --debug --style compact
49
49
50 echo '# error if style not readable'
50 echo '# error if style not readable'
51 touch q
51 touch q
52 chmod 0 q
52 chmod 0 q
53 hg log --style ./q
53 hg log --style ./q
54
54
55 echo '# error if no style'
55 echo '# error if no style'
56 hg log --style notexist
56 hg log --style notexist
57
57
58 echo '# error if style missing key'
58 echo '# error if style missing key'
59 echo 'q = q' > t
59 echo 'q = q' > t
60 hg log --style ./t
60 hg log --style ./t
61
61
62 echo '# error if include fails'
62 echo '# error if include fails'
63 echo 'changeset = q' >> t
63 echo 'changeset = q' >> t
64 hg log --style ./t
64 hg log --style ./t
65
65
66 echo '# include works'
66 echo '# include works'
67 rm q
67 rm q
68 echo '{rev}' > q
68 echo '{rev}' > q
69 hg log --style ./t
69 hg log --style ./t
70
70
71 echo '# ui.style works'
71 echo '# ui.style works'
72 echo '[ui]' > .hg/hgrc
72 echo '[ui]' > .hg/hgrc
73 echo 'style = t' >> .hg/hgrc
73 echo 'style = t' >> .hg/hgrc
74 hg log
74 hg log
75
75
76 echo '# issue338'
76 echo '# issue338'
77 hg log --style=changelog > changelog
77 hg log --style=changelog > changelog
78 cat changelog
78 cat changelog
79
79
80 echo "# keys work"
80 echo "# keys work"
81 for key in author branches date desc file_adds file_dels files \
81 for key in author branches date desc file_adds file_dels files \
82 manifest node parents rev tags; do
82 manifest node parents rev tags; do
83 for mode in '' --verbose --debug; do
83 for mode in '' --verbose --debug; do
84 hg log $mode --template "$key$mode: {$key}\n"
84 hg log $mode --template "$key$mode: {$key}\n"
85 done
85 done
86 done
86 done
87
87
88 echo '# filters work'
88 echo '# filters work'
89 hg log --template '{author|domain}\n'
89 hg log --template '{author|domain}\n'
90 hg log --template '{author|person}\n'
90 hg log --template '{author|person}\n'
91 hg log --template '{author|user}\n'
91 hg log --template '{author|user}\n'
92 hg log --template '{date|age}\n' > /dev/null || exit 1
92 hg log --template '{date|age}\n' > /dev/null || exit 1
93 hg log --template '{date|date}\n'
93 hg log --template '{date|date}\n'
94 hg log --template '{date|isodate}\n'
94 hg log --template '{date|isodate}\n'
95 hg log --template '{date|rfc822date}\n'
95 hg log --template '{date|rfc822date}\n'
96 hg log --template '{desc|firstline}\n'
96 hg log --template '{desc|firstline}\n'
97 hg log --template '{node|short}\n'
97 hg log --template '{node|short}\n'
98
98
99 echo '# formatnode filter works'
100 echo '# quiet'
101 hg -q log -r 0 --template '#node|formatnode#\n'
102 echo '# normal'
103 hg log -r 0 --template '#node|formatnode#\n'
104 echo '# verbose'
105 hg -v log -r 0 --template '#node|formatnode#\n'
106 echo '# debug'
107 hg --debug log -r 0 --template '#node|formatnode#\n'
108
99 echo '# error on syntax'
109 echo '# error on syntax'
100 echo 'x = "f' >> t
110 echo 'x = "f' >> t
101 hg log
111 hg log
102
112
103 echo '# done'
113 echo '# done'
@@ -1,341 +1,350 b''
1 # default style is like normal output
1 # default style is like normal output
2 # normal
2 # normal
3 # verbose
3 # verbose
4 # debug
4 # debug
5 # revision with no copies (used to print a traceback)
5 # revision with no copies (used to print a traceback)
6
6
7 # compact style works
7 # compact style works
8 4[tip] 32a18f097fcc 1970-01-17 04:53 +0000 person
8 4[tip] 32a18f097fcc 1970-01-17 04:53 +0000 person
9 new branch
9 new branch
10
10
11 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
11 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
12 no user, no domain
12 no user, no domain
13
13
14 2 97054abb4ab8 1970-01-14 21:20 +0000 other
14 2 97054abb4ab8 1970-01-14 21:20 +0000 other
15 no person
15 no person
16
16
17 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
17 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
18 other 1
18 other 1
19
19
20 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
20 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
21 line 1
21 line 1
22
22
23 4[tip] 32a18f097fcc 1970-01-17 04:53 +0000 person
23 4[tip] 32a18f097fcc 1970-01-17 04:53 +0000 person
24 new branch
24 new branch
25
25
26 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
26 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
27 no user, no domain
27 no user, no domain
28
28
29 2 97054abb4ab8 1970-01-14 21:20 +0000 other
29 2 97054abb4ab8 1970-01-14 21:20 +0000 other
30 no person
30 no person
31
31
32 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
32 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
33 other 1
33 other 1
34
34
35 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
35 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
36 line 1
36 line 1
37
37
38 4[tip]:3,-1 32a18f097fcc 1970-01-17 04:53 +0000 person
38 4[tip]:3,-1 32a18f097fcc 1970-01-17 04:53 +0000 person
39 new branch
39 new branch
40
40
41 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
41 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
42 no user, no domain
42 no user, no domain
43
43
44 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other
44 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other
45 no person
45 no person
46
46
47 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
47 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
48 other 1
48 other 1
49
49
50 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
50 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
51 line 1
51 line 1
52
52
53 # error if style not readable
53 # error if style not readable
54 abort: Permission denied: ./q
54 abort: Permission denied: ./q
55 # error if no style
55 # error if no style
56 abort: No such file or directory: notexist
56 abort: No such file or directory: notexist
57 # error if style missing key
57 # error if style missing key
58 abort: ./t: no key named 'changeset'
58 abort: ./t: no key named 'changeset'
59 # error if include fails
59 # error if include fails
60 abort: template file ./q: Permission denied
60 abort: template file ./q: Permission denied
61 # include works
61 # include works
62 4
62 4
63 3
63 3
64 2
64 2
65 1
65 1
66 0
66 0
67 # ui.style works
67 # ui.style works
68 4
68 4
69 3
69 3
70 2
70 2
71 1
71 1
72 0
72 0
73 # issue338
73 # issue338
74 1970-01-17 person <person>
74 1970-01-17 person <person>
75
75
76 * new branch
76 * new branch
77 [32a18f097fcc] [tip]
77 [32a18f097fcc] [tip]
78
78
79 1970-01-16 person <person>
79 1970-01-16 person <person>
80
80
81 * c:
81 * c:
82 no user, no domain
82 no user, no domain
83 [10e46f2dcbf4]
83 [10e46f2dcbf4]
84
84
85 1970-01-14 other <other@place>
85 1970-01-14 other <other@place>
86
86
87 * c:
87 * c:
88 no person
88 no person
89 [97054abb4ab8]
89 [97054abb4ab8]
90
90
91 1970-01-13 A. N. Other <other@place>
91 1970-01-13 A. N. Other <other@place>
92
92
93 * b:
93 * b:
94 other 1 other 2
94 other 1 other 2
95
95
96 other 3
96 other 3
97 [b608e9d1a3f0]
97 [b608e9d1a3f0]
98
98
99 1970-01-12 User Name <user@hostname>
99 1970-01-12 User Name <user@hostname>
100
100
101 * a:
101 * a:
102 line 1 line 2
102 line 1 line 2
103 [1e4e1b8f71e0]
103 [1e4e1b8f71e0]
104
104
105 # keys work
105 # keys work
106 author: person
106 author: person
107 author: person
107 author: person
108 author: other@place
108 author: other@place
109 author: A. N. Other <other@place>
109 author: A. N. Other <other@place>
110 author: User Name <user@hostname>
110 author: User Name <user@hostname>
111 author--verbose: person
111 author--verbose: person
112 author--verbose: person
112 author--verbose: person
113 author--verbose: other@place
113 author--verbose: other@place
114 author--verbose: A. N. Other <other@place>
114 author--verbose: A. N. Other <other@place>
115 author--verbose: User Name <user@hostname>
115 author--verbose: User Name <user@hostname>
116 author--debug: person
116 author--debug: person
117 author--debug: person
117 author--debug: person
118 author--debug: other@place
118 author--debug: other@place
119 author--debug: A. N. Other <other@place>
119 author--debug: A. N. Other <other@place>
120 author--debug: User Name <user@hostname>
120 author--debug: User Name <user@hostname>
121 branches: foo
121 branches: foo
122 branches:
122 branches:
123 branches:
123 branches:
124 branches:
124 branches:
125 branches:
125 branches:
126 branches--verbose: foo
126 branches--verbose: foo
127 branches--verbose:
127 branches--verbose:
128 branches--verbose:
128 branches--verbose:
129 branches--verbose:
129 branches--verbose:
130 branches--verbose:
130 branches--verbose:
131 branches--debug: foo
131 branches--debug: foo
132 branches--debug:
132 branches--debug:
133 branches--debug:
133 branches--debug:
134 branches--debug:
134 branches--debug:
135 branches--debug:
135 branches--debug:
136 date: 1400000.00
136 date: 1400000.00
137 date: 1300000.00
137 date: 1300000.00
138 date: 1200000.00
138 date: 1200000.00
139 date: 1100000.00
139 date: 1100000.00
140 date: 1000000.00
140 date: 1000000.00
141 date--verbose: 1400000.00
141 date--verbose: 1400000.00
142 date--verbose: 1300000.00
142 date--verbose: 1300000.00
143 date--verbose: 1200000.00
143 date--verbose: 1200000.00
144 date--verbose: 1100000.00
144 date--verbose: 1100000.00
145 date--verbose: 1000000.00
145 date--verbose: 1000000.00
146 date--debug: 1400000.00
146 date--debug: 1400000.00
147 date--debug: 1300000.00
147 date--debug: 1300000.00
148 date--debug: 1200000.00
148 date--debug: 1200000.00
149 date--debug: 1100000.00
149 date--debug: 1100000.00
150 date--debug: 1000000.00
150 date--debug: 1000000.00
151 desc: new branch
151 desc: new branch
152 desc: no user, no domain
152 desc: no user, no domain
153 desc: no person
153 desc: no person
154 desc: other 1
154 desc: other 1
155 other 2
155 other 2
156
156
157 other 3
157 other 3
158 desc: line 1
158 desc: line 1
159 line 2
159 line 2
160 desc--verbose: new branch
160 desc--verbose: new branch
161 desc--verbose: no user, no domain
161 desc--verbose: no user, no domain
162 desc--verbose: no person
162 desc--verbose: no person
163 desc--verbose: other 1
163 desc--verbose: other 1
164 other 2
164 other 2
165
165
166 other 3
166 other 3
167 desc--verbose: line 1
167 desc--verbose: line 1
168 line 2
168 line 2
169 desc--debug: new branch
169 desc--debug: new branch
170 desc--debug: no user, no domain
170 desc--debug: no user, no domain
171 desc--debug: no person
171 desc--debug: no person
172 desc--debug: other 1
172 desc--debug: other 1
173 other 2
173 other 2
174
174
175 other 3
175 other 3
176 desc--debug: line 1
176 desc--debug: line 1
177 line 2
177 line 2
178 file_adds:
178 file_adds:
179 file_adds:
179 file_adds:
180 file_adds:
180 file_adds:
181 file_adds:
181 file_adds:
182 file_adds:
182 file_adds:
183 file_adds--verbose:
183 file_adds--verbose:
184 file_adds--verbose:
184 file_adds--verbose:
185 file_adds--verbose:
185 file_adds--verbose:
186 file_adds--verbose:
186 file_adds--verbose:
187 file_adds--verbose:
187 file_adds--verbose:
188 file_adds--debug:
188 file_adds--debug:
189 file_adds--debug:
189 file_adds--debug:
190 file_adds--debug: c
190 file_adds--debug: c
191 file_adds--debug: b
191 file_adds--debug: b
192 file_adds--debug: a
192 file_adds--debug: a
193 file_dels:
193 file_dels:
194 file_dels:
194 file_dels:
195 file_dels:
195 file_dels:
196 file_dels:
196 file_dels:
197 file_dels:
197 file_dels:
198 file_dels--verbose:
198 file_dels--verbose:
199 file_dels--verbose:
199 file_dels--verbose:
200 file_dels--verbose:
200 file_dels--verbose:
201 file_dels--verbose:
201 file_dels--verbose:
202 file_dels--verbose:
202 file_dels--verbose:
203 file_dels--debug:
203 file_dels--debug:
204 file_dels--debug:
204 file_dels--debug:
205 file_dels--debug:
205 file_dels--debug:
206 file_dels--debug:
206 file_dels--debug:
207 file_dels--debug:
207 file_dels--debug:
208 files:
208 files:
209 files: c
209 files: c
210 files: c
210 files: c
211 files: b
211 files: b
212 files: a
212 files: a
213 files--verbose:
213 files--verbose:
214 files--verbose: c
214 files--verbose: c
215 files--verbose: c
215 files--verbose: c
216 files--verbose: b
216 files--verbose: b
217 files--verbose: a
217 files--verbose: a
218 files--debug:
218 files--debug:
219 files--debug: c
219 files--debug: c
220 files--debug:
220 files--debug:
221 files--debug:
221 files--debug:
222 files--debug:
222 files--debug:
223 manifest:
223 manifest:
224 manifest:
224 manifest:
225 manifest:
225 manifest:
226 manifest:
226 manifest:
227 manifest:
227 manifest:
228 manifest--verbose:
228 manifest--verbose:
229 manifest--verbose:
229 manifest--verbose:
230 manifest--verbose:
230 manifest--verbose:
231 manifest--verbose:
231 manifest--verbose:
232 manifest--verbose:
232 manifest--verbose:
233 manifest--debug: 4:90ae8dda64e1
233 manifest--debug: 4:90ae8dda64e1a876c792bccb9af66284f6018363
234 manifest--debug: 3:cb5a1327723b
234 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
235 manifest--debug: 2:6e0e82995c35
235 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
236 manifest--debug: 1:4e8d705b1e53
236 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
237 manifest--debug: 0:a0c8bcbbb45c
237 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
238 node: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
238 node: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
239 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
239 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
240 node: 97054abb4ab824450e9164180baf491ae0078465
240 node: 97054abb4ab824450e9164180baf491ae0078465
241 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
241 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
242 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
242 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
243 node--verbose: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
243 node--verbose: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
244 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
244 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
245 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
245 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
246 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
246 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
247 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
247 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
248 node--debug: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
248 node--debug: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
249 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
249 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
250 node--debug: 97054abb4ab824450e9164180baf491ae0078465
250 node--debug: 97054abb4ab824450e9164180baf491ae0078465
251 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
251 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
252 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
252 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
253 parents:
253 parents:
254 parents:
254 parents:
255 parents:
255 parents:
256 parents:
256 parents:
257 parents:
257 parents:
258 parents--verbose:
258 parents--verbose:
259 parents--verbose:
259 parents--verbose:
260 parents--verbose:
260 parents--verbose:
261 parents--verbose:
261 parents--verbose:
262 parents--verbose:
262 parents--verbose:
263 parents--debug: 3:10e46f2dcbf4 -1:000000000000
263 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
264 parents--debug: 2:97054abb4ab8 -1:000000000000
264 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
265 parents--debug: 1:b608e9d1a3f0 -1:000000000000
265 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
266 parents--debug: 0:1e4e1b8f71e0 -1:000000000000
266 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
267 parents--debug: -1:000000000000 -1:000000000000
267 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
268 rev: 4
268 rev: 4
269 rev: 3
269 rev: 3
270 rev: 2
270 rev: 2
271 rev: 1
271 rev: 1
272 rev: 0
272 rev: 0
273 rev--verbose: 4
273 rev--verbose: 4
274 rev--verbose: 3
274 rev--verbose: 3
275 rev--verbose: 2
275 rev--verbose: 2
276 rev--verbose: 1
276 rev--verbose: 1
277 rev--verbose: 0
277 rev--verbose: 0
278 rev--debug: 4
278 rev--debug: 4
279 rev--debug: 3
279 rev--debug: 3
280 rev--debug: 2
280 rev--debug: 2
281 rev--debug: 1
281 rev--debug: 1
282 rev--debug: 0
282 rev--debug: 0
283 tags: tip
283 tags: tip
284 tags:
284 tags:
285 tags:
285 tags:
286 tags:
286 tags:
287 tags:
287 tags:
288 tags--verbose: tip
288 tags--verbose: tip
289 tags--verbose:
289 tags--verbose:
290 tags--verbose:
290 tags--verbose:
291 tags--verbose:
291 tags--verbose:
292 tags--verbose:
292 tags--verbose:
293 tags--debug: tip
293 tags--debug: tip
294 tags--debug:
294 tags--debug:
295 tags--debug:
295 tags--debug:
296 tags--debug:
296 tags--debug:
297 tags--debug:
297 tags--debug:
298 # filters work
298 # filters work
299
299
300
300
301 place
301 place
302 place
302 place
303 hostname
303 hostname
304 person
304 person
305 person
305 person
306 other
306 other
307 A. N. Other
307 A. N. Other
308 User Name
308 User Name
309 person
309 person
310 person
310 person
311 other
311 other
312 other
312 other
313 user
313 user
314 Sat Jan 17 04:53:20 1970 +0000
314 Sat Jan 17 04:53:20 1970 +0000
315 Fri Jan 16 01:06:40 1970 +0000
315 Fri Jan 16 01:06:40 1970 +0000
316 Wed Jan 14 21:20:00 1970 +0000
316 Wed Jan 14 21:20:00 1970 +0000
317 Tue Jan 13 17:33:20 1970 +0000
317 Tue Jan 13 17:33:20 1970 +0000
318 Mon Jan 12 13:46:40 1970 +0000
318 Mon Jan 12 13:46:40 1970 +0000
319 1970-01-17 04:53 +0000
319 1970-01-17 04:53 +0000
320 1970-01-16 01:06 +0000
320 1970-01-16 01:06 +0000
321 1970-01-14 21:20 +0000
321 1970-01-14 21:20 +0000
322 1970-01-13 17:33 +0000
322 1970-01-13 17:33 +0000
323 1970-01-12 13:46 +0000
323 1970-01-12 13:46 +0000
324 Sat, 17 Jan 1970 04:53:20 +0000
324 Sat, 17 Jan 1970 04:53:20 +0000
325 Fri, 16 Jan 1970 01:06:40 +0000
325 Fri, 16 Jan 1970 01:06:40 +0000
326 Wed, 14 Jan 1970 21:20:00 +0000
326 Wed, 14 Jan 1970 21:20:00 +0000
327 Tue, 13 Jan 1970 17:33:20 +0000
327 Tue, 13 Jan 1970 17:33:20 +0000
328 Mon, 12 Jan 1970 13:46:40 +0000
328 Mon, 12 Jan 1970 13:46:40 +0000
329 new branch
329 new branch
330 no user, no domain
330 no user, no domain
331 no person
331 no person
332 other 1
332 other 1
333 line 1
333 line 1
334 32a18f097fcc
334 32a18f097fcc
335 10e46f2dcbf4
335 10e46f2dcbf4
336 97054abb4ab8
336 97054abb4ab8
337 b608e9d1a3f0
337 b608e9d1a3f0
338 1e4e1b8f71e0
338 1e4e1b8f71e0
339 # formatnode filter works
340 # quiet
341 1e4e1b8f71e0
342 # normal
343 1e4e1b8f71e0
344 # verbose
345 1e4e1b8f71e0
346 # debug
347 1e4e1b8f71e05681d422154f5421e385fec3454f
339 # error on syntax
348 # error on syntax
340 abort: t:3: unmatched quotes
349 abort: t:3: unmatched quotes
341 # done
350 # done
General Comments 0
You need to be logged in to leave comments. Login now