##// END OF EJS Templates
cmdutil: make "files" list all files, add "file_mods" for modified files
Patrick Mezard -
r5550:db6633f1 default
parent child Browse files
Show More
@@ -1,949 +1,945 b''
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in mercurial
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
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 node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import os, sys, bisect, stat
10 import os, sys, bisect, stat
11 import mdiff, bdiff, util, templater, patch
11 import mdiff, bdiff, util, templater, patch
12
12
13 revrangesep = ':'
13 revrangesep = ':'
14
14
15 class UnknownCommand(Exception):
15 class UnknownCommand(Exception):
16 """Exception raised if command is not in the command table."""
16 """Exception raised if command is not in the command table."""
17 class AmbiguousCommand(Exception):
17 class AmbiguousCommand(Exception):
18 """Exception raised if command shortcut matches more than one command."""
18 """Exception raised if command shortcut matches more than one command."""
19
19
20 def findpossible(ui, cmd, table):
20 def findpossible(ui, cmd, table):
21 """
21 """
22 Return cmd -> (aliases, command table entry)
22 Return cmd -> (aliases, command table entry)
23 for each matching command.
23 for each matching command.
24 Return debug commands (or their aliases) only if no normal command matches.
24 Return debug commands (or their aliases) only if no normal command matches.
25 """
25 """
26 choice = {}
26 choice = {}
27 debugchoice = {}
27 debugchoice = {}
28 for e in table.keys():
28 for e in table.keys():
29 aliases = e.lstrip("^").split("|")
29 aliases = e.lstrip("^").split("|")
30 found = None
30 found = None
31 if cmd in aliases:
31 if cmd in aliases:
32 found = cmd
32 found = cmd
33 elif not ui.config("ui", "strict"):
33 elif not ui.config("ui", "strict"):
34 for a in aliases:
34 for a in aliases:
35 if a.startswith(cmd):
35 if a.startswith(cmd):
36 found = a
36 found = a
37 break
37 break
38 if found is not None:
38 if found is not None:
39 if aliases[0].startswith("debug") or found.startswith("debug"):
39 if aliases[0].startswith("debug") or found.startswith("debug"):
40 debugchoice[found] = (aliases, table[e])
40 debugchoice[found] = (aliases, table[e])
41 else:
41 else:
42 choice[found] = (aliases, table[e])
42 choice[found] = (aliases, table[e])
43
43
44 if not choice and debugchoice:
44 if not choice and debugchoice:
45 choice = debugchoice
45 choice = debugchoice
46
46
47 return choice
47 return choice
48
48
49 def findcmd(ui, cmd, table):
49 def findcmd(ui, cmd, table):
50 """Return (aliases, command table entry) for command string."""
50 """Return (aliases, command table entry) for command string."""
51 choice = findpossible(ui, cmd, table)
51 choice = findpossible(ui, cmd, table)
52
52
53 if choice.has_key(cmd):
53 if choice.has_key(cmd):
54 return choice[cmd]
54 return choice[cmd]
55
55
56 if len(choice) > 1:
56 if len(choice) > 1:
57 clist = choice.keys()
57 clist = choice.keys()
58 clist.sort()
58 clist.sort()
59 raise AmbiguousCommand(cmd, clist)
59 raise AmbiguousCommand(cmd, clist)
60
60
61 if choice:
61 if choice:
62 return choice.values()[0]
62 return choice.values()[0]
63
63
64 raise UnknownCommand(cmd)
64 raise UnknownCommand(cmd)
65
65
66 def bail_if_changed(repo):
66 def bail_if_changed(repo):
67 modified, added, removed, deleted = repo.status()[:4]
67 modified, added, removed, deleted = repo.status()[:4]
68 if modified or added or removed or deleted:
68 if modified or added or removed or deleted:
69 raise util.Abort(_("outstanding uncommitted changes"))
69 raise util.Abort(_("outstanding uncommitted changes"))
70
70
71 def logmessage(opts):
71 def logmessage(opts):
72 """ get the log message according to -m and -l option """
72 """ get the log message according to -m and -l option """
73 message = opts['message']
73 message = opts['message']
74 logfile = opts['logfile']
74 logfile = opts['logfile']
75
75
76 if message and logfile:
76 if message and logfile:
77 raise util.Abort(_('options --message and --logfile are mutually '
77 raise util.Abort(_('options --message and --logfile are mutually '
78 'exclusive'))
78 'exclusive'))
79 if not message and logfile:
79 if not message and logfile:
80 try:
80 try:
81 if logfile == '-':
81 if logfile == '-':
82 message = sys.stdin.read()
82 message = sys.stdin.read()
83 else:
83 else:
84 message = open(logfile).read()
84 message = open(logfile).read()
85 except IOError, inst:
85 except IOError, inst:
86 raise util.Abort(_("can't read commit message '%s': %s") %
86 raise util.Abort(_("can't read commit message '%s': %s") %
87 (logfile, inst.strerror))
87 (logfile, inst.strerror))
88 return message
88 return message
89
89
90 def setremoteconfig(ui, opts):
90 def setremoteconfig(ui, opts):
91 "copy remote options to ui tree"
91 "copy remote options to ui tree"
92 if opts.get('ssh'):
92 if opts.get('ssh'):
93 ui.setconfig("ui", "ssh", opts['ssh'])
93 ui.setconfig("ui", "ssh", opts['ssh'])
94 if opts.get('remotecmd'):
94 if opts.get('remotecmd'):
95 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
95 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
96
96
97 def revpair(repo, revs):
97 def revpair(repo, revs):
98 '''return pair of nodes, given list of revisions. second item can
98 '''return pair of nodes, given list of revisions. second item can
99 be None, meaning use working dir.'''
99 be None, meaning use working dir.'''
100
100
101 def revfix(repo, val, defval):
101 def revfix(repo, val, defval):
102 if not val and val != 0 and defval is not None:
102 if not val and val != 0 and defval is not None:
103 val = defval
103 val = defval
104 return repo.lookup(val)
104 return repo.lookup(val)
105
105
106 if not revs:
106 if not revs:
107 return repo.dirstate.parents()[0], None
107 return repo.dirstate.parents()[0], None
108 end = None
108 end = None
109 if len(revs) == 1:
109 if len(revs) == 1:
110 if revrangesep in revs[0]:
110 if revrangesep in revs[0]:
111 start, end = revs[0].split(revrangesep, 1)
111 start, end = revs[0].split(revrangesep, 1)
112 start = revfix(repo, start, 0)
112 start = revfix(repo, start, 0)
113 end = revfix(repo, end, repo.changelog.count() - 1)
113 end = revfix(repo, end, repo.changelog.count() - 1)
114 else:
114 else:
115 start = revfix(repo, revs[0], None)
115 start = revfix(repo, revs[0], None)
116 elif len(revs) == 2:
116 elif len(revs) == 2:
117 if revrangesep in revs[0] or revrangesep in revs[1]:
117 if revrangesep in revs[0] or revrangesep in revs[1]:
118 raise util.Abort(_('too many revisions specified'))
118 raise util.Abort(_('too many revisions specified'))
119 start = revfix(repo, revs[0], None)
119 start = revfix(repo, revs[0], None)
120 end = revfix(repo, revs[1], None)
120 end = revfix(repo, revs[1], None)
121 else:
121 else:
122 raise util.Abort(_('too many revisions specified'))
122 raise util.Abort(_('too many revisions specified'))
123 return start, end
123 return start, end
124
124
125 def revrange(repo, revs):
125 def revrange(repo, revs):
126 """Yield revision as strings from a list of revision specifications."""
126 """Yield revision as strings from a list of revision specifications."""
127
127
128 def revfix(repo, val, defval):
128 def revfix(repo, val, defval):
129 if not val and val != 0 and defval is not None:
129 if not val and val != 0 and defval is not None:
130 return defval
130 return defval
131 return repo.changelog.rev(repo.lookup(val))
131 return repo.changelog.rev(repo.lookup(val))
132
132
133 seen, l = {}, []
133 seen, l = {}, []
134 for spec in revs:
134 for spec in revs:
135 if revrangesep in spec:
135 if revrangesep in spec:
136 start, end = spec.split(revrangesep, 1)
136 start, end = spec.split(revrangesep, 1)
137 start = revfix(repo, start, 0)
137 start = revfix(repo, start, 0)
138 end = revfix(repo, end, repo.changelog.count() - 1)
138 end = revfix(repo, end, repo.changelog.count() - 1)
139 step = start > end and -1 or 1
139 step = start > end and -1 or 1
140 for rev in xrange(start, end+step, step):
140 for rev in xrange(start, end+step, step):
141 if rev in seen:
141 if rev in seen:
142 continue
142 continue
143 seen[rev] = 1
143 seen[rev] = 1
144 l.append(rev)
144 l.append(rev)
145 else:
145 else:
146 rev = revfix(repo, spec, None)
146 rev = revfix(repo, spec, None)
147 if rev in seen:
147 if rev in seen:
148 continue
148 continue
149 seen[rev] = 1
149 seen[rev] = 1
150 l.append(rev)
150 l.append(rev)
151
151
152 return l
152 return l
153
153
154 def make_filename(repo, pat, node,
154 def make_filename(repo, pat, node,
155 total=None, seqno=None, revwidth=None, pathname=None):
155 total=None, seqno=None, revwidth=None, pathname=None):
156 node_expander = {
156 node_expander = {
157 'H': lambda: hex(node),
157 'H': lambda: hex(node),
158 'R': lambda: str(repo.changelog.rev(node)),
158 'R': lambda: str(repo.changelog.rev(node)),
159 'h': lambda: short(node),
159 'h': lambda: short(node),
160 }
160 }
161 expander = {
161 expander = {
162 '%': lambda: '%',
162 '%': lambda: '%',
163 'b': lambda: os.path.basename(repo.root),
163 'b': lambda: os.path.basename(repo.root),
164 }
164 }
165
165
166 try:
166 try:
167 if node:
167 if node:
168 expander.update(node_expander)
168 expander.update(node_expander)
169 if node:
169 if node:
170 expander['r'] = (lambda:
170 expander['r'] = (lambda:
171 str(repo.changelog.rev(node)).zfill(revwidth or 0))
171 str(repo.changelog.rev(node)).zfill(revwidth or 0))
172 if total is not None:
172 if total is not None:
173 expander['N'] = lambda: str(total)
173 expander['N'] = lambda: str(total)
174 if seqno is not None:
174 if seqno is not None:
175 expander['n'] = lambda: str(seqno)
175 expander['n'] = lambda: str(seqno)
176 if total is not None and seqno is not None:
176 if total is not None and seqno is not None:
177 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
177 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
178 if pathname is not None:
178 if pathname is not None:
179 expander['s'] = lambda: os.path.basename(pathname)
179 expander['s'] = lambda: os.path.basename(pathname)
180 expander['d'] = lambda: os.path.dirname(pathname) or '.'
180 expander['d'] = lambda: os.path.dirname(pathname) or '.'
181 expander['p'] = lambda: pathname
181 expander['p'] = lambda: pathname
182
182
183 newname = []
183 newname = []
184 patlen = len(pat)
184 patlen = len(pat)
185 i = 0
185 i = 0
186 while i < patlen:
186 while i < patlen:
187 c = pat[i]
187 c = pat[i]
188 if c == '%':
188 if c == '%':
189 i += 1
189 i += 1
190 c = pat[i]
190 c = pat[i]
191 c = expander[c]()
191 c = expander[c]()
192 newname.append(c)
192 newname.append(c)
193 i += 1
193 i += 1
194 return ''.join(newname)
194 return ''.join(newname)
195 except KeyError, inst:
195 except KeyError, inst:
196 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
196 raise util.Abort(_("invalid format spec '%%%s' in output file name") %
197 inst.args[0])
197 inst.args[0])
198
198
199 def make_file(repo, pat, node=None,
199 def make_file(repo, pat, node=None,
200 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
200 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
201 if not pat or pat == '-':
201 if not pat or pat == '-':
202 return 'w' in mode and sys.stdout or sys.stdin
202 return 'w' in mode and sys.stdout or sys.stdin
203 if hasattr(pat, 'write') and 'w' in mode:
203 if hasattr(pat, 'write') and 'w' in mode:
204 return pat
204 return pat
205 if hasattr(pat, 'read') and 'r' in mode:
205 if hasattr(pat, 'read') and 'r' in mode:
206 return pat
206 return pat
207 return open(make_filename(repo, pat, node, total, seqno, revwidth,
207 return open(make_filename(repo, pat, node, total, seqno, revwidth,
208 pathname),
208 pathname),
209 mode)
209 mode)
210
210
211 def matchpats(repo, pats=[], opts={}, globbed=False, default=None):
211 def matchpats(repo, pats=[], opts={}, globbed=False, default=None):
212 cwd = repo.getcwd()
212 cwd = repo.getcwd()
213 return util.cmdmatcher(repo.root, cwd, pats or [], opts.get('include'),
213 return util.cmdmatcher(repo.root, cwd, pats or [], opts.get('include'),
214 opts.get('exclude'), globbed=globbed,
214 opts.get('exclude'), globbed=globbed,
215 default=default)
215 default=default)
216
216
217 def walk(repo, pats=[], opts={}, node=None, badmatch=None, globbed=False,
217 def walk(repo, pats=[], opts={}, node=None, badmatch=None, globbed=False,
218 default=None):
218 default=None):
219 files, matchfn, anypats = matchpats(repo, pats, opts, globbed=globbed,
219 files, matchfn, anypats = matchpats(repo, pats, opts, globbed=globbed,
220 default=default)
220 default=default)
221 exact = dict.fromkeys(files)
221 exact = dict.fromkeys(files)
222 cwd = repo.getcwd()
222 cwd = repo.getcwd()
223 for src, fn in repo.walk(node=node, files=files, match=matchfn,
223 for src, fn in repo.walk(node=node, files=files, match=matchfn,
224 badmatch=badmatch):
224 badmatch=badmatch):
225 yield src, fn, repo.pathto(fn, cwd), fn in exact
225 yield src, fn, repo.pathto(fn, cwd), fn in exact
226
226
227 def findrenames(repo, added=None, removed=None, threshold=0.5):
227 def findrenames(repo, added=None, removed=None, threshold=0.5):
228 '''find renamed files -- yields (before, after, score) tuples'''
228 '''find renamed files -- yields (before, after, score) tuples'''
229 if added is None or removed is None:
229 if added is None or removed is None:
230 added, removed = repo.status()[1:3]
230 added, removed = repo.status()[1:3]
231 ctx = repo.changectx()
231 ctx = repo.changectx()
232 for a in added:
232 for a in added:
233 aa = repo.wread(a)
233 aa = repo.wread(a)
234 bestname, bestscore = None, threshold
234 bestname, bestscore = None, threshold
235 for r in removed:
235 for r in removed:
236 rr = ctx.filectx(r).data()
236 rr = ctx.filectx(r).data()
237
237
238 # bdiff.blocks() returns blocks of matching lines
238 # bdiff.blocks() returns blocks of matching lines
239 # count the number of bytes in each
239 # count the number of bytes in each
240 equal = 0
240 equal = 0
241 alines = mdiff.splitnewlines(aa)
241 alines = mdiff.splitnewlines(aa)
242 matches = bdiff.blocks(aa, rr)
242 matches = bdiff.blocks(aa, rr)
243 for x1,x2,y1,y2 in matches:
243 for x1,x2,y1,y2 in matches:
244 for line in alines[x1:x2]:
244 for line in alines[x1:x2]:
245 equal += len(line)
245 equal += len(line)
246
246
247 lengths = len(aa) + len(rr)
247 lengths = len(aa) + len(rr)
248 if lengths:
248 if lengths:
249 myscore = equal*2.0 / lengths
249 myscore = equal*2.0 / lengths
250 if myscore >= bestscore:
250 if myscore >= bestscore:
251 bestname, bestscore = r, myscore
251 bestname, bestscore = r, myscore
252 if bestname:
252 if bestname:
253 yield bestname, a, bestscore
253 yield bestname, a, bestscore
254
254
255 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
255 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
256 if dry_run is None:
256 if dry_run is None:
257 dry_run = opts.get('dry_run')
257 dry_run = opts.get('dry_run')
258 if similarity is None:
258 if similarity is None:
259 similarity = float(opts.get('similarity') or 0)
259 similarity = float(opts.get('similarity') or 0)
260 add, remove = [], []
260 add, remove = [], []
261 mapping = {}
261 mapping = {}
262 for src, abs, rel, exact in walk(repo, pats, opts):
262 for src, abs, rel, exact in walk(repo, pats, opts):
263 target = repo.wjoin(abs)
263 target = repo.wjoin(abs)
264 if src == 'f' and abs not in repo.dirstate:
264 if src == 'f' and abs not in repo.dirstate:
265 add.append(abs)
265 add.append(abs)
266 mapping[abs] = rel, exact
266 mapping[abs] = rel, exact
267 if repo.ui.verbose or not exact:
267 if repo.ui.verbose or not exact:
268 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
268 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
269 if repo.dirstate[abs] != 'r' and (not util.lexists(target)
269 if repo.dirstate[abs] != 'r' and (not util.lexists(target)
270 or (os.path.isdir(target) and not os.path.islink(target))):
270 or (os.path.isdir(target) and not os.path.islink(target))):
271 remove.append(abs)
271 remove.append(abs)
272 mapping[abs] = rel, exact
272 mapping[abs] = rel, exact
273 if repo.ui.verbose or not exact:
273 if repo.ui.verbose or not exact:
274 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
274 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
275 if not dry_run:
275 if not dry_run:
276 repo.remove(remove)
276 repo.remove(remove)
277 repo.add(add)
277 repo.add(add)
278 if similarity > 0:
278 if similarity > 0:
279 for old, new, score in findrenames(repo, add, remove, similarity):
279 for old, new, score in findrenames(repo, add, remove, similarity):
280 oldrel, oldexact = mapping[old]
280 oldrel, oldexact = mapping[old]
281 newrel, newexact = mapping[new]
281 newrel, newexact = mapping[new]
282 if repo.ui.verbose or not oldexact or not newexact:
282 if repo.ui.verbose or not oldexact or not newexact:
283 repo.ui.status(_('recording removal of %s as rename to %s '
283 repo.ui.status(_('recording removal of %s as rename to %s '
284 '(%d%% similar)\n') %
284 '(%d%% similar)\n') %
285 (oldrel, newrel, score * 100))
285 (oldrel, newrel, score * 100))
286 if not dry_run:
286 if not dry_run:
287 repo.copy(old, new)
287 repo.copy(old, new)
288
288
289 def service(opts, parentfn=None, initfn=None, runfn=None):
289 def service(opts, parentfn=None, initfn=None, runfn=None):
290 '''Run a command as a service.'''
290 '''Run a command as a service.'''
291
291
292 if opts['daemon'] and not opts['daemon_pipefds']:
292 if opts['daemon'] and not opts['daemon_pipefds']:
293 rfd, wfd = os.pipe()
293 rfd, wfd = os.pipe()
294 args = sys.argv[:]
294 args = sys.argv[:]
295 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
295 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
296 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
296 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
297 args[0], args)
297 args[0], args)
298 os.close(wfd)
298 os.close(wfd)
299 os.read(rfd, 1)
299 os.read(rfd, 1)
300 if parentfn:
300 if parentfn:
301 return parentfn(pid)
301 return parentfn(pid)
302 else:
302 else:
303 os._exit(0)
303 os._exit(0)
304
304
305 if initfn:
305 if initfn:
306 initfn()
306 initfn()
307
307
308 if opts['pid_file']:
308 if opts['pid_file']:
309 fp = open(opts['pid_file'], 'w')
309 fp = open(opts['pid_file'], 'w')
310 fp.write(str(os.getpid()) + '\n')
310 fp.write(str(os.getpid()) + '\n')
311 fp.close()
311 fp.close()
312
312
313 if opts['daemon_pipefds']:
313 if opts['daemon_pipefds']:
314 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
314 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
315 os.close(rfd)
315 os.close(rfd)
316 try:
316 try:
317 os.setsid()
317 os.setsid()
318 except AttributeError:
318 except AttributeError:
319 pass
319 pass
320 os.write(wfd, 'y')
320 os.write(wfd, 'y')
321 os.close(wfd)
321 os.close(wfd)
322 sys.stdout.flush()
322 sys.stdout.flush()
323 sys.stderr.flush()
323 sys.stderr.flush()
324 fd = os.open(util.nulldev, os.O_RDWR)
324 fd = os.open(util.nulldev, os.O_RDWR)
325 if fd != 0: os.dup2(fd, 0)
325 if fd != 0: os.dup2(fd, 0)
326 if fd != 1: os.dup2(fd, 1)
326 if fd != 1: os.dup2(fd, 1)
327 if fd != 2: os.dup2(fd, 2)
327 if fd != 2: os.dup2(fd, 2)
328 if fd not in (0, 1, 2): os.close(fd)
328 if fd not in (0, 1, 2): os.close(fd)
329
329
330 if runfn:
330 if runfn:
331 return runfn()
331 return runfn()
332
332
333 class changeset_printer(object):
333 class changeset_printer(object):
334 '''show changeset information when templating not requested.'''
334 '''show changeset information when templating not requested.'''
335
335
336 def __init__(self, ui, repo, patch, buffered):
336 def __init__(self, ui, repo, patch, buffered):
337 self.ui = ui
337 self.ui = ui
338 self.repo = repo
338 self.repo = repo
339 self.buffered = buffered
339 self.buffered = buffered
340 self.patch = patch
340 self.patch = patch
341 self.header = {}
341 self.header = {}
342 self.hunk = {}
342 self.hunk = {}
343 self.lastheader = None
343 self.lastheader = None
344
344
345 def flush(self, rev):
345 def flush(self, rev):
346 if rev in self.header:
346 if rev in self.header:
347 h = self.header[rev]
347 h = self.header[rev]
348 if h != self.lastheader:
348 if h != self.lastheader:
349 self.lastheader = h
349 self.lastheader = h
350 self.ui.write(h)
350 self.ui.write(h)
351 del self.header[rev]
351 del self.header[rev]
352 if rev in self.hunk:
352 if rev in self.hunk:
353 self.ui.write(self.hunk[rev])
353 self.ui.write(self.hunk[rev])
354 del self.hunk[rev]
354 del self.hunk[rev]
355 return 1
355 return 1
356 return 0
356 return 0
357
357
358 def show(self, rev=0, changenode=None, copies=(), **props):
358 def show(self, rev=0, changenode=None, copies=(), **props):
359 if self.buffered:
359 if self.buffered:
360 self.ui.pushbuffer()
360 self.ui.pushbuffer()
361 self._show(rev, changenode, copies, props)
361 self._show(rev, changenode, copies, props)
362 self.hunk[rev] = self.ui.popbuffer()
362 self.hunk[rev] = self.ui.popbuffer()
363 else:
363 else:
364 self._show(rev, changenode, copies, props)
364 self._show(rev, changenode, copies, props)
365
365
366 def _show(self, rev, changenode, copies, props):
366 def _show(self, rev, changenode, copies, props):
367 '''show a single changeset or file revision'''
367 '''show a single changeset or file revision'''
368 log = self.repo.changelog
368 log = self.repo.changelog
369 if changenode is None:
369 if changenode is None:
370 changenode = log.node(rev)
370 changenode = log.node(rev)
371 elif not rev:
371 elif not rev:
372 rev = log.rev(changenode)
372 rev = log.rev(changenode)
373
373
374 if self.ui.quiet:
374 if self.ui.quiet:
375 self.ui.write("%d:%s\n" % (rev, short(changenode)))
375 self.ui.write("%d:%s\n" % (rev, short(changenode)))
376 return
376 return
377
377
378 changes = log.read(changenode)
378 changes = log.read(changenode)
379 date = util.datestr(changes[2])
379 date = util.datestr(changes[2])
380 extra = changes[5]
380 extra = changes[5]
381 branch = extra.get("branch")
381 branch = extra.get("branch")
382
382
383 hexfunc = self.ui.debugflag and hex or short
383 hexfunc = self.ui.debugflag and hex or short
384
384
385 parents = [(p, hexfunc(log.node(p)))
385 parents = [(p, hexfunc(log.node(p)))
386 for p in self._meaningful_parentrevs(log, rev)]
386 for p in self._meaningful_parentrevs(log, rev)]
387
387
388 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
388 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
389
389
390 # don't show the default branch name
390 # don't show the default branch name
391 if branch != 'default':
391 if branch != 'default':
392 branch = util.tolocal(branch)
392 branch = util.tolocal(branch)
393 self.ui.write(_("branch: %s\n") % branch)
393 self.ui.write(_("branch: %s\n") % branch)
394 for tag in self.repo.nodetags(changenode):
394 for tag in self.repo.nodetags(changenode):
395 self.ui.write(_("tag: %s\n") % tag)
395 self.ui.write(_("tag: %s\n") % tag)
396 for parent in parents:
396 for parent in parents:
397 self.ui.write(_("parent: %d:%s\n") % parent)
397 self.ui.write(_("parent: %d:%s\n") % parent)
398
398
399 if self.ui.debugflag:
399 if self.ui.debugflag:
400 self.ui.write(_("manifest: %d:%s\n") %
400 self.ui.write(_("manifest: %d:%s\n") %
401 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
401 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
402 self.ui.write(_("user: %s\n") % changes[1])
402 self.ui.write(_("user: %s\n") % changes[1])
403 self.ui.write(_("date: %s\n") % date)
403 self.ui.write(_("date: %s\n") % date)
404
404
405 if self.ui.debugflag:
405 if self.ui.debugflag:
406 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
406 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
407 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
407 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
408 files):
408 files):
409 if value:
409 if value:
410 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
410 self.ui.write("%-12s %s\n" % (key, " ".join(value)))
411 elif changes[3] and self.ui.verbose:
411 elif changes[3] and self.ui.verbose:
412 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
412 self.ui.write(_("files: %s\n") % " ".join(changes[3]))
413 if copies and self.ui.verbose:
413 if copies and self.ui.verbose:
414 copies = ['%s (%s)' % c for c in copies]
414 copies = ['%s (%s)' % c for c in copies]
415 self.ui.write(_("copies: %s\n") % ' '.join(copies))
415 self.ui.write(_("copies: %s\n") % ' '.join(copies))
416
416
417 if extra and self.ui.debugflag:
417 if extra and self.ui.debugflag:
418 extraitems = extra.items()
418 extraitems = extra.items()
419 extraitems.sort()
419 extraitems.sort()
420 for key, value in extraitems:
420 for key, value in extraitems:
421 self.ui.write(_("extra: %s=%s\n")
421 self.ui.write(_("extra: %s=%s\n")
422 % (key, value.encode('string_escape')))
422 % (key, value.encode('string_escape')))
423
423
424 description = changes[4].strip()
424 description = changes[4].strip()
425 if description:
425 if description:
426 if self.ui.verbose:
426 if self.ui.verbose:
427 self.ui.write(_("description:\n"))
427 self.ui.write(_("description:\n"))
428 self.ui.write(description)
428 self.ui.write(description)
429 self.ui.write("\n\n")
429 self.ui.write("\n\n")
430 else:
430 else:
431 self.ui.write(_("summary: %s\n") %
431 self.ui.write(_("summary: %s\n") %
432 description.splitlines()[0])
432 description.splitlines()[0])
433 self.ui.write("\n")
433 self.ui.write("\n")
434
434
435 self.showpatch(changenode)
435 self.showpatch(changenode)
436
436
437 def showpatch(self, node):
437 def showpatch(self, node):
438 if self.patch:
438 if self.patch:
439 prev = self.repo.changelog.parents(node)[0]
439 prev = self.repo.changelog.parents(node)[0]
440 patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui,
440 patch.diff(self.repo, prev, node, match=self.patch, fp=self.ui,
441 opts=patch.diffopts(self.ui))
441 opts=patch.diffopts(self.ui))
442 self.ui.write("\n")
442 self.ui.write("\n")
443
443
444 def _meaningful_parentrevs(self, log, rev):
444 def _meaningful_parentrevs(self, log, rev):
445 """Return list of meaningful (or all if debug) parentrevs for rev.
445 """Return list of meaningful (or all if debug) parentrevs for rev.
446
446
447 For merges (two non-nullrev revisions) both parents are meaningful.
447 For merges (two non-nullrev revisions) both parents are meaningful.
448 Otherwise the first parent revision is considered meaningful if it
448 Otherwise the first parent revision is considered meaningful if it
449 is not the preceding revision.
449 is not the preceding revision.
450 """
450 """
451 parents = log.parentrevs(rev)
451 parents = log.parentrevs(rev)
452 if not self.ui.debugflag and parents[1] == nullrev:
452 if not self.ui.debugflag and parents[1] == nullrev:
453 if parents[0] >= rev - 1:
453 if parents[0] >= rev - 1:
454 parents = []
454 parents = []
455 else:
455 else:
456 parents = [parents[0]]
456 parents = [parents[0]]
457 return parents
457 return parents
458
458
459
459
460 class changeset_templater(changeset_printer):
460 class changeset_templater(changeset_printer):
461 '''format changeset information.'''
461 '''format changeset information.'''
462
462
463 def __init__(self, ui, repo, patch, mapfile, buffered):
463 def __init__(self, ui, repo, patch, mapfile, buffered):
464 changeset_printer.__init__(self, ui, repo, patch, buffered)
464 changeset_printer.__init__(self, ui, repo, patch, buffered)
465 filters = templater.common_filters.copy()
465 filters = templater.common_filters.copy()
466 filters['formatnode'] = (ui.debugflag and (lambda x: x)
466 filters['formatnode'] = (ui.debugflag and (lambda x: x)
467 or (lambda x: x[:12]))
467 or (lambda x: x[:12]))
468 self.t = templater.templater(mapfile, filters,
468 self.t = templater.templater(mapfile, filters,
469 cache={
469 cache={
470 'parent': '{rev}:{node|formatnode} ',
470 'parent': '{rev}:{node|formatnode} ',
471 'manifest': '{rev}:{node|formatnode}',
471 'manifest': '{rev}:{node|formatnode}',
472 'filecopy': '{name} ({source})'})
472 'filecopy': '{name} ({source})'})
473
473
474 def use_template(self, t):
474 def use_template(self, t):
475 '''set template string to use'''
475 '''set template string to use'''
476 self.t.cache['changeset'] = t
476 self.t.cache['changeset'] = t
477
477
478 def _show(self, rev, changenode, copies, props):
478 def _show(self, rev, changenode, copies, props):
479 '''show a single changeset or file revision'''
479 '''show a single changeset or file revision'''
480 log = self.repo.changelog
480 log = self.repo.changelog
481 if changenode is None:
481 if changenode is None:
482 changenode = log.node(rev)
482 changenode = log.node(rev)
483 elif not rev:
483 elif not rev:
484 rev = log.rev(changenode)
484 rev = log.rev(changenode)
485
485
486 changes = log.read(changenode)
486 changes = log.read(changenode)
487
487
488 def showlist(name, values, plural=None, **args):
488 def showlist(name, values, plural=None, **args):
489 '''expand set of values.
489 '''expand set of values.
490 name is name of key in template map.
490 name is name of key in template map.
491 values is list of strings or dicts.
491 values is list of strings or dicts.
492 plural is plural of name, if not simply name + 's'.
492 plural is plural of name, if not simply name + 's'.
493
493
494 expansion works like this, given name 'foo'.
494 expansion works like this, given name 'foo'.
495
495
496 if values is empty, expand 'no_foos'.
496 if values is empty, expand 'no_foos'.
497
497
498 if 'foo' not in template map, return values as a string,
498 if 'foo' not in template map, return values as a string,
499 joined by space.
499 joined by space.
500
500
501 expand 'start_foos'.
501 expand 'start_foos'.
502
502
503 for each value, expand 'foo'. if 'last_foo' in template
503 for each value, expand 'foo'. if 'last_foo' in template
504 map, expand it instead of 'foo' for last key.
504 map, expand it instead of 'foo' for last key.
505
505
506 expand 'end_foos'.
506 expand 'end_foos'.
507 '''
507 '''
508 if plural: names = plural
508 if plural: names = plural
509 else: names = name + 's'
509 else: names = name + 's'
510 if not values:
510 if not values:
511 noname = 'no_' + names
511 noname = 'no_' + names
512 if noname in self.t:
512 if noname in self.t:
513 yield self.t(noname, **args)
513 yield self.t(noname, **args)
514 return
514 return
515 if name not in self.t:
515 if name not in self.t:
516 if isinstance(values[0], str):
516 if isinstance(values[0], str):
517 yield ' '.join(values)
517 yield ' '.join(values)
518 else:
518 else:
519 for v in values:
519 for v in values:
520 yield dict(v, **args)
520 yield dict(v, **args)
521 return
521 return
522 startname = 'start_' + names
522 startname = 'start_' + names
523 if startname in self.t:
523 if startname in self.t:
524 yield self.t(startname, **args)
524 yield self.t(startname, **args)
525 vargs = args.copy()
525 vargs = args.copy()
526 def one(v, tag=name):
526 def one(v, tag=name):
527 try:
527 try:
528 vargs.update(v)
528 vargs.update(v)
529 except (AttributeError, ValueError):
529 except (AttributeError, ValueError):
530 try:
530 try:
531 for a, b in v:
531 for a, b in v:
532 vargs[a] = b
532 vargs[a] = b
533 except ValueError:
533 except ValueError:
534 vargs[name] = v
534 vargs[name] = v
535 return self.t(tag, **vargs)
535 return self.t(tag, **vargs)
536 lastname = 'last_' + name
536 lastname = 'last_' + name
537 if lastname in self.t:
537 if lastname in self.t:
538 last = values.pop()
538 last = values.pop()
539 else:
539 else:
540 last = None
540 last = None
541 for v in values:
541 for v in values:
542 yield one(v)
542 yield one(v)
543 if last is not None:
543 if last is not None:
544 yield one(last, tag=lastname)
544 yield one(last, tag=lastname)
545 endname = 'end_' + names
545 endname = 'end_' + names
546 if endname in self.t:
546 if endname in self.t:
547 yield self.t(endname, **args)
547 yield self.t(endname, **args)
548
548
549 def showbranches(**args):
549 def showbranches(**args):
550 branch = changes[5].get("branch")
550 branch = changes[5].get("branch")
551 if branch != 'default':
551 if branch != 'default':
552 branch = util.tolocal(branch)
552 branch = util.tolocal(branch)
553 return showlist('branch', [branch], plural='branches', **args)
553 return showlist('branch', [branch], plural='branches', **args)
554
554
555 def showparents(**args):
555 def showparents(**args):
556 parents = [[('rev', p), ('node', hex(log.node(p)))]
556 parents = [[('rev', p), ('node', hex(log.node(p)))]
557 for p in self._meaningful_parentrevs(log, rev)]
557 for p in self._meaningful_parentrevs(log, rev)]
558 return showlist('parent', parents, **args)
558 return showlist('parent', parents, **args)
559
559
560 def showtags(**args):
560 def showtags(**args):
561 return showlist('tag', self.repo.nodetags(changenode), **args)
561 return showlist('tag', self.repo.nodetags(changenode), **args)
562
562
563 def showextras(**args):
563 def showextras(**args):
564 extras = changes[5].items()
564 extras = changes[5].items()
565 extras.sort()
565 extras.sort()
566 for key, value in extras:
566 for key, value in extras:
567 args = args.copy()
567 args = args.copy()
568 args.update(dict(key=key, value=value))
568 args.update(dict(key=key, value=value))
569 yield self.t('extra', **args)
569 yield self.t('extra', **args)
570
570
571 def showcopies(**args):
571 def showcopies(**args):
572 c = [{'name': x[0], 'source': x[1]} for x in copies]
572 c = [{'name': x[0], 'source': x[1]} for x in copies]
573 return showlist('file_copy', c, plural='file_copies', **args)
573 return showlist('file_copy', c, plural='file_copies', **args)
574
574
575 files = []
575 files = []
576 def getfiles():
576 def getfiles():
577 if not files:
577 if not files:
578 files[:] = self.repo.status(
578 files[:] = self.repo.status(
579 log.parents(changenode)[0], changenode)[:3]
579 log.parents(changenode)[0], changenode)[:3]
580 return files
580 return files
581 # XXX: "files" means "modified files" in debug, "all changed
581 def showfiles(**args):
582 # files" otherwise. This should be fixed and a "file_mods" be
582 return showlist('file', changes[3], **args)
583 # introduced instead.
583 def showmods(**args):
584 if self.ui.debugflag:
584 return showlist('file_mod', getfiles()[0], **args)
585 def showfiles(**args):
586 return showlist('file', getfiles()[0], **args)
587 else:
588 def showfiles(**args):
589 return showlist('file', changes[3], **args)
590 def showadds(**args):
585 def showadds(**args):
591 return showlist('file_add', getfiles()[1], **args)
586 return showlist('file_add', getfiles()[1], **args)
592 def showdels(**args):
587 def showdels(**args):
593 return showlist('file_del', getfiles()[2], **args)
588 return showlist('file_del', getfiles()[2], **args)
594 def showmanifest(**args):
589 def showmanifest(**args):
595 args = args.copy()
590 args = args.copy()
596 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
591 args.update(dict(rev=self.repo.manifest.rev(changes[0]),
597 node=hex(changes[0])))
592 node=hex(changes[0])))
598 return self.t('manifest', **args)
593 return self.t('manifest', **args)
599
594
600 defprops = {
595 defprops = {
601 'author': changes[1],
596 'author': changes[1],
602 'branches': showbranches,
597 'branches': showbranches,
603 'date': changes[2],
598 'date': changes[2],
604 'desc': changes[4].strip(),
599 'desc': changes[4].strip(),
605 'file_adds': showadds,
600 'file_adds': showadds,
606 'file_dels': showdels,
601 'file_dels': showdels,
602 'file_mods': showmods,
607 'files': showfiles,
603 'files': showfiles,
608 'file_copies': showcopies,
604 'file_copies': showcopies,
609 'manifest': showmanifest,
605 'manifest': showmanifest,
610 'node': hex(changenode),
606 'node': hex(changenode),
611 'parents': showparents,
607 'parents': showparents,
612 'rev': rev,
608 'rev': rev,
613 'tags': showtags,
609 'tags': showtags,
614 'extras': showextras,
610 'extras': showextras,
615 }
611 }
616 props = props.copy()
612 props = props.copy()
617 props.update(defprops)
613 props.update(defprops)
618
614
619 try:
615 try:
620 if self.ui.debugflag and 'header_debug' in self.t:
616 if self.ui.debugflag and 'header_debug' in self.t:
621 key = 'header_debug'
617 key = 'header_debug'
622 elif self.ui.quiet and 'header_quiet' in self.t:
618 elif self.ui.quiet and 'header_quiet' in self.t:
623 key = 'header_quiet'
619 key = 'header_quiet'
624 elif self.ui.verbose and 'header_verbose' in self.t:
620 elif self.ui.verbose and 'header_verbose' in self.t:
625 key = 'header_verbose'
621 key = 'header_verbose'
626 elif 'header' in self.t:
622 elif 'header' in self.t:
627 key = 'header'
623 key = 'header'
628 else:
624 else:
629 key = ''
625 key = ''
630 if key:
626 if key:
631 h = templater.stringify(self.t(key, **props))
627 h = templater.stringify(self.t(key, **props))
632 if self.buffered:
628 if self.buffered:
633 self.header[rev] = h
629 self.header[rev] = h
634 else:
630 else:
635 self.ui.write(h)
631 self.ui.write(h)
636 if self.ui.debugflag and 'changeset_debug' in self.t:
632 if self.ui.debugflag and 'changeset_debug' in self.t:
637 key = 'changeset_debug'
633 key = 'changeset_debug'
638 elif self.ui.quiet and 'changeset_quiet' in self.t:
634 elif self.ui.quiet and 'changeset_quiet' in self.t:
639 key = 'changeset_quiet'
635 key = 'changeset_quiet'
640 elif self.ui.verbose and 'changeset_verbose' in self.t:
636 elif self.ui.verbose and 'changeset_verbose' in self.t:
641 key = 'changeset_verbose'
637 key = 'changeset_verbose'
642 else:
638 else:
643 key = 'changeset'
639 key = 'changeset'
644 self.ui.write(templater.stringify(self.t(key, **props)))
640 self.ui.write(templater.stringify(self.t(key, **props)))
645 self.showpatch(changenode)
641 self.showpatch(changenode)
646 except KeyError, inst:
642 except KeyError, inst:
647 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
643 raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
648 inst.args[0]))
644 inst.args[0]))
649 except SyntaxError, inst:
645 except SyntaxError, inst:
650 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
646 raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
651
647
652 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
648 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
653 """show one changeset using template or regular display.
649 """show one changeset using template or regular display.
654
650
655 Display format will be the first non-empty hit of:
651 Display format will be the first non-empty hit of:
656 1. option 'template'
652 1. option 'template'
657 2. option 'style'
653 2. option 'style'
658 3. [ui] setting 'logtemplate'
654 3. [ui] setting 'logtemplate'
659 4. [ui] setting 'style'
655 4. [ui] setting 'style'
660 If all of these values are either the unset or the empty string,
656 If all of these values are either the unset or the empty string,
661 regular display via changeset_printer() is done.
657 regular display via changeset_printer() is done.
662 """
658 """
663 # options
659 # options
664 patch = False
660 patch = False
665 if opts.get('patch'):
661 if opts.get('patch'):
666 patch = matchfn or util.always
662 patch = matchfn or util.always
667
663
668 tmpl = opts.get('template')
664 tmpl = opts.get('template')
669 mapfile = None
665 mapfile = None
670 if tmpl:
666 if tmpl:
671 tmpl = templater.parsestring(tmpl, quoted=False)
667 tmpl = templater.parsestring(tmpl, quoted=False)
672 else:
668 else:
673 mapfile = opts.get('style')
669 mapfile = opts.get('style')
674 # ui settings
670 # ui settings
675 if not mapfile:
671 if not mapfile:
676 tmpl = ui.config('ui', 'logtemplate')
672 tmpl = ui.config('ui', 'logtemplate')
677 if tmpl:
673 if tmpl:
678 tmpl = templater.parsestring(tmpl)
674 tmpl = templater.parsestring(tmpl)
679 else:
675 else:
680 mapfile = ui.config('ui', 'style')
676 mapfile = ui.config('ui', 'style')
681
677
682 if tmpl or mapfile:
678 if tmpl or mapfile:
683 if mapfile:
679 if mapfile:
684 if not os.path.split(mapfile)[0]:
680 if not os.path.split(mapfile)[0]:
685 mapname = (templater.templatepath('map-cmdline.' + mapfile)
681 mapname = (templater.templatepath('map-cmdline.' + mapfile)
686 or templater.templatepath(mapfile))
682 or templater.templatepath(mapfile))
687 if mapname: mapfile = mapname
683 if mapname: mapfile = mapname
688 try:
684 try:
689 t = changeset_templater(ui, repo, patch, mapfile, buffered)
685 t = changeset_templater(ui, repo, patch, mapfile, buffered)
690 except SyntaxError, inst:
686 except SyntaxError, inst:
691 raise util.Abort(inst.args[0])
687 raise util.Abort(inst.args[0])
692 if tmpl: t.use_template(tmpl)
688 if tmpl: t.use_template(tmpl)
693 return t
689 return t
694 return changeset_printer(ui, repo, patch, buffered)
690 return changeset_printer(ui, repo, patch, buffered)
695
691
696 def finddate(ui, repo, date):
692 def finddate(ui, repo, date):
697 """Find the tipmost changeset that matches the given date spec"""
693 """Find the tipmost changeset that matches the given date spec"""
698 df = util.matchdate(date + " to " + date)
694 df = util.matchdate(date + " to " + date)
699 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
695 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
700 changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None})
696 changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None})
701 results = {}
697 results = {}
702 for st, rev, fns in changeiter:
698 for st, rev, fns in changeiter:
703 if st == 'add':
699 if st == 'add':
704 d = get(rev)[2]
700 d = get(rev)[2]
705 if df(d[0]):
701 if df(d[0]):
706 results[rev] = d
702 results[rev] = d
707 elif st == 'iter':
703 elif st == 'iter':
708 if rev in results:
704 if rev in results:
709 ui.status("Found revision %s from %s\n" %
705 ui.status("Found revision %s from %s\n" %
710 (rev, util.datestr(results[rev])))
706 (rev, util.datestr(results[rev])))
711 return str(rev)
707 return str(rev)
712
708
713 raise util.Abort(_("revision matching date not found"))
709 raise util.Abort(_("revision matching date not found"))
714
710
715 def walkchangerevs(ui, repo, pats, change, opts):
711 def walkchangerevs(ui, repo, pats, change, opts):
716 '''Iterate over files and the revs they changed in.
712 '''Iterate over files and the revs they changed in.
717
713
718 Callers most commonly need to iterate backwards over the history
714 Callers most commonly need to iterate backwards over the history
719 it is interested in. Doing so has awful (quadratic-looking)
715 it is interested in. Doing so has awful (quadratic-looking)
720 performance, so we use iterators in a "windowed" way.
716 performance, so we use iterators in a "windowed" way.
721
717
722 We walk a window of revisions in the desired order. Within the
718 We walk a window of revisions in the desired order. Within the
723 window, we first walk forwards to gather data, then in the desired
719 window, we first walk forwards to gather data, then in the desired
724 order (usually backwards) to display it.
720 order (usually backwards) to display it.
725
721
726 This function returns an (iterator, matchfn) tuple. The iterator
722 This function returns an (iterator, matchfn) tuple. The iterator
727 yields 3-tuples. They will be of one of the following forms:
723 yields 3-tuples. They will be of one of the following forms:
728
724
729 "window", incrementing, lastrev: stepping through a window,
725 "window", incrementing, lastrev: stepping through a window,
730 positive if walking forwards through revs, last rev in the
726 positive if walking forwards through revs, last rev in the
731 sequence iterated over - use to reset state for the current window
727 sequence iterated over - use to reset state for the current window
732
728
733 "add", rev, fns: out-of-order traversal of the given file names
729 "add", rev, fns: out-of-order traversal of the given file names
734 fns, which changed during revision rev - use to gather data for
730 fns, which changed during revision rev - use to gather data for
735 possible display
731 possible display
736
732
737 "iter", rev, None: in-order traversal of the revs earlier iterated
733 "iter", rev, None: in-order traversal of the revs earlier iterated
738 over with "add" - use to display data'''
734 over with "add" - use to display data'''
739
735
740 def increasing_windows(start, end, windowsize=8, sizelimit=512):
736 def increasing_windows(start, end, windowsize=8, sizelimit=512):
741 if start < end:
737 if start < end:
742 while start < end:
738 while start < end:
743 yield start, min(windowsize, end-start)
739 yield start, min(windowsize, end-start)
744 start += windowsize
740 start += windowsize
745 if windowsize < sizelimit:
741 if windowsize < sizelimit:
746 windowsize *= 2
742 windowsize *= 2
747 else:
743 else:
748 while start > end:
744 while start > end:
749 yield start, min(windowsize, start-end-1)
745 yield start, min(windowsize, start-end-1)
750 start -= windowsize
746 start -= windowsize
751 if windowsize < sizelimit:
747 if windowsize < sizelimit:
752 windowsize *= 2
748 windowsize *= 2
753
749
754 files, matchfn, anypats = matchpats(repo, pats, opts)
750 files, matchfn, anypats = matchpats(repo, pats, opts)
755 follow = opts.get('follow') or opts.get('follow_first')
751 follow = opts.get('follow') or opts.get('follow_first')
756
752
757 if repo.changelog.count() == 0:
753 if repo.changelog.count() == 0:
758 return [], matchfn
754 return [], matchfn
759
755
760 if follow:
756 if follow:
761 defrange = '%s:0' % repo.changectx().rev()
757 defrange = '%s:0' % repo.changectx().rev()
762 else:
758 else:
763 defrange = 'tip:0'
759 defrange = 'tip:0'
764 revs = revrange(repo, opts['rev'] or [defrange])
760 revs = revrange(repo, opts['rev'] or [defrange])
765 wanted = {}
761 wanted = {}
766 slowpath = anypats or opts.get('removed')
762 slowpath = anypats or opts.get('removed')
767 fncache = {}
763 fncache = {}
768
764
769 if not slowpath and not files:
765 if not slowpath and not files:
770 # No files, no patterns. Display all revs.
766 # No files, no patterns. Display all revs.
771 wanted = dict.fromkeys(revs)
767 wanted = dict.fromkeys(revs)
772 copies = []
768 copies = []
773 if not slowpath:
769 if not slowpath:
774 # Only files, no patterns. Check the history of each file.
770 # Only files, no patterns. Check the history of each file.
775 def filerevgen(filelog, node):
771 def filerevgen(filelog, node):
776 cl_count = repo.changelog.count()
772 cl_count = repo.changelog.count()
777 if node is None:
773 if node is None:
778 last = filelog.count() - 1
774 last = filelog.count() - 1
779 else:
775 else:
780 last = filelog.rev(node)
776 last = filelog.rev(node)
781 for i, window in increasing_windows(last, nullrev):
777 for i, window in increasing_windows(last, nullrev):
782 revs = []
778 revs = []
783 for j in xrange(i - window, i + 1):
779 for j in xrange(i - window, i + 1):
784 n = filelog.node(j)
780 n = filelog.node(j)
785 revs.append((filelog.linkrev(n),
781 revs.append((filelog.linkrev(n),
786 follow and filelog.renamed(n)))
782 follow and filelog.renamed(n)))
787 revs.reverse()
783 revs.reverse()
788 for rev in revs:
784 for rev in revs:
789 # only yield rev for which we have the changelog, it can
785 # only yield rev for which we have the changelog, it can
790 # happen while doing "hg log" during a pull or commit
786 # happen while doing "hg log" during a pull or commit
791 if rev[0] < cl_count:
787 if rev[0] < cl_count:
792 yield rev
788 yield rev
793 def iterfiles():
789 def iterfiles():
794 for filename in files:
790 for filename in files:
795 yield filename, None
791 yield filename, None
796 for filename_node in copies:
792 for filename_node in copies:
797 yield filename_node
793 yield filename_node
798 minrev, maxrev = min(revs), max(revs)
794 minrev, maxrev = min(revs), max(revs)
799 for file_, node in iterfiles():
795 for file_, node in iterfiles():
800 filelog = repo.file(file_)
796 filelog = repo.file(file_)
801 # A zero count may be a directory or deleted file, so
797 # A zero count may be a directory or deleted file, so
802 # try to find matching entries on the slow path.
798 # try to find matching entries on the slow path.
803 if filelog.count() == 0:
799 if filelog.count() == 0:
804 slowpath = True
800 slowpath = True
805 break
801 break
806 for rev, copied in filerevgen(filelog, node):
802 for rev, copied in filerevgen(filelog, node):
807 if rev <= maxrev:
803 if rev <= maxrev:
808 if rev < minrev:
804 if rev < minrev:
809 break
805 break
810 fncache.setdefault(rev, [])
806 fncache.setdefault(rev, [])
811 fncache[rev].append(file_)
807 fncache[rev].append(file_)
812 wanted[rev] = 1
808 wanted[rev] = 1
813 if follow and copied:
809 if follow and copied:
814 copies.append(copied)
810 copies.append(copied)
815 if slowpath:
811 if slowpath:
816 if follow:
812 if follow:
817 raise util.Abort(_('can only follow copies/renames for explicit '
813 raise util.Abort(_('can only follow copies/renames for explicit '
818 'file names'))
814 'file names'))
819
815
820 # The slow path checks files modified in every changeset.
816 # The slow path checks files modified in every changeset.
821 def changerevgen():
817 def changerevgen():
822 for i, window in increasing_windows(repo.changelog.count()-1,
818 for i, window in increasing_windows(repo.changelog.count()-1,
823 nullrev):
819 nullrev):
824 for j in xrange(i - window, i + 1):
820 for j in xrange(i - window, i + 1):
825 yield j, change(j)[3]
821 yield j, change(j)[3]
826
822
827 for rev, changefiles in changerevgen():
823 for rev, changefiles in changerevgen():
828 matches = filter(matchfn, changefiles)
824 matches = filter(matchfn, changefiles)
829 if matches:
825 if matches:
830 fncache[rev] = matches
826 fncache[rev] = matches
831 wanted[rev] = 1
827 wanted[rev] = 1
832
828
833 class followfilter:
829 class followfilter:
834 def __init__(self, onlyfirst=False):
830 def __init__(self, onlyfirst=False):
835 self.startrev = nullrev
831 self.startrev = nullrev
836 self.roots = []
832 self.roots = []
837 self.onlyfirst = onlyfirst
833 self.onlyfirst = onlyfirst
838
834
839 def match(self, rev):
835 def match(self, rev):
840 def realparents(rev):
836 def realparents(rev):
841 if self.onlyfirst:
837 if self.onlyfirst:
842 return repo.changelog.parentrevs(rev)[0:1]
838 return repo.changelog.parentrevs(rev)[0:1]
843 else:
839 else:
844 return filter(lambda x: x != nullrev,
840 return filter(lambda x: x != nullrev,
845 repo.changelog.parentrevs(rev))
841 repo.changelog.parentrevs(rev))
846
842
847 if self.startrev == nullrev:
843 if self.startrev == nullrev:
848 self.startrev = rev
844 self.startrev = rev
849 return True
845 return True
850
846
851 if rev > self.startrev:
847 if rev > self.startrev:
852 # forward: all descendants
848 # forward: all descendants
853 if not self.roots:
849 if not self.roots:
854 self.roots.append(self.startrev)
850 self.roots.append(self.startrev)
855 for parent in realparents(rev):
851 for parent in realparents(rev):
856 if parent in self.roots:
852 if parent in self.roots:
857 self.roots.append(rev)
853 self.roots.append(rev)
858 return True
854 return True
859 else:
855 else:
860 # backwards: all parents
856 # backwards: all parents
861 if not self.roots:
857 if not self.roots:
862 self.roots.extend(realparents(self.startrev))
858 self.roots.extend(realparents(self.startrev))
863 if rev in self.roots:
859 if rev in self.roots:
864 self.roots.remove(rev)
860 self.roots.remove(rev)
865 self.roots.extend(realparents(rev))
861 self.roots.extend(realparents(rev))
866 return True
862 return True
867
863
868 return False
864 return False
869
865
870 # it might be worthwhile to do this in the iterator if the rev range
866 # it might be worthwhile to do this in the iterator if the rev range
871 # is descending and the prune args are all within that range
867 # is descending and the prune args are all within that range
872 for rev in opts.get('prune', ()):
868 for rev in opts.get('prune', ()):
873 rev = repo.changelog.rev(repo.lookup(rev))
869 rev = repo.changelog.rev(repo.lookup(rev))
874 ff = followfilter()
870 ff = followfilter()
875 stop = min(revs[0], revs[-1])
871 stop = min(revs[0], revs[-1])
876 for x in xrange(rev, stop-1, -1):
872 for x in xrange(rev, stop-1, -1):
877 if ff.match(x) and x in wanted:
873 if ff.match(x) and x in wanted:
878 del wanted[x]
874 del wanted[x]
879
875
880 def iterate():
876 def iterate():
881 if follow and not files:
877 if follow and not files:
882 ff = followfilter(onlyfirst=opts.get('follow_first'))
878 ff = followfilter(onlyfirst=opts.get('follow_first'))
883 def want(rev):
879 def want(rev):
884 if ff.match(rev) and rev in wanted:
880 if ff.match(rev) and rev in wanted:
885 return True
881 return True
886 return False
882 return False
887 else:
883 else:
888 def want(rev):
884 def want(rev):
889 return rev in wanted
885 return rev in wanted
890
886
891 for i, window in increasing_windows(0, len(revs)):
887 for i, window in increasing_windows(0, len(revs)):
892 yield 'window', revs[0] < revs[-1], revs[-1]
888 yield 'window', revs[0] < revs[-1], revs[-1]
893 nrevs = [rev for rev in revs[i:i+window] if want(rev)]
889 nrevs = [rev for rev in revs[i:i+window] if want(rev)]
894 srevs = list(nrevs)
890 srevs = list(nrevs)
895 srevs.sort()
891 srevs.sort()
896 for rev in srevs:
892 for rev in srevs:
897 fns = fncache.get(rev)
893 fns = fncache.get(rev)
898 if not fns:
894 if not fns:
899 def fns_generator():
895 def fns_generator():
900 for f in change(rev)[3]:
896 for f in change(rev)[3]:
901 if matchfn(f):
897 if matchfn(f):
902 yield f
898 yield f
903 fns = fns_generator()
899 fns = fns_generator()
904 yield 'add', rev, fns
900 yield 'add', rev, fns
905 for rev in nrevs:
901 for rev in nrevs:
906 yield 'iter', rev, None
902 yield 'iter', rev, None
907 return iterate(), matchfn
903 return iterate(), matchfn
908
904
909 def commit(ui, repo, commitfunc, pats, opts):
905 def commit(ui, repo, commitfunc, pats, opts):
910 '''commit the specified files or all outstanding changes'''
906 '''commit the specified files or all outstanding changes'''
911 message = logmessage(opts)
907 message = logmessage(opts)
912
908
913 if opts['addremove']:
909 if opts['addremove']:
914 addremove(repo, pats, opts)
910 addremove(repo, pats, opts)
915 fns, match, anypats = matchpats(repo, pats, opts)
911 fns, match, anypats = matchpats(repo, pats, opts)
916 if pats:
912 if pats:
917 status = repo.status(files=fns, match=match)
913 status = repo.status(files=fns, match=match)
918 modified, added, removed, deleted, unknown = status[:5]
914 modified, added, removed, deleted, unknown = status[:5]
919 files = modified + added + removed
915 files = modified + added + removed
920 slist = None
916 slist = None
921 for f in fns:
917 for f in fns:
922 if f == '.':
918 if f == '.':
923 continue
919 continue
924 if f not in files:
920 if f not in files:
925 rf = repo.wjoin(f)
921 rf = repo.wjoin(f)
926 try:
922 try:
927 mode = os.lstat(rf)[stat.ST_MODE]
923 mode = os.lstat(rf)[stat.ST_MODE]
928 except OSError:
924 except OSError:
929 raise util.Abort(_("file %s not found!") % rf)
925 raise util.Abort(_("file %s not found!") % rf)
930 if stat.S_ISDIR(mode):
926 if stat.S_ISDIR(mode):
931 name = f + '/'
927 name = f + '/'
932 if slist is None:
928 if slist is None:
933 slist = list(files)
929 slist = list(files)
934 slist.sort()
930 slist.sort()
935 i = bisect.bisect(slist, name)
931 i = bisect.bisect(slist, name)
936 if i >= len(slist) or not slist[i].startswith(name):
932 if i >= len(slist) or not slist[i].startswith(name):
937 raise util.Abort(_("no match under directory %s!")
933 raise util.Abort(_("no match under directory %s!")
938 % rf)
934 % rf)
939 elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)):
935 elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)):
940 raise util.Abort(_("can't commit %s: "
936 raise util.Abort(_("can't commit %s: "
941 "unsupported file type!") % rf)
937 "unsupported file type!") % rf)
942 elif f not in repo.dirstate:
938 elif f not in repo.dirstate:
943 raise util.Abort(_("file %s not tracked!") % rf)
939 raise util.Abort(_("file %s not tracked!") % rf)
944 else:
940 else:
945 files = []
941 files = []
946 try:
942 try:
947 return commitfunc(ui, repo, files, message, match, opts)
943 return commitfunc(ui, repo, files, message, match, opts)
948 except ValueError, inst:
944 except ValueError, inst:
949 raise util.Abort(str(inst))
945 raise util.Abort(str(inst))
@@ -1,21 +1,24 b''
1 changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{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}user: {author}\ndate: {date|date}\n{files}{file_copies}description:\n{desc|strip}\n\n\n'
3 changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\n{files}{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{file_mods}{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_mods = 'files: '
9 file_mod = ' {file_mod}'
10 end_file_mods = '\n'
8 start_file_adds = 'files+: '
11 start_file_adds = 'files+: '
9 file_add = ' {file_add}'
12 file_add = ' {file_add}'
10 end_file_adds = '\n'
13 end_file_adds = '\n'
11 start_file_dels = 'files-: '
14 start_file_dels = 'files-: '
12 file_del = ' {file_del}'
15 file_del = ' {file_del}'
13 end_file_dels = '\n'
16 end_file_dels = '\n'
14 start_file_copies = 'copies: '
17 start_file_copies = 'copies: '
15 file_copy = ' {name} ({source})'
18 file_copy = ' {name} ({source})'
16 end_file_copies = '\n'
19 end_file_copies = '\n'
17 parent = 'parent: {rev}:{node|formatnode}\n'
20 parent = 'parent: {rev}:{node|formatnode}\n'
18 manifest = 'manifest: {rev}:{node}\n'
21 manifest = 'manifest: {rev}:{node}\n'
19 branch = 'branch: {branch}\n'
22 branch = 'branch: {branch}\n'
20 tag = 'tag: {tag}\n'
23 tag = 'tag: {tag}\n'
21 extra = 'extra: {key}={value|stringescape}\n'
24 extra = 'extra: {key}={value|stringescape}\n'
@@ -1,124 +1,124 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 hg co -q 3
22 hg co -q 3
23 echo other 4 >> d
23 echo other 4 >> d
24 hg add d
24 hg add d
25 hg commit -m 'new head' -d '1500000 0' -u 'person'
25 hg commit -m 'new head' -d '1500000 0' -u 'person'
26 hg merge -q
26 hg merge -q
27 hg commit -m 'merge' -d '1500001 0' -u 'person'
27 hg commit -m 'merge' -d '1500001 0' -u 'person'
28 # second branch starting at nullrev
28 # second branch starting at nullrev
29 hg update null
29 hg update null
30 echo second > second
30 echo second > second
31 hg add second
31 hg add second
32 hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
32 hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
33
33
34 # make sure user/global hgrc does not affect tests
34 # make sure user/global hgrc does not affect tests
35 echo '[ui]' > .hg/hgrc
35 echo '[ui]' > .hg/hgrc
36 echo 'logtemplate =' >> .hg/hgrc
36 echo 'logtemplate =' >> .hg/hgrc
37 echo 'style =' >> .hg/hgrc
37 echo 'style =' >> .hg/hgrc
38
38
39 echo '# default style is like normal output'
39 echo '# default style is like normal output'
40 echo '# normal'
40 echo '# normal'
41 hg log > log.out
41 hg log > log.out
42 hg log --style default > style.out
42 hg log --style default > style.out
43 diff log.out style.out
43 diff log.out style.out
44 echo '# verbose'
44 echo '# verbose'
45 hg log -v > log.out
45 hg log -v > log.out
46 hg log -v --style default > style.out
46 hg log -v --style default > style.out
47 diff log.out style.out
47 diff log.out style.out
48 echo '# debug'
48 echo '# debug'
49 hg log --debug > log.out
49 hg log --debug > log.out
50 hg log --debug --style default > style.out
50 hg log --debug --style default > style.out
51 diff log.out style.out
51 diff log.out style.out
52
52
53 echo '# revision with no copies (used to print a traceback)'
53 echo '# revision with no copies (used to print a traceback)'
54 hg tip -v --template '\n'
54 hg tip -v --template '\n'
55
55
56 echo '# compact style works'
56 echo '# compact style works'
57 hg log --style compact
57 hg log --style compact
58 hg log -v --style compact
58 hg log -v --style compact
59 hg log --debug --style compact
59 hg log --debug --style compact
60
60
61 echo '# error if style not readable'
61 echo '# error if style not readable'
62 touch q
62 touch q
63 chmod 0 q
63 chmod 0 q
64 hg log --style ./q
64 hg log --style ./q
65
65
66 echo '# error if no style'
66 echo '# error if no style'
67 hg log --style notexist
67 hg log --style notexist
68
68
69 echo '# error if style missing key'
69 echo '# error if style missing key'
70 echo 'q = q' > t
70 echo 'q = q' > t
71 hg log --style ./t
71 hg log --style ./t
72
72
73 echo '# error if include fails'
73 echo '# error if include fails'
74 echo 'changeset = q' >> t
74 echo 'changeset = q' >> t
75 hg log --style ./t
75 hg log --style ./t
76
76
77 echo '# include works'
77 echo '# include works'
78 rm q
78 rm q
79 echo '{rev}' > q
79 echo '{rev}' > q
80 hg log --style ./t
80 hg log --style ./t
81
81
82 echo '# ui.style works'
82 echo '# ui.style works'
83 echo '[ui]' > .hg/hgrc
83 echo '[ui]' > .hg/hgrc
84 echo 'style = t' >> .hg/hgrc
84 echo 'style = t' >> .hg/hgrc
85 hg log
85 hg log
86
86
87 echo '# issue338'
87 echo '# issue338'
88 hg log --style=changelog > changelog
88 hg log --style=changelog > changelog
89 cat changelog
89 cat changelog
90
90
91 echo "# keys work"
91 echo "# keys work"
92 for key in author branches date desc file_adds file_dels files \
92 for key in author branches date desc file_adds file_dels file_mods \
93 manifest node parents rev tags; do
93 files manifest node parents rev tags; do
94 for mode in '' --verbose --debug; do
94 for mode in '' --verbose --debug; do
95 hg log $mode --template "$key$mode: {$key}\n"
95 hg log $mode --template "$key$mode: {$key}\n"
96 done
96 done
97 done
97 done
98
98
99 echo '# filters work'
99 echo '# filters work'
100 hg log --template '{author|domain}\n'
100 hg log --template '{author|domain}\n'
101 hg log --template '{author|person}\n'
101 hg log --template '{author|person}\n'
102 hg log --template '{author|user}\n'
102 hg log --template '{author|user}\n'
103 hg log --template '{date|age}\n' > /dev/null || exit 1
103 hg log --template '{date|age}\n' > /dev/null || exit 1
104 hg log --template '{date|date}\n'
104 hg log --template '{date|date}\n'
105 hg log --template '{date|isodate}\n'
105 hg log --template '{date|isodate}\n'
106 hg log --template '{date|rfc822date}\n'
106 hg log --template '{date|rfc822date}\n'
107 hg log --template '{desc|firstline}\n'
107 hg log --template '{desc|firstline}\n'
108 hg log --template '{node|short}\n'
108 hg log --template '{node|short}\n'
109
109
110 echo '# formatnode filter works'
110 echo '# formatnode filter works'
111 echo '# quiet'
111 echo '# quiet'
112 hg -q log -r 0 --template '#node|formatnode#\n'
112 hg -q log -r 0 --template '#node|formatnode#\n'
113 echo '# normal'
113 echo '# normal'
114 hg log -r 0 --template '#node|formatnode#\n'
114 hg log -r 0 --template '#node|formatnode#\n'
115 echo '# verbose'
115 echo '# verbose'
116 hg -v log -r 0 --template '#node|formatnode#\n'
116 hg -v log -r 0 --template '#node|formatnode#\n'
117 echo '# debug'
117 echo '# debug'
118 hg --debug log -r 0 --template '#node|formatnode#\n'
118 hg --debug log -r 0 --template '#node|formatnode#\n'
119
119
120 echo '# error on syntax'
120 echo '# error on syntax'
121 echo 'x = "f' >> t
121 echo 'x = "f' >> t
122 hg log
122 hg log
123
123
124 echo '# done'
124 echo '# done'
@@ -1,531 +1,555 b''
1 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
1 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
2 # default style is like normal output
2 # default style is like normal output
3 # normal
3 # normal
4 # verbose
4 # verbose
5 # debug
5 # debug
6 # revision with no copies (used to print a traceback)
6 # revision with no copies (used to print a traceback)
7
7
8 # compact style works
8 # compact style works
9 7[tip]:-1 29114dbae42b 1970-01-12 13:46 +0000 user
9 7[tip]:-1 29114dbae42b 1970-01-12 13:46 +0000 user
10 second
10 second
11
11
12 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
12 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
13 merge
13 merge
14
14
15 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
15 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
16 new head
16 new head
17
17
18 4 32a18f097fcc 1970-01-17 04:53 +0000 person
18 4 32a18f097fcc 1970-01-17 04:53 +0000 person
19 new branch
19 new branch
20
20
21 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
21 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
22 no user, no domain
22 no user, no domain
23
23
24 2 97054abb4ab8 1970-01-14 21:20 +0000 other
24 2 97054abb4ab8 1970-01-14 21:20 +0000 other
25 no person
25 no person
26
26
27 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
27 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
28 other 1
28 other 1
29
29
30 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
30 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
31 line 1
31 line 1
32
32
33 7[tip]:-1 29114dbae42b 1970-01-12 13:46 +0000 user
33 7[tip]:-1 29114dbae42b 1970-01-12 13:46 +0000 user
34 second
34 second
35
35
36 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
36 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
37 merge
37 merge
38
38
39 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
39 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
40 new head
40 new head
41
41
42 4 32a18f097fcc 1970-01-17 04:53 +0000 person
42 4 32a18f097fcc 1970-01-17 04:53 +0000 person
43 new branch
43 new branch
44
44
45 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
45 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
46 no user, no domain
46 no user, no domain
47
47
48 2 97054abb4ab8 1970-01-14 21:20 +0000 other
48 2 97054abb4ab8 1970-01-14 21:20 +0000 other
49 no person
49 no person
50
50
51 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
51 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
52 other 1
52 other 1
53
53
54 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
54 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
55 line 1
55 line 1
56
56
57 7[tip]:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 user
57 7[tip]:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 user
58 second
58 second
59
59
60 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
60 6:5,4 c7b487c6c50e 1970-01-18 08:40 +0000 person
61 merge
61 merge
62
62
63 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
63 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
64 new head
64 new head
65
65
66 4:3,-1 32a18f097fcc 1970-01-17 04:53 +0000 person
66 4:3,-1 32a18f097fcc 1970-01-17 04:53 +0000 person
67 new branch
67 new branch
68
68
69 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
69 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
70 no user, no domain
70 no user, no domain
71
71
72 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other
72 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other
73 no person
73 no person
74
74
75 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
75 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
76 other 1
76 other 1
77
77
78 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
78 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
79 line 1
79 line 1
80
80
81 # error if style not readable
81 # error if style not readable
82 abort: Permission denied: ./q
82 abort: Permission denied: ./q
83 # error if no style
83 # error if no style
84 abort: No such file or directory: notexist
84 abort: No such file or directory: notexist
85 # error if style missing key
85 # error if style missing key
86 abort: ./t: no key named 'changeset'
86 abort: ./t: no key named 'changeset'
87 # error if include fails
87 # error if include fails
88 abort: template file ./q: Permission denied
88 abort: template file ./q: Permission denied
89 # include works
89 # include works
90 7
90 7
91 6
91 6
92 5
92 5
93 4
93 4
94 3
94 3
95 2
95 2
96 1
96 1
97 0
97 0
98 # ui.style works
98 # ui.style works
99 7
99 7
100 6
100 6
101 5
101 5
102 4
102 4
103 3
103 3
104 2
104 2
105 1
105 1
106 0
106 0
107 # issue338
107 # issue338
108 1970-01-12 User Name <user@hostname>
108 1970-01-12 User Name <user@hostname>
109
109
110 * second:
110 * second:
111 second
111 second
112 [29114dbae42b] [tip]
112 [29114dbae42b] [tip]
113
113
114 1970-01-18 person <person>
114 1970-01-18 person <person>
115
115
116 * merge
116 * merge
117 [c7b487c6c50e]
117 [c7b487c6c50e]
118
118
119 * d:
119 * d:
120 new head
120 new head
121 [13207e5a10d9]
121 [13207e5a10d9]
122
122
123 1970-01-17 person <person>
123 1970-01-17 person <person>
124
124
125 * new branch
125 * new branch
126 [32a18f097fcc]
126 [32a18f097fcc]
127
127
128 1970-01-16 person <person>
128 1970-01-16 person <person>
129
129
130 * c:
130 * c:
131 no user, no domain
131 no user, no domain
132 [10e46f2dcbf4]
132 [10e46f2dcbf4]
133
133
134 1970-01-14 other <other@place>
134 1970-01-14 other <other@place>
135
135
136 * c:
136 * c:
137 no person
137 no person
138 [97054abb4ab8]
138 [97054abb4ab8]
139
139
140 1970-01-13 A. N. Other <other@place>
140 1970-01-13 A. N. Other <other@place>
141
141
142 * b:
142 * b:
143 other 1 other 2
143 other 1 other 2
144
144
145 other 3
145 other 3
146 [b608e9d1a3f0]
146 [b608e9d1a3f0]
147
147
148 1970-01-12 User Name <user@hostname>
148 1970-01-12 User Name <user@hostname>
149
149
150 * a:
150 * a:
151 line 1 line 2
151 line 1 line 2
152 [1e4e1b8f71e0]
152 [1e4e1b8f71e0]
153
153
154 # keys work
154 # keys work
155 author: User Name <user@hostname>
155 author: User Name <user@hostname>
156 author: person
156 author: person
157 author: person
157 author: person
158 author: person
158 author: person
159 author: person
159 author: person
160 author: other@place
160 author: other@place
161 author: A. N. Other <other@place>
161 author: A. N. Other <other@place>
162 author: User Name <user@hostname>
162 author: User Name <user@hostname>
163 author--verbose: User Name <user@hostname>
163 author--verbose: User Name <user@hostname>
164 author--verbose: person
164 author--verbose: person
165 author--verbose: person
165 author--verbose: person
166 author--verbose: person
166 author--verbose: person
167 author--verbose: person
167 author--verbose: person
168 author--verbose: other@place
168 author--verbose: other@place
169 author--verbose: A. N. Other <other@place>
169 author--verbose: A. N. Other <other@place>
170 author--verbose: User Name <user@hostname>
170 author--verbose: User Name <user@hostname>
171 author--debug: User Name <user@hostname>
171 author--debug: User Name <user@hostname>
172 author--debug: person
172 author--debug: person
173 author--debug: person
173 author--debug: person
174 author--debug: person
174 author--debug: person
175 author--debug: person
175 author--debug: person
176 author--debug: other@place
176 author--debug: other@place
177 author--debug: A. N. Other <other@place>
177 author--debug: A. N. Other <other@place>
178 author--debug: User Name <user@hostname>
178 author--debug: User Name <user@hostname>
179 branches:
179 branches:
180 branches:
180 branches:
181 branches:
181 branches:
182 branches: foo
182 branches: foo
183 branches:
183 branches:
184 branches:
184 branches:
185 branches:
185 branches:
186 branches:
186 branches:
187 branches--verbose:
187 branches--verbose:
188 branches--verbose:
188 branches--verbose:
189 branches--verbose:
189 branches--verbose:
190 branches--verbose: foo
190 branches--verbose: foo
191 branches--verbose:
191 branches--verbose:
192 branches--verbose:
192 branches--verbose:
193 branches--verbose:
193 branches--verbose:
194 branches--verbose:
194 branches--verbose:
195 branches--debug:
195 branches--debug:
196 branches--debug:
196 branches--debug:
197 branches--debug:
197 branches--debug:
198 branches--debug: foo
198 branches--debug: foo
199 branches--debug:
199 branches--debug:
200 branches--debug:
200 branches--debug:
201 branches--debug:
201 branches--debug:
202 branches--debug:
202 branches--debug:
203 date: 1000000.00
203 date: 1000000.00
204 date: 1500001.00
204 date: 1500001.00
205 date: 1500000.00
205 date: 1500000.00
206 date: 1400000.00
206 date: 1400000.00
207 date: 1300000.00
207 date: 1300000.00
208 date: 1200000.00
208 date: 1200000.00
209 date: 1100000.00
209 date: 1100000.00
210 date: 1000000.00
210 date: 1000000.00
211 date--verbose: 1000000.00
211 date--verbose: 1000000.00
212 date--verbose: 1500001.00
212 date--verbose: 1500001.00
213 date--verbose: 1500000.00
213 date--verbose: 1500000.00
214 date--verbose: 1400000.00
214 date--verbose: 1400000.00
215 date--verbose: 1300000.00
215 date--verbose: 1300000.00
216 date--verbose: 1200000.00
216 date--verbose: 1200000.00
217 date--verbose: 1100000.00
217 date--verbose: 1100000.00
218 date--verbose: 1000000.00
218 date--verbose: 1000000.00
219 date--debug: 1000000.00
219 date--debug: 1000000.00
220 date--debug: 1500001.00
220 date--debug: 1500001.00
221 date--debug: 1500000.00
221 date--debug: 1500000.00
222 date--debug: 1400000.00
222 date--debug: 1400000.00
223 date--debug: 1300000.00
223 date--debug: 1300000.00
224 date--debug: 1200000.00
224 date--debug: 1200000.00
225 date--debug: 1100000.00
225 date--debug: 1100000.00
226 date--debug: 1000000.00
226 date--debug: 1000000.00
227 desc: second
227 desc: second
228 desc: merge
228 desc: merge
229 desc: new head
229 desc: new head
230 desc: new branch
230 desc: new branch
231 desc: no user, no domain
231 desc: no user, no domain
232 desc: no person
232 desc: no person
233 desc: other 1
233 desc: other 1
234 other 2
234 other 2
235
235
236 other 3
236 other 3
237 desc: line 1
237 desc: line 1
238 line 2
238 line 2
239 desc--verbose: second
239 desc--verbose: second
240 desc--verbose: merge
240 desc--verbose: merge
241 desc--verbose: new head
241 desc--verbose: new head
242 desc--verbose: new branch
242 desc--verbose: new branch
243 desc--verbose: no user, no domain
243 desc--verbose: no user, no domain
244 desc--verbose: no person
244 desc--verbose: no person
245 desc--verbose: other 1
245 desc--verbose: other 1
246 other 2
246 other 2
247
247
248 other 3
248 other 3
249 desc--verbose: line 1
249 desc--verbose: line 1
250 line 2
250 line 2
251 desc--debug: second
251 desc--debug: second
252 desc--debug: merge
252 desc--debug: merge
253 desc--debug: new head
253 desc--debug: new head
254 desc--debug: new branch
254 desc--debug: new branch
255 desc--debug: no user, no domain
255 desc--debug: no user, no domain
256 desc--debug: no person
256 desc--debug: no person
257 desc--debug: other 1
257 desc--debug: other 1
258 other 2
258 other 2
259
259
260 other 3
260 other 3
261 desc--debug: line 1
261 desc--debug: line 1
262 line 2
262 line 2
263 file_adds: second
263 file_adds: second
264 file_adds:
264 file_adds:
265 file_adds: d
265 file_adds: d
266 file_adds:
266 file_adds:
267 file_adds:
267 file_adds:
268 file_adds: c
268 file_adds: c
269 file_adds: b
269 file_adds: b
270 file_adds: a
270 file_adds: a
271 file_adds--verbose: second
271 file_adds--verbose: second
272 file_adds--verbose:
272 file_adds--verbose:
273 file_adds--verbose: d
273 file_adds--verbose: d
274 file_adds--verbose:
274 file_adds--verbose:
275 file_adds--verbose:
275 file_adds--verbose:
276 file_adds--verbose: c
276 file_adds--verbose: c
277 file_adds--verbose: b
277 file_adds--verbose: b
278 file_adds--verbose: a
278 file_adds--verbose: a
279 file_adds--debug: second
279 file_adds--debug: second
280 file_adds--debug:
280 file_adds--debug:
281 file_adds--debug: d
281 file_adds--debug: d
282 file_adds--debug:
282 file_adds--debug:
283 file_adds--debug:
283 file_adds--debug:
284 file_adds--debug: c
284 file_adds--debug: c
285 file_adds--debug: b
285 file_adds--debug: b
286 file_adds--debug: a
286 file_adds--debug: a
287 file_dels:
287 file_dels:
288 file_dels:
288 file_dels:
289 file_dels:
289 file_dels:
290 file_dels:
290 file_dels:
291 file_dels:
291 file_dels:
292 file_dels:
292 file_dels:
293 file_dels:
293 file_dels:
294 file_dels:
294 file_dels:
295 file_dels--verbose:
295 file_dels--verbose:
296 file_dels--verbose:
296 file_dels--verbose:
297 file_dels--verbose:
297 file_dels--verbose:
298 file_dels--verbose:
298 file_dels--verbose:
299 file_dels--verbose:
299 file_dels--verbose:
300 file_dels--verbose:
300 file_dels--verbose:
301 file_dels--verbose:
301 file_dels--verbose:
302 file_dels--verbose:
302 file_dels--verbose:
303 file_dels--debug:
303 file_dels--debug:
304 file_dels--debug:
304 file_dels--debug:
305 file_dels--debug:
305 file_dels--debug:
306 file_dels--debug:
306 file_dels--debug:
307 file_dels--debug:
307 file_dels--debug:
308 file_dels--debug:
308 file_dels--debug:
309 file_dels--debug:
309 file_dels--debug:
310 file_dels--debug:
310 file_dels--debug:
311 file_mods:
312 file_mods:
313 file_mods:
314 file_mods:
315 file_mods: c
316 file_mods:
317 file_mods:
318 file_mods:
319 file_mods--verbose:
320 file_mods--verbose:
321 file_mods--verbose:
322 file_mods--verbose:
323 file_mods--verbose: c
324 file_mods--verbose:
325 file_mods--verbose:
326 file_mods--verbose:
327 file_mods--debug:
328 file_mods--debug:
329 file_mods--debug:
330 file_mods--debug:
331 file_mods--debug: c
332 file_mods--debug:
333 file_mods--debug:
334 file_mods--debug:
311 files: second
335 files: second
312 files:
336 files:
313 files: d
337 files: d
314 files:
338 files:
315 files: c
339 files: c
316 files: c
340 files: c
317 files: b
341 files: b
318 files: a
342 files: a
319 files--verbose: second
343 files--verbose: second
320 files--verbose:
344 files--verbose:
321 files--verbose: d
345 files--verbose: d
322 files--verbose:
346 files--verbose:
323 files--verbose: c
347 files--verbose: c
324 files--verbose: c
348 files--verbose: c
325 files--verbose: b
349 files--verbose: b
326 files--verbose: a
350 files--verbose: a
327 files--debug:
351 files--debug: second
328 files--debug:
352 files--debug:
329 files--debug:
353 files--debug: d
330 files--debug:
354 files--debug:
331 files--debug: c
355 files--debug: c
332 files--debug:
356 files--debug: c
333 files--debug:
357 files--debug: b
334 files--debug:
358 files--debug: a
335 manifest: 7:f2dbc354b94e
359 manifest: 7:f2dbc354b94e
336 manifest: 6:91015e9dbdd7
360 manifest: 6:91015e9dbdd7
337 manifest: 5:4dc3def4f9b4
361 manifest: 5:4dc3def4f9b4
338 manifest: 4:90ae8dda64e1
362 manifest: 4:90ae8dda64e1
339 manifest: 3:cb5a1327723b
363 manifest: 3:cb5a1327723b
340 manifest: 2:6e0e82995c35
364 manifest: 2:6e0e82995c35
341 manifest: 1:4e8d705b1e53
365 manifest: 1:4e8d705b1e53
342 manifest: 0:a0c8bcbbb45c
366 manifest: 0:a0c8bcbbb45c
343 manifest--verbose: 7:f2dbc354b94e
367 manifest--verbose: 7:f2dbc354b94e
344 manifest--verbose: 6:91015e9dbdd7
368 manifest--verbose: 6:91015e9dbdd7
345 manifest--verbose: 5:4dc3def4f9b4
369 manifest--verbose: 5:4dc3def4f9b4
346 manifest--verbose: 4:90ae8dda64e1
370 manifest--verbose: 4:90ae8dda64e1
347 manifest--verbose: 3:cb5a1327723b
371 manifest--verbose: 3:cb5a1327723b
348 manifest--verbose: 2:6e0e82995c35
372 manifest--verbose: 2:6e0e82995c35
349 manifest--verbose: 1:4e8d705b1e53
373 manifest--verbose: 1:4e8d705b1e53
350 manifest--verbose: 0:a0c8bcbbb45c
374 manifest--verbose: 0:a0c8bcbbb45c
351 manifest--debug: 7:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
375 manifest--debug: 7:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
352 manifest--debug: 6:91015e9dbdd76a6791085d12b0a0ec7fcd22ffbf
376 manifest--debug: 6:91015e9dbdd76a6791085d12b0a0ec7fcd22ffbf
353 manifest--debug: 5:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
377 manifest--debug: 5:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
354 manifest--debug: 4:90ae8dda64e1a876c792bccb9af66284f6018363
378 manifest--debug: 4:90ae8dda64e1a876c792bccb9af66284f6018363
355 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
379 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
356 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
380 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
357 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
381 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
358 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
382 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
359 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
383 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
360 node: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
384 node: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
361 node: 13207e5a10d9fd28ec424934298e176197f2c67f
385 node: 13207e5a10d9fd28ec424934298e176197f2c67f
362 node: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
386 node: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
363 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
387 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
364 node: 97054abb4ab824450e9164180baf491ae0078465
388 node: 97054abb4ab824450e9164180baf491ae0078465
365 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
389 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
366 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
390 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
367 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
391 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
368 node--verbose: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
392 node--verbose: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
369 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
393 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
370 node--verbose: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
394 node--verbose: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
371 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
395 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
372 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
396 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
373 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
397 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
374 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
398 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
375 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
399 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
376 node--debug: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
400 node--debug: c7b487c6c50ef1cf464cafdc4f4f5e615fc5999f
377 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
401 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
378 node--debug: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
402 node--debug: 32a18f097fcccf76ef282f62f8a85b3adf8d13c4
379 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
403 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
380 node--debug: 97054abb4ab824450e9164180baf491ae0078465
404 node--debug: 97054abb4ab824450e9164180baf491ae0078465
381 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
405 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
382 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
406 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
383 parents: -1:000000000000
407 parents: -1:000000000000
384 parents: 5:13207e5a10d9 4:32a18f097fcc
408 parents: 5:13207e5a10d9 4:32a18f097fcc
385 parents: 3:10e46f2dcbf4
409 parents: 3:10e46f2dcbf4
386 parents:
410 parents:
387 parents:
411 parents:
388 parents:
412 parents:
389 parents:
413 parents:
390 parents:
414 parents:
391 parents--verbose: -1:000000000000
415 parents--verbose: -1:000000000000
392 parents--verbose: 5:13207e5a10d9 4:32a18f097fcc
416 parents--verbose: 5:13207e5a10d9 4:32a18f097fcc
393 parents--verbose: 3:10e46f2dcbf4
417 parents--verbose: 3:10e46f2dcbf4
394 parents--verbose:
418 parents--verbose:
395 parents--verbose:
419 parents--verbose:
396 parents--verbose:
420 parents--verbose:
397 parents--verbose:
421 parents--verbose:
398 parents--verbose:
422 parents--verbose:
399 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
423 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
400 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:32a18f097fcccf76ef282f62f8a85b3adf8d13c4
424 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:32a18f097fcccf76ef282f62f8a85b3adf8d13c4
401 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
425 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
402 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
426 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
403 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
427 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
404 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
428 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
405 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
429 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
406 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
430 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
407 rev: 7
431 rev: 7
408 rev: 6
432 rev: 6
409 rev: 5
433 rev: 5
410 rev: 4
434 rev: 4
411 rev: 3
435 rev: 3
412 rev: 2
436 rev: 2
413 rev: 1
437 rev: 1
414 rev: 0
438 rev: 0
415 rev--verbose: 7
439 rev--verbose: 7
416 rev--verbose: 6
440 rev--verbose: 6
417 rev--verbose: 5
441 rev--verbose: 5
418 rev--verbose: 4
442 rev--verbose: 4
419 rev--verbose: 3
443 rev--verbose: 3
420 rev--verbose: 2
444 rev--verbose: 2
421 rev--verbose: 1
445 rev--verbose: 1
422 rev--verbose: 0
446 rev--verbose: 0
423 rev--debug: 7
447 rev--debug: 7
424 rev--debug: 6
448 rev--debug: 6
425 rev--debug: 5
449 rev--debug: 5
426 rev--debug: 4
450 rev--debug: 4
427 rev--debug: 3
451 rev--debug: 3
428 rev--debug: 2
452 rev--debug: 2
429 rev--debug: 1
453 rev--debug: 1
430 rev--debug: 0
454 rev--debug: 0
431 tags: tip
455 tags: tip
432 tags:
456 tags:
433 tags:
457 tags:
434 tags:
458 tags:
435 tags:
459 tags:
436 tags:
460 tags:
437 tags:
461 tags:
438 tags:
462 tags:
439 tags--verbose: tip
463 tags--verbose: tip
440 tags--verbose:
464 tags--verbose:
441 tags--verbose:
465 tags--verbose:
442 tags--verbose:
466 tags--verbose:
443 tags--verbose:
467 tags--verbose:
444 tags--verbose:
468 tags--verbose:
445 tags--verbose:
469 tags--verbose:
446 tags--verbose:
470 tags--verbose:
447 tags--debug: tip
471 tags--debug: tip
448 tags--debug:
472 tags--debug:
449 tags--debug:
473 tags--debug:
450 tags--debug:
474 tags--debug:
451 tags--debug:
475 tags--debug:
452 tags--debug:
476 tags--debug:
453 tags--debug:
477 tags--debug:
454 tags--debug:
478 tags--debug:
455 # filters work
479 # filters work
456 hostname
480 hostname
457
481
458
482
459
483
460
484
461 place
485 place
462 place
486 place
463 hostname
487 hostname
464 User Name
488 User Name
465 person
489 person
466 person
490 person
467 person
491 person
468 person
492 person
469 other
493 other
470 A. N. Other
494 A. N. Other
471 User Name
495 User Name
472 user
496 user
473 person
497 person
474 person
498 person
475 person
499 person
476 person
500 person
477 other
501 other
478 other
502 other
479 user
503 user
480 Mon Jan 12 13:46:40 1970 +0000
504 Mon Jan 12 13:46:40 1970 +0000
481 Sun Jan 18 08:40:01 1970 +0000
505 Sun Jan 18 08:40:01 1970 +0000
482 Sun Jan 18 08:40:00 1970 +0000
506 Sun Jan 18 08:40:00 1970 +0000
483 Sat Jan 17 04:53:20 1970 +0000
507 Sat Jan 17 04:53:20 1970 +0000
484 Fri Jan 16 01:06:40 1970 +0000
508 Fri Jan 16 01:06:40 1970 +0000
485 Wed Jan 14 21:20:00 1970 +0000
509 Wed Jan 14 21:20:00 1970 +0000
486 Tue Jan 13 17:33:20 1970 +0000
510 Tue Jan 13 17:33:20 1970 +0000
487 Mon Jan 12 13:46:40 1970 +0000
511 Mon Jan 12 13:46:40 1970 +0000
488 1970-01-12 13:46 +0000
512 1970-01-12 13:46 +0000
489 1970-01-18 08:40 +0000
513 1970-01-18 08:40 +0000
490 1970-01-18 08:40 +0000
514 1970-01-18 08:40 +0000
491 1970-01-17 04:53 +0000
515 1970-01-17 04:53 +0000
492 1970-01-16 01:06 +0000
516 1970-01-16 01:06 +0000
493 1970-01-14 21:20 +0000
517 1970-01-14 21:20 +0000
494 1970-01-13 17:33 +0000
518 1970-01-13 17:33 +0000
495 1970-01-12 13:46 +0000
519 1970-01-12 13:46 +0000
496 Mon, 12 Jan 1970 13:46:40 +0000
520 Mon, 12 Jan 1970 13:46:40 +0000
497 Sun, 18 Jan 1970 08:40:01 +0000
521 Sun, 18 Jan 1970 08:40:01 +0000
498 Sun, 18 Jan 1970 08:40:00 +0000
522 Sun, 18 Jan 1970 08:40:00 +0000
499 Sat, 17 Jan 1970 04:53:20 +0000
523 Sat, 17 Jan 1970 04:53:20 +0000
500 Fri, 16 Jan 1970 01:06:40 +0000
524 Fri, 16 Jan 1970 01:06:40 +0000
501 Wed, 14 Jan 1970 21:20:00 +0000
525 Wed, 14 Jan 1970 21:20:00 +0000
502 Tue, 13 Jan 1970 17:33:20 +0000
526 Tue, 13 Jan 1970 17:33:20 +0000
503 Mon, 12 Jan 1970 13:46:40 +0000
527 Mon, 12 Jan 1970 13:46:40 +0000
504 second
528 second
505 merge
529 merge
506 new head
530 new head
507 new branch
531 new branch
508 no user, no domain
532 no user, no domain
509 no person
533 no person
510 other 1
534 other 1
511 line 1
535 line 1
512 29114dbae42b
536 29114dbae42b
513 c7b487c6c50e
537 c7b487c6c50e
514 13207e5a10d9
538 13207e5a10d9
515 32a18f097fcc
539 32a18f097fcc
516 10e46f2dcbf4
540 10e46f2dcbf4
517 97054abb4ab8
541 97054abb4ab8
518 b608e9d1a3f0
542 b608e9d1a3f0
519 1e4e1b8f71e0
543 1e4e1b8f71e0
520 # formatnode filter works
544 # formatnode filter works
521 # quiet
545 # quiet
522 1e4e1b8f71e0
546 1e4e1b8f71e0
523 # normal
547 # normal
524 1e4e1b8f71e0
548 1e4e1b8f71e0
525 # verbose
549 # verbose
526 1e4e1b8f71e0
550 1e4e1b8f71e0
527 # debug
551 # debug
528 1e4e1b8f71e05681d422154f5421e385fec3454f
552 1e4e1b8f71e05681d422154f5421e385fec3454f
529 # error on syntax
553 # error on syntax
530 abort: t:3: unmatched quotes
554 abort: t:3: unmatched quotes
531 # done
555 # done
General Comments 0
You need to be logged in to leave comments. Login now