##// END OF EJS Templates
log: add --stat for diffstat output...
Yuya Nishihara -
r11061:51d03875 default
parent child Browse files
Show More
@@ -1,1240 +1,1240 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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from i18n import _
9 from i18n import _
10 import os, sys, errno, re, glob, tempfile
10 import os, sys, errno, re, glob, tempfile
11 import mdiff, bdiff, util, templater, patch, error, encoding, templatekw
11 import mdiff, bdiff, util, templater, patch, error, encoding, templatekw
12 import match as _match
12 import match as _match
13 import similar
13 import similar
14
14
15 revrangesep = ':'
15 revrangesep = ':'
16
16
17 def parsealiases(cmd):
17 def parsealiases(cmd):
18 return cmd.lstrip("^").split("|")
18 return cmd.lstrip("^").split("|")
19
19
20 def findpossible(cmd, table, strict=False):
20 def findpossible(cmd, table, strict=False):
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 = parsealiases(e)
29 aliases = parsealiases(e)
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 strict:
33 elif not 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(cmd, table, strict=True):
49 def findcmd(cmd, table, strict=True):
50 """Return (aliases, command table entry) for command string."""
50 """Return (aliases, command table entry) for command string."""
51 choice = findpossible(cmd, table, strict)
51 choice = findpossible(cmd, table, strict)
52
52
53 if cmd in choice:
53 if cmd in choice:
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 error.AmbiguousCommand(cmd, clist)
59 raise error.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 error.UnknownCommand(cmd)
64 raise error.UnknownCommand(cmd)
65
65
66 def findrepo(p):
66 def findrepo(p):
67 while not os.path.isdir(os.path.join(p, ".hg")):
67 while not os.path.isdir(os.path.join(p, ".hg")):
68 oldp, p = p, os.path.dirname(p)
68 oldp, p = p, os.path.dirname(p)
69 if p == oldp:
69 if p == oldp:
70 return None
70 return None
71
71
72 return p
72 return p
73
73
74 def bail_if_changed(repo):
74 def bail_if_changed(repo):
75 if repo.dirstate.parents()[1] != nullid:
75 if repo.dirstate.parents()[1] != nullid:
76 raise util.Abort(_('outstanding uncommitted merge'))
76 raise util.Abort(_('outstanding uncommitted merge'))
77 modified, added, removed, deleted = repo.status()[:4]
77 modified, added, removed, deleted = repo.status()[:4]
78 if modified or added or removed or deleted:
78 if modified or added or removed or deleted:
79 raise util.Abort(_("outstanding uncommitted changes"))
79 raise util.Abort(_("outstanding uncommitted changes"))
80
80
81 def logmessage(opts):
81 def logmessage(opts):
82 """ get the log message according to -m and -l option """
82 """ get the log message according to -m and -l option """
83 message = opts.get('message')
83 message = opts.get('message')
84 logfile = opts.get('logfile')
84 logfile = opts.get('logfile')
85
85
86 if message and logfile:
86 if message and logfile:
87 raise util.Abort(_('options --message and --logfile are mutually '
87 raise util.Abort(_('options --message and --logfile are mutually '
88 'exclusive'))
88 'exclusive'))
89 if not message and logfile:
89 if not message and logfile:
90 try:
90 try:
91 if logfile == '-':
91 if logfile == '-':
92 message = sys.stdin.read()
92 message = sys.stdin.read()
93 else:
93 else:
94 message = open(logfile).read()
94 message = open(logfile).read()
95 except IOError, inst:
95 except IOError, inst:
96 raise util.Abort(_("can't read commit message '%s': %s") %
96 raise util.Abort(_("can't read commit message '%s': %s") %
97 (logfile, inst.strerror))
97 (logfile, inst.strerror))
98 return message
98 return message
99
99
100 def loglimit(opts):
100 def loglimit(opts):
101 """get the log limit according to option -l/--limit"""
101 """get the log limit according to option -l/--limit"""
102 limit = opts.get('limit')
102 limit = opts.get('limit')
103 if limit:
103 if limit:
104 try:
104 try:
105 limit = int(limit)
105 limit = int(limit)
106 except ValueError:
106 except ValueError:
107 raise util.Abort(_('limit must be a positive integer'))
107 raise util.Abort(_('limit must be a positive integer'))
108 if limit <= 0:
108 if limit <= 0:
109 raise util.Abort(_('limit must be positive'))
109 raise util.Abort(_('limit must be positive'))
110 else:
110 else:
111 limit = None
111 limit = None
112 return limit
112 return limit
113
113
114 def remoteui(src, opts):
114 def remoteui(src, opts):
115 'build a remote ui from ui or repo and opts'
115 'build a remote ui from ui or repo and opts'
116 if hasattr(src, 'baseui'): # looks like a repository
116 if hasattr(src, 'baseui'): # looks like a repository
117 dst = src.baseui.copy() # drop repo-specific config
117 dst = src.baseui.copy() # drop repo-specific config
118 src = src.ui # copy target options from repo
118 src = src.ui # copy target options from repo
119 else: # assume it's a global ui object
119 else: # assume it's a global ui object
120 dst = src.copy() # keep all global options
120 dst = src.copy() # keep all global options
121
121
122 # copy ssh-specific options
122 # copy ssh-specific options
123 for o in 'ssh', 'remotecmd':
123 for o in 'ssh', 'remotecmd':
124 v = opts.get(o) or src.config('ui', o)
124 v = opts.get(o) or src.config('ui', o)
125 if v:
125 if v:
126 dst.setconfig("ui", o, v)
126 dst.setconfig("ui", o, v)
127
127
128 # copy bundle-specific options
128 # copy bundle-specific options
129 r = src.config('bundle', 'mainreporoot')
129 r = src.config('bundle', 'mainreporoot')
130 if r:
130 if r:
131 dst.setconfig('bundle', 'mainreporoot', r)
131 dst.setconfig('bundle', 'mainreporoot', r)
132
132
133 # copy auth and http_proxy section settings
133 # copy auth and http_proxy section settings
134 for sect in ('auth', 'http_proxy'):
134 for sect in ('auth', 'http_proxy'):
135 for key, val in src.configitems(sect):
135 for key, val in src.configitems(sect):
136 dst.setconfig(sect, key, val)
136 dst.setconfig(sect, key, val)
137
137
138 return dst
138 return dst
139
139
140 def revpair(repo, revs):
140 def revpair(repo, revs):
141 '''return pair of nodes, given list of revisions. second item can
141 '''return pair of nodes, given list of revisions. second item can
142 be None, meaning use working dir.'''
142 be None, meaning use working dir.'''
143
143
144 def revfix(repo, val, defval):
144 def revfix(repo, val, defval):
145 if not val and val != 0 and defval is not None:
145 if not val and val != 0 and defval is not None:
146 val = defval
146 val = defval
147 return repo.lookup(val)
147 return repo.lookup(val)
148
148
149 if not revs:
149 if not revs:
150 return repo.dirstate.parents()[0], None
150 return repo.dirstate.parents()[0], None
151 end = None
151 end = None
152 if len(revs) == 1:
152 if len(revs) == 1:
153 if revrangesep in revs[0]:
153 if revrangesep in revs[0]:
154 start, end = revs[0].split(revrangesep, 1)
154 start, end = revs[0].split(revrangesep, 1)
155 start = revfix(repo, start, 0)
155 start = revfix(repo, start, 0)
156 end = revfix(repo, end, len(repo) - 1)
156 end = revfix(repo, end, len(repo) - 1)
157 else:
157 else:
158 start = revfix(repo, revs[0], None)
158 start = revfix(repo, revs[0], None)
159 elif len(revs) == 2:
159 elif len(revs) == 2:
160 if revrangesep in revs[0] or revrangesep in revs[1]:
160 if revrangesep in revs[0] or revrangesep in revs[1]:
161 raise util.Abort(_('too many revisions specified'))
161 raise util.Abort(_('too many revisions specified'))
162 start = revfix(repo, revs[0], None)
162 start = revfix(repo, revs[0], None)
163 end = revfix(repo, revs[1], None)
163 end = revfix(repo, revs[1], None)
164 else:
164 else:
165 raise util.Abort(_('too many revisions specified'))
165 raise util.Abort(_('too many revisions specified'))
166 return start, end
166 return start, end
167
167
168 def revrange(repo, revs):
168 def revrange(repo, revs):
169 """Yield revision as strings from a list of revision specifications."""
169 """Yield revision as strings from a list of revision specifications."""
170
170
171 def revfix(repo, val, defval):
171 def revfix(repo, val, defval):
172 if not val and val != 0 and defval is not None:
172 if not val and val != 0 and defval is not None:
173 return defval
173 return defval
174 return repo.changelog.rev(repo.lookup(val))
174 return repo.changelog.rev(repo.lookup(val))
175
175
176 seen, l = set(), []
176 seen, l = set(), []
177 for spec in revs:
177 for spec in revs:
178 if revrangesep in spec:
178 if revrangesep in spec:
179 start, end = spec.split(revrangesep, 1)
179 start, end = spec.split(revrangesep, 1)
180 start = revfix(repo, start, 0)
180 start = revfix(repo, start, 0)
181 end = revfix(repo, end, len(repo) - 1)
181 end = revfix(repo, end, len(repo) - 1)
182 step = start > end and -1 or 1
182 step = start > end and -1 or 1
183 for rev in xrange(start, end + step, step):
183 for rev in xrange(start, end + step, step):
184 if rev in seen:
184 if rev in seen:
185 continue
185 continue
186 seen.add(rev)
186 seen.add(rev)
187 l.append(rev)
187 l.append(rev)
188 else:
188 else:
189 rev = revfix(repo, spec, None)
189 rev = revfix(repo, spec, None)
190 if rev in seen:
190 if rev in seen:
191 continue
191 continue
192 seen.add(rev)
192 seen.add(rev)
193 l.append(rev)
193 l.append(rev)
194
194
195 return l
195 return l
196
196
197 def make_filename(repo, pat, node,
197 def make_filename(repo, pat, node,
198 total=None, seqno=None, revwidth=None, pathname=None):
198 total=None, seqno=None, revwidth=None, pathname=None):
199 node_expander = {
199 node_expander = {
200 'H': lambda: hex(node),
200 'H': lambda: hex(node),
201 'R': lambda: str(repo.changelog.rev(node)),
201 'R': lambda: str(repo.changelog.rev(node)),
202 'h': lambda: short(node),
202 'h': lambda: short(node),
203 }
203 }
204 expander = {
204 expander = {
205 '%': lambda: '%',
205 '%': lambda: '%',
206 'b': lambda: os.path.basename(repo.root),
206 'b': lambda: os.path.basename(repo.root),
207 }
207 }
208
208
209 try:
209 try:
210 if node:
210 if node:
211 expander.update(node_expander)
211 expander.update(node_expander)
212 if node:
212 if node:
213 expander['r'] = (lambda:
213 expander['r'] = (lambda:
214 str(repo.changelog.rev(node)).zfill(revwidth or 0))
214 str(repo.changelog.rev(node)).zfill(revwidth or 0))
215 if total is not None:
215 if total is not None:
216 expander['N'] = lambda: str(total)
216 expander['N'] = lambda: str(total)
217 if seqno is not None:
217 if seqno is not None:
218 expander['n'] = lambda: str(seqno)
218 expander['n'] = lambda: str(seqno)
219 if total is not None and seqno is not None:
219 if total is not None and seqno is not None:
220 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
220 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
221 if pathname is not None:
221 if pathname is not None:
222 expander['s'] = lambda: os.path.basename(pathname)
222 expander['s'] = lambda: os.path.basename(pathname)
223 expander['d'] = lambda: os.path.dirname(pathname) or '.'
223 expander['d'] = lambda: os.path.dirname(pathname) or '.'
224 expander['p'] = lambda: pathname
224 expander['p'] = lambda: pathname
225
225
226 newname = []
226 newname = []
227 patlen = len(pat)
227 patlen = len(pat)
228 i = 0
228 i = 0
229 while i < patlen:
229 while i < patlen:
230 c = pat[i]
230 c = pat[i]
231 if c == '%':
231 if c == '%':
232 i += 1
232 i += 1
233 c = pat[i]
233 c = pat[i]
234 c = expander[c]()
234 c = expander[c]()
235 newname.append(c)
235 newname.append(c)
236 i += 1
236 i += 1
237 return ''.join(newname)
237 return ''.join(newname)
238 except KeyError, inst:
238 except KeyError, inst:
239 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
239 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
240 inst.args[0])
240 inst.args[0])
241
241
242 def make_file(repo, pat, node=None,
242 def make_file(repo, pat, node=None,
243 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
243 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
244
244
245 writable = 'w' in mode or 'a' in mode
245 writable = 'w' in mode or 'a' in mode
246
246
247 if not pat or pat == '-':
247 if not pat or pat == '-':
248 return writable and sys.stdout or sys.stdin
248 return writable and sys.stdout or sys.stdin
249 if hasattr(pat, 'write') and writable:
249 if hasattr(pat, 'write') and writable:
250 return pat
250 return pat
251 if hasattr(pat, 'read') and 'r' in mode:
251 if hasattr(pat, 'read') and 'r' in mode:
252 return pat
252 return pat
253 return open(make_filename(repo, pat, node, total, seqno, revwidth,
253 return open(make_filename(repo, pat, node, total, seqno, revwidth,
254 pathname),
254 pathname),
255 mode)
255 mode)
256
256
257 def expandpats(pats):
257 def expandpats(pats):
258 if not util.expandglobs:
258 if not util.expandglobs:
259 return list(pats)
259 return list(pats)
260 ret = []
260 ret = []
261 for p in pats:
261 for p in pats:
262 kind, name = _match._patsplit(p, None)
262 kind, name = _match._patsplit(p, None)
263 if kind is None:
263 if kind is None:
264 try:
264 try:
265 globbed = glob.glob(name)
265 globbed = glob.glob(name)
266 except re.error:
266 except re.error:
267 globbed = [name]
267 globbed = [name]
268 if globbed:
268 if globbed:
269 ret.extend(globbed)
269 ret.extend(globbed)
270 continue
270 continue
271 ret.append(p)
271 ret.append(p)
272 return ret
272 return ret
273
273
274 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
274 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
275 if not globbed and default == 'relpath':
275 if not globbed and default == 'relpath':
276 pats = expandpats(pats or [])
276 pats = expandpats(pats or [])
277 m = _match.match(repo.root, repo.getcwd(), pats,
277 m = _match.match(repo.root, repo.getcwd(), pats,
278 opts.get('include'), opts.get('exclude'), default)
278 opts.get('include'), opts.get('exclude'), default)
279 def badfn(f, msg):
279 def badfn(f, msg):
280 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
280 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
281 m.bad = badfn
281 m.bad = badfn
282 return m
282 return m
283
283
284 def matchall(repo):
284 def matchall(repo):
285 return _match.always(repo.root, repo.getcwd())
285 return _match.always(repo.root, repo.getcwd())
286
286
287 def matchfiles(repo, files):
287 def matchfiles(repo, files):
288 return _match.exact(repo.root, repo.getcwd(), files)
288 return _match.exact(repo.root, repo.getcwd(), files)
289
289
290 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
290 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
291 if dry_run is None:
291 if dry_run is None:
292 dry_run = opts.get('dry_run')
292 dry_run = opts.get('dry_run')
293 if similarity is None:
293 if similarity is None:
294 similarity = float(opts.get('similarity') or 0)
294 similarity = float(opts.get('similarity') or 0)
295 # we'd use status here, except handling of symlinks and ignore is tricky
295 # we'd use status here, except handling of symlinks and ignore is tricky
296 added, unknown, deleted, removed = [], [], [], []
296 added, unknown, deleted, removed = [], [], [], []
297 audit_path = util.path_auditor(repo.root)
297 audit_path = util.path_auditor(repo.root)
298 m = match(repo, pats, opts)
298 m = match(repo, pats, opts)
299 for abs in repo.walk(m):
299 for abs in repo.walk(m):
300 target = repo.wjoin(abs)
300 target = repo.wjoin(abs)
301 good = True
301 good = True
302 try:
302 try:
303 audit_path(abs)
303 audit_path(abs)
304 except:
304 except:
305 good = False
305 good = False
306 rel = m.rel(abs)
306 rel = m.rel(abs)
307 exact = m.exact(abs)
307 exact = m.exact(abs)
308 if good and abs not in repo.dirstate:
308 if good and abs not in repo.dirstate:
309 unknown.append(abs)
309 unknown.append(abs)
310 if repo.ui.verbose or not exact:
310 if repo.ui.verbose or not exact:
311 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
311 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
312 elif repo.dirstate[abs] != 'r' and (not good or not util.lexists(target)
312 elif repo.dirstate[abs] != 'r' and (not good or not util.lexists(target)
313 or (os.path.isdir(target) and not os.path.islink(target))):
313 or (os.path.isdir(target) and not os.path.islink(target))):
314 deleted.append(abs)
314 deleted.append(abs)
315 if repo.ui.verbose or not exact:
315 if repo.ui.verbose or not exact:
316 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
316 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
317 # for finding renames
317 # for finding renames
318 elif repo.dirstate[abs] == 'r':
318 elif repo.dirstate[abs] == 'r':
319 removed.append(abs)
319 removed.append(abs)
320 elif repo.dirstate[abs] == 'a':
320 elif repo.dirstate[abs] == 'a':
321 added.append(abs)
321 added.append(abs)
322 copies = {}
322 copies = {}
323 if similarity > 0:
323 if similarity > 0:
324 for old, new, score in similar.findrenames(repo,
324 for old, new, score in similar.findrenames(repo,
325 added + unknown, removed + deleted, similarity):
325 added + unknown, removed + deleted, similarity):
326 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
326 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
327 repo.ui.status(_('recording removal of %s as rename to %s '
327 repo.ui.status(_('recording removal of %s as rename to %s '
328 '(%d%% similar)\n') %
328 '(%d%% similar)\n') %
329 (m.rel(old), m.rel(new), score * 100))
329 (m.rel(old), m.rel(new), score * 100))
330 copies[new] = old
330 copies[new] = old
331
331
332 if not dry_run:
332 if not dry_run:
333 wlock = repo.wlock()
333 wlock = repo.wlock()
334 try:
334 try:
335 repo.remove(deleted)
335 repo.remove(deleted)
336 repo.add(unknown)
336 repo.add(unknown)
337 for new, old in copies.iteritems():
337 for new, old in copies.iteritems():
338 repo.copy(old, new)
338 repo.copy(old, new)
339 finally:
339 finally:
340 wlock.release()
340 wlock.release()
341
341
342 def copy(ui, repo, pats, opts, rename=False):
342 def copy(ui, repo, pats, opts, rename=False):
343 # called with the repo lock held
343 # called with the repo lock held
344 #
344 #
345 # hgsep => pathname that uses "/" to separate directories
345 # hgsep => pathname that uses "/" to separate directories
346 # ossep => pathname that uses os.sep to separate directories
346 # ossep => pathname that uses os.sep to separate directories
347 cwd = repo.getcwd()
347 cwd = repo.getcwd()
348 targets = {}
348 targets = {}
349 after = opts.get("after")
349 after = opts.get("after")
350 dryrun = opts.get("dry_run")
350 dryrun = opts.get("dry_run")
351
351
352 def walkpat(pat):
352 def walkpat(pat):
353 srcs = []
353 srcs = []
354 m = match(repo, [pat], opts, globbed=True)
354 m = match(repo, [pat], opts, globbed=True)
355 for abs in repo.walk(m):
355 for abs in repo.walk(m):
356 state = repo.dirstate[abs]
356 state = repo.dirstate[abs]
357 rel = m.rel(abs)
357 rel = m.rel(abs)
358 exact = m.exact(abs)
358 exact = m.exact(abs)
359 if state in '?r':
359 if state in '?r':
360 if exact and state == '?':
360 if exact and state == '?':
361 ui.warn(_('%s: not copying - file is not managed\n') % rel)
361 ui.warn(_('%s: not copying - file is not managed\n') % rel)
362 if exact and state == 'r':
362 if exact and state == 'r':
363 ui.warn(_('%s: not copying - file has been marked for'
363 ui.warn(_('%s: not copying - file has been marked for'
364 ' remove\n') % rel)
364 ' remove\n') % rel)
365 continue
365 continue
366 # abs: hgsep
366 # abs: hgsep
367 # rel: ossep
367 # rel: ossep
368 srcs.append((abs, rel, exact))
368 srcs.append((abs, rel, exact))
369 return srcs
369 return srcs
370
370
371 # abssrc: hgsep
371 # abssrc: hgsep
372 # relsrc: ossep
372 # relsrc: ossep
373 # otarget: ossep
373 # otarget: ossep
374 def copyfile(abssrc, relsrc, otarget, exact):
374 def copyfile(abssrc, relsrc, otarget, exact):
375 abstarget = util.canonpath(repo.root, cwd, otarget)
375 abstarget = util.canonpath(repo.root, cwd, otarget)
376 reltarget = repo.pathto(abstarget, cwd)
376 reltarget = repo.pathto(abstarget, cwd)
377 target = repo.wjoin(abstarget)
377 target = repo.wjoin(abstarget)
378 src = repo.wjoin(abssrc)
378 src = repo.wjoin(abssrc)
379 state = repo.dirstate[abstarget]
379 state = repo.dirstate[abstarget]
380
380
381 # check for collisions
381 # check for collisions
382 prevsrc = targets.get(abstarget)
382 prevsrc = targets.get(abstarget)
383 if prevsrc is not None:
383 if prevsrc is not None:
384 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
384 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
385 (reltarget, repo.pathto(abssrc, cwd),
385 (reltarget, repo.pathto(abssrc, cwd),
386 repo.pathto(prevsrc, cwd)))
386 repo.pathto(prevsrc, cwd)))
387 return
387 return
388
388
389 # check for overwrites
389 # check for overwrites
390 exists = os.path.exists(target)
390 exists = os.path.exists(target)
391 if not after and exists or after and state in 'mn':
391 if not after and exists or after and state in 'mn':
392 if not opts['force']:
392 if not opts['force']:
393 ui.warn(_('%s: not overwriting - file exists\n') %
393 ui.warn(_('%s: not overwriting - file exists\n') %
394 reltarget)
394 reltarget)
395 return
395 return
396
396
397 if after:
397 if after:
398 if not exists:
398 if not exists:
399 return
399 return
400 elif not dryrun:
400 elif not dryrun:
401 try:
401 try:
402 if exists:
402 if exists:
403 os.unlink(target)
403 os.unlink(target)
404 targetdir = os.path.dirname(target) or '.'
404 targetdir = os.path.dirname(target) or '.'
405 if not os.path.isdir(targetdir):
405 if not os.path.isdir(targetdir):
406 os.makedirs(targetdir)
406 os.makedirs(targetdir)
407 util.copyfile(src, target)
407 util.copyfile(src, target)
408 except IOError, inst:
408 except IOError, inst:
409 if inst.errno == errno.ENOENT:
409 if inst.errno == errno.ENOENT:
410 ui.warn(_('%s: deleted in working copy\n') % relsrc)
410 ui.warn(_('%s: deleted in working copy\n') % relsrc)
411 else:
411 else:
412 ui.warn(_('%s: cannot copy - %s\n') %
412 ui.warn(_('%s: cannot copy - %s\n') %
413 (relsrc, inst.strerror))
413 (relsrc, inst.strerror))
414 return True # report a failure
414 return True # report a failure
415
415
416 if ui.verbose or not exact:
416 if ui.verbose or not exact:
417 if rename:
417 if rename:
418 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
418 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
419 else:
419 else:
420 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
420 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
421
421
422 targets[abstarget] = abssrc
422 targets[abstarget] = abssrc
423
423
424 # fix up dirstate
424 # fix up dirstate
425 origsrc = repo.dirstate.copied(abssrc) or abssrc
425 origsrc = repo.dirstate.copied(abssrc) or abssrc
426 if abstarget == origsrc: # copying back a copy?
426 if abstarget == origsrc: # copying back a copy?
427 if state not in 'mn' and not dryrun:
427 if state not in 'mn' and not dryrun:
428 repo.dirstate.normallookup(abstarget)
428 repo.dirstate.normallookup(abstarget)
429 else:
429 else:
430 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
430 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
431 if not ui.quiet:
431 if not ui.quiet:
432 ui.warn(_("%s has not been committed yet, so no copy "
432 ui.warn(_("%s has not been committed yet, so no copy "
433 "data will be stored for %s.\n")
433 "data will be stored for %s.\n")
434 % (repo.pathto(origsrc, cwd), reltarget))
434 % (repo.pathto(origsrc, cwd), reltarget))
435 if repo.dirstate[abstarget] in '?r' and not dryrun:
435 if repo.dirstate[abstarget] in '?r' and not dryrun:
436 repo.add([abstarget])
436 repo.add([abstarget])
437 elif not dryrun:
437 elif not dryrun:
438 repo.copy(origsrc, abstarget)
438 repo.copy(origsrc, abstarget)
439
439
440 if rename and not dryrun:
440 if rename and not dryrun:
441 repo.remove([abssrc], not after)
441 repo.remove([abssrc], not after)
442
442
443 # pat: ossep
443 # pat: ossep
444 # dest ossep
444 # dest ossep
445 # srcs: list of (hgsep, hgsep, ossep, bool)
445 # srcs: list of (hgsep, hgsep, ossep, bool)
446 # return: function that takes hgsep and returns ossep
446 # return: function that takes hgsep and returns ossep
447 def targetpathfn(pat, dest, srcs):
447 def targetpathfn(pat, dest, srcs):
448 if os.path.isdir(pat):
448 if os.path.isdir(pat):
449 abspfx = util.canonpath(repo.root, cwd, pat)
449 abspfx = util.canonpath(repo.root, cwd, pat)
450 abspfx = util.localpath(abspfx)
450 abspfx = util.localpath(abspfx)
451 if destdirexists:
451 if destdirexists:
452 striplen = len(os.path.split(abspfx)[0])
452 striplen = len(os.path.split(abspfx)[0])
453 else:
453 else:
454 striplen = len(abspfx)
454 striplen = len(abspfx)
455 if striplen:
455 if striplen:
456 striplen += len(os.sep)
456 striplen += len(os.sep)
457 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
457 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
458 elif destdirexists:
458 elif destdirexists:
459 res = lambda p: os.path.join(dest,
459 res = lambda p: os.path.join(dest,
460 os.path.basename(util.localpath(p)))
460 os.path.basename(util.localpath(p)))
461 else:
461 else:
462 res = lambda p: dest
462 res = lambda p: dest
463 return res
463 return res
464
464
465 # pat: ossep
465 # pat: ossep
466 # dest ossep
466 # dest ossep
467 # srcs: list of (hgsep, hgsep, ossep, bool)
467 # srcs: list of (hgsep, hgsep, ossep, bool)
468 # return: function that takes hgsep and returns ossep
468 # return: function that takes hgsep and returns ossep
469 def targetpathafterfn(pat, dest, srcs):
469 def targetpathafterfn(pat, dest, srcs):
470 if _match.patkind(pat):
470 if _match.patkind(pat):
471 # a mercurial pattern
471 # a mercurial pattern
472 res = lambda p: os.path.join(dest,
472 res = lambda p: os.path.join(dest,
473 os.path.basename(util.localpath(p)))
473 os.path.basename(util.localpath(p)))
474 else:
474 else:
475 abspfx = util.canonpath(repo.root, cwd, pat)
475 abspfx = util.canonpath(repo.root, cwd, pat)
476 if len(abspfx) < len(srcs[0][0]):
476 if len(abspfx) < len(srcs[0][0]):
477 # A directory. Either the target path contains the last
477 # A directory. Either the target path contains the last
478 # component of the source path or it does not.
478 # component of the source path or it does not.
479 def evalpath(striplen):
479 def evalpath(striplen):
480 score = 0
480 score = 0
481 for s in srcs:
481 for s in srcs:
482 t = os.path.join(dest, util.localpath(s[0])[striplen:])
482 t = os.path.join(dest, util.localpath(s[0])[striplen:])
483 if os.path.exists(t):
483 if os.path.exists(t):
484 score += 1
484 score += 1
485 return score
485 return score
486
486
487 abspfx = util.localpath(abspfx)
487 abspfx = util.localpath(abspfx)
488 striplen = len(abspfx)
488 striplen = len(abspfx)
489 if striplen:
489 if striplen:
490 striplen += len(os.sep)
490 striplen += len(os.sep)
491 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
491 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
492 score = evalpath(striplen)
492 score = evalpath(striplen)
493 striplen1 = len(os.path.split(abspfx)[0])
493 striplen1 = len(os.path.split(abspfx)[0])
494 if striplen1:
494 if striplen1:
495 striplen1 += len(os.sep)
495 striplen1 += len(os.sep)
496 if evalpath(striplen1) > score:
496 if evalpath(striplen1) > score:
497 striplen = striplen1
497 striplen = striplen1
498 res = lambda p: os.path.join(dest,
498 res = lambda p: os.path.join(dest,
499 util.localpath(p)[striplen:])
499 util.localpath(p)[striplen:])
500 else:
500 else:
501 # a file
501 # a file
502 if destdirexists:
502 if destdirexists:
503 res = lambda p: os.path.join(dest,
503 res = lambda p: os.path.join(dest,
504 os.path.basename(util.localpath(p)))
504 os.path.basename(util.localpath(p)))
505 else:
505 else:
506 res = lambda p: dest
506 res = lambda p: dest
507 return res
507 return res
508
508
509
509
510 pats = expandpats(pats)
510 pats = expandpats(pats)
511 if not pats:
511 if not pats:
512 raise util.Abort(_('no source or destination specified'))
512 raise util.Abort(_('no source or destination specified'))
513 if len(pats) == 1:
513 if len(pats) == 1:
514 raise util.Abort(_('no destination specified'))
514 raise util.Abort(_('no destination specified'))
515 dest = pats.pop()
515 dest = pats.pop()
516 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
516 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
517 if not destdirexists:
517 if not destdirexists:
518 if len(pats) > 1 or _match.patkind(pats[0]):
518 if len(pats) > 1 or _match.patkind(pats[0]):
519 raise util.Abort(_('with multiple sources, destination must be an '
519 raise util.Abort(_('with multiple sources, destination must be an '
520 'existing directory'))
520 'existing directory'))
521 if util.endswithsep(dest):
521 if util.endswithsep(dest):
522 raise util.Abort(_('destination %s is not a directory') % dest)
522 raise util.Abort(_('destination %s is not a directory') % dest)
523
523
524 tfn = targetpathfn
524 tfn = targetpathfn
525 if after:
525 if after:
526 tfn = targetpathafterfn
526 tfn = targetpathafterfn
527 copylist = []
527 copylist = []
528 for pat in pats:
528 for pat in pats:
529 srcs = walkpat(pat)
529 srcs = walkpat(pat)
530 if not srcs:
530 if not srcs:
531 continue
531 continue
532 copylist.append((tfn(pat, dest, srcs), srcs))
532 copylist.append((tfn(pat, dest, srcs), srcs))
533 if not copylist:
533 if not copylist:
534 raise util.Abort(_('no files to copy'))
534 raise util.Abort(_('no files to copy'))
535
535
536 errors = 0
536 errors = 0
537 for targetpath, srcs in copylist:
537 for targetpath, srcs in copylist:
538 for abssrc, relsrc, exact in srcs:
538 for abssrc, relsrc, exact in srcs:
539 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
539 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
540 errors += 1
540 errors += 1
541
541
542 if errors:
542 if errors:
543 ui.warn(_('(consider using --after)\n'))
543 ui.warn(_('(consider using --after)\n'))
544
544
545 return errors
545 return errors
546
546
547 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
547 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
548 runargs=None, appendpid=False):
548 runargs=None, appendpid=False):
549 '''Run a command as a service.'''
549 '''Run a command as a service.'''
550
550
551 if opts['daemon'] and not opts['daemon_pipefds']:
551 if opts['daemon'] and not opts['daemon_pipefds']:
552 # Signal child process startup with file removal
552 # Signal child process startup with file removal
553 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
553 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
554 os.close(lockfd)
554 os.close(lockfd)
555 try:
555 try:
556 if not runargs:
556 if not runargs:
557 runargs = util.hgcmd() + sys.argv[1:]
557 runargs = util.hgcmd() + sys.argv[1:]
558 runargs.append('--daemon-pipefds=%s' % lockpath)
558 runargs.append('--daemon-pipefds=%s' % lockpath)
559 # Don't pass --cwd to the child process, because we've already
559 # Don't pass --cwd to the child process, because we've already
560 # changed directory.
560 # changed directory.
561 for i in xrange(1, len(runargs)):
561 for i in xrange(1, len(runargs)):
562 if runargs[i].startswith('--cwd='):
562 if runargs[i].startswith('--cwd='):
563 del runargs[i]
563 del runargs[i]
564 break
564 break
565 elif runargs[i].startswith('--cwd'):
565 elif runargs[i].startswith('--cwd'):
566 del runargs[i:i + 2]
566 del runargs[i:i + 2]
567 break
567 break
568 def condfn():
568 def condfn():
569 return not os.path.exists(lockpath)
569 return not os.path.exists(lockpath)
570 pid = util.rundetached(runargs, condfn)
570 pid = util.rundetached(runargs, condfn)
571 if pid < 0:
571 if pid < 0:
572 raise util.Abort(_('child process failed to start'))
572 raise util.Abort(_('child process failed to start'))
573 finally:
573 finally:
574 try:
574 try:
575 os.unlink(lockpath)
575 os.unlink(lockpath)
576 except OSError, e:
576 except OSError, e:
577 if e.errno != errno.ENOENT:
577 if e.errno != errno.ENOENT:
578 raise
578 raise
579 if parentfn:
579 if parentfn:
580 return parentfn(pid)
580 return parentfn(pid)
581 else:
581 else:
582 return
582 return
583
583
584 if initfn:
584 if initfn:
585 initfn()
585 initfn()
586
586
587 if opts['pid_file']:
587 if opts['pid_file']:
588 mode = appendpid and 'a' or 'w'
588 mode = appendpid and 'a' or 'w'
589 fp = open(opts['pid_file'], mode)
589 fp = open(opts['pid_file'], mode)
590 fp.write(str(os.getpid()) + '\n')
590 fp.write(str(os.getpid()) + '\n')
591 fp.close()
591 fp.close()
592
592
593 if opts['daemon_pipefds']:
593 if opts['daemon_pipefds']:
594 lockpath = opts['daemon_pipefds']
594 lockpath = opts['daemon_pipefds']
595 try:
595 try:
596 os.setsid()
596 os.setsid()
597 except AttributeError:
597 except AttributeError:
598 pass
598 pass
599 os.unlink(lockpath)
599 os.unlink(lockpath)
600 util.hidewindow()
600 util.hidewindow()
601 sys.stdout.flush()
601 sys.stdout.flush()
602 sys.stderr.flush()
602 sys.stderr.flush()
603
603
604 nullfd = os.open(util.nulldev, os.O_RDWR)
604 nullfd = os.open(util.nulldev, os.O_RDWR)
605 logfilefd = nullfd
605 logfilefd = nullfd
606 if logfile:
606 if logfile:
607 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
607 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
608 os.dup2(nullfd, 0)
608 os.dup2(nullfd, 0)
609 os.dup2(logfilefd, 1)
609 os.dup2(logfilefd, 1)
610 os.dup2(logfilefd, 2)
610 os.dup2(logfilefd, 2)
611 if nullfd not in (0, 1, 2):
611 if nullfd not in (0, 1, 2):
612 os.close(nullfd)
612 os.close(nullfd)
613 if logfile and logfilefd not in (0, 1, 2):
613 if logfile and logfilefd not in (0, 1, 2):
614 os.close(logfilefd)
614 os.close(logfilefd)
615
615
616 if runfn:
616 if runfn:
617 return runfn()
617 return runfn()
618
618
619 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
619 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
620 opts=None):
620 opts=None):
621 '''export changesets as hg patches.'''
621 '''export changesets as hg patches.'''
622
622
623 total = len(revs)
623 total = len(revs)
624 revwidth = max([len(str(rev)) for rev in revs])
624 revwidth = max([len(str(rev)) for rev in revs])
625
625
626 def single(rev, seqno, fp):
626 def single(rev, seqno, fp):
627 ctx = repo[rev]
627 ctx = repo[rev]
628 node = ctx.node()
628 node = ctx.node()
629 parents = [p.node() for p in ctx.parents() if p]
629 parents = [p.node() for p in ctx.parents() if p]
630 branch = ctx.branch()
630 branch = ctx.branch()
631 if switch_parent:
631 if switch_parent:
632 parents.reverse()
632 parents.reverse()
633 prev = (parents and parents[0]) or nullid
633 prev = (parents and parents[0]) or nullid
634
634
635 if not fp:
635 if not fp:
636 fp = make_file(repo, template, node, total=total, seqno=seqno,
636 fp = make_file(repo, template, node, total=total, seqno=seqno,
637 revwidth=revwidth, mode='ab')
637 revwidth=revwidth, mode='ab')
638 if fp != sys.stdout and hasattr(fp, 'name'):
638 if fp != sys.stdout and hasattr(fp, 'name'):
639 repo.ui.note("%s\n" % fp.name)
639 repo.ui.note("%s\n" % fp.name)
640
640
641 fp.write("# HG changeset patch\n")
641 fp.write("# HG changeset patch\n")
642 fp.write("# User %s\n" % ctx.user())
642 fp.write("# User %s\n" % ctx.user())
643 fp.write("# Date %d %d\n" % ctx.date())
643 fp.write("# Date %d %d\n" % ctx.date())
644 if branch and (branch != 'default'):
644 if branch and (branch != 'default'):
645 fp.write("# Branch %s\n" % branch)
645 fp.write("# Branch %s\n" % branch)
646 fp.write("# Node ID %s\n" % hex(node))
646 fp.write("# Node ID %s\n" % hex(node))
647 fp.write("# Parent %s\n" % hex(prev))
647 fp.write("# Parent %s\n" % hex(prev))
648 if len(parents) > 1:
648 if len(parents) > 1:
649 fp.write("# Parent %s\n" % hex(parents[1]))
649 fp.write("# Parent %s\n" % hex(parents[1]))
650 fp.write(ctx.description().rstrip())
650 fp.write(ctx.description().rstrip())
651 fp.write("\n\n")
651 fp.write("\n\n")
652
652
653 for chunk in patch.diff(repo, prev, node, opts=opts):
653 for chunk in patch.diff(repo, prev, node, opts=opts):
654 fp.write(chunk)
654 fp.write(chunk)
655
655
656 for seqno, rev in enumerate(revs):
656 for seqno, rev in enumerate(revs):
657 single(rev, seqno + 1, fp)
657 single(rev, seqno + 1, fp)
658
658
659 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
659 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
660 changes=None, stat=False, fp=None):
660 changes=None, stat=False, fp=None):
661 '''show diff or diffstat.'''
661 '''show diff or diffstat.'''
662 if fp is None:
662 if fp is None:
663 write = ui.write
663 write = ui.write
664 else:
664 else:
665 def write(s, **kw):
665 def write(s, **kw):
666 fp.write(s)
666 fp.write(s)
667
667
668 if stat:
668 if stat:
669 diffopts.context = 0
669 diffopts.context = 0
670 width = 80
670 width = 80
671 if not ui.plain():
671 if not ui.plain():
672 width = util.termwidth()
672 width = util.termwidth()
673 chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
673 chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
674 for chunk, label in patch.diffstatui(util.iterlines(chunks),
674 for chunk, label in patch.diffstatui(util.iterlines(chunks),
675 width=width,
675 width=width,
676 git=diffopts.git):
676 git=diffopts.git):
677 write(chunk, label=label)
677 write(chunk, label=label)
678 else:
678 else:
679 for chunk, label in patch.diffui(repo, node1, node2, match,
679 for chunk, label in patch.diffui(repo, node1, node2, match,
680 changes, diffopts):
680 changes, diffopts):
681 write(chunk, label=label)
681 write(chunk, label=label)
682
682
683 class changeset_printer(object):
683 class changeset_printer(object):
684 '''show changeset information when templating not requested.'''
684 '''show changeset information when templating not requested.'''
685
685
686 def __init__(self, ui, repo, patch, diffopts, buffered):
686 def __init__(self, ui, repo, patch, diffopts, buffered):
687 self.ui = ui
687 self.ui = ui
688 self.repo = repo
688 self.repo = repo
689 self.buffered = buffered
689 self.buffered = buffered
690 self.patch = patch
690 self.patch = patch
691 self.diffopts = diffopts
691 self.diffopts = diffopts
692 self.header = {}
692 self.header = {}
693 self.hunk = {}
693 self.hunk = {}
694 self.lastheader = None
694 self.lastheader = None
695 self.footer = None
695 self.footer = None
696
696
697 def flush(self, rev):
697 def flush(self, rev):
698 if rev in self.header:
698 if rev in self.header:
699 h = self.header[rev]
699 h = self.header[rev]
700 if h != self.lastheader:
700 if h != self.lastheader:
701 self.lastheader = h
701 self.lastheader = h
702 self.ui.write(h)
702 self.ui.write(h)
703 del self.header[rev]
703 del self.header[rev]
704 if rev in self.hunk:
704 if rev in self.hunk:
705 self.ui.write(self.hunk[rev])
705 self.ui.write(self.hunk[rev])
706 del self.hunk[rev]
706 del self.hunk[rev]
707 return 1
707 return 1
708 return 0
708 return 0
709
709
710 def close(self):
710 def close(self):
711 if self.footer:
711 if self.footer:
712 self.ui.write(self.footer)
712 self.ui.write(self.footer)
713
713
714 def show(self, ctx, copies=None, **props):
714 def show(self, ctx, copies=None, **props):
715 if self.buffered:
715 if self.buffered:
716 self.ui.pushbuffer()
716 self.ui.pushbuffer()
717 self._show(ctx, copies, props)
717 self._show(ctx, copies, props)
718 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
718 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
719 else:
719 else:
720 self._show(ctx, copies, props)
720 self._show(ctx, copies, props)
721
721
722 def _show(self, ctx, copies, props):
722 def _show(self, ctx, copies, props):
723 '''show a single changeset or file revision'''
723 '''show a single changeset or file revision'''
724 changenode = ctx.node()
724 changenode = ctx.node()
725 rev = ctx.rev()
725 rev = ctx.rev()
726
726
727 if self.ui.quiet:
727 if self.ui.quiet:
728 self.ui.write("%d:%s\n" % (rev, short(changenode)),
728 self.ui.write("%d:%s\n" % (rev, short(changenode)),
729 label='log.node')
729 label='log.node')
730 return
730 return
731
731
732 log = self.repo.changelog
732 log = self.repo.changelog
733 date = util.datestr(ctx.date())
733 date = util.datestr(ctx.date())
734
734
735 hexfunc = self.ui.debugflag and hex or short
735 hexfunc = self.ui.debugflag and hex or short
736
736
737 parents = [(p, hexfunc(log.node(p)))
737 parents = [(p, hexfunc(log.node(p)))
738 for p in self._meaningful_parentrevs(log, rev)]
738 for p in self._meaningful_parentrevs(log, rev)]
739
739
740 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
740 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
741 label='log.changeset')
741 label='log.changeset')
742
742
743 branch = ctx.branch()
743 branch = ctx.branch()
744 # don't show the default branch name
744 # don't show the default branch name
745 if branch != 'default':
745 if branch != 'default':
746 branch = encoding.tolocal(branch)
746 branch = encoding.tolocal(branch)
747 self.ui.write(_("branch: %s\n") % branch,
747 self.ui.write(_("branch: %s\n") % branch,
748 label='log.branch')
748 label='log.branch')
749 for tag in self.repo.nodetags(changenode):
749 for tag in self.repo.nodetags(changenode):
750 self.ui.write(_("tag: %s\n") % tag,
750 self.ui.write(_("tag: %s\n") % tag,
751 label='log.tag')
751 label='log.tag')
752 for parent in parents:
752 for parent in parents:
753 self.ui.write(_("parent: %d:%s\n") % parent,
753 self.ui.write(_("parent: %d:%s\n") % parent,
754 label='log.parent')
754 label='log.parent')
755
755
756 if self.ui.debugflag:
756 if self.ui.debugflag:
757 mnode = ctx.manifestnode()
757 mnode = ctx.manifestnode()
758 self.ui.write(_("manifest: %d:%s\n") %
758 self.ui.write(_("manifest: %d:%s\n") %
759 (self.repo.manifest.rev(mnode), hex(mnode)),
759 (self.repo.manifest.rev(mnode), hex(mnode)),
760 label='ui.debug log.manifest')
760 label='ui.debug log.manifest')
761 self.ui.write(_("user: %s\n") % ctx.user(),
761 self.ui.write(_("user: %s\n") % ctx.user(),
762 label='log.user')
762 label='log.user')
763 self.ui.write(_("date: %s\n") % date,
763 self.ui.write(_("date: %s\n") % date,
764 label='log.date')
764 label='log.date')
765
765
766 if self.ui.debugflag:
766 if self.ui.debugflag:
767 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
767 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
768 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
768 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
769 files):
769 files):
770 if value:
770 if value:
771 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
771 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
772 label='ui.debug log.files')
772 label='ui.debug log.files')
773 elif ctx.files() and self.ui.verbose:
773 elif ctx.files() and self.ui.verbose:
774 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
774 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
775 label='ui.note log.files')
775 label='ui.note log.files')
776 if copies and self.ui.verbose:
776 if copies and self.ui.verbose:
777 copies = ['%s (%s)' % c for c in copies]
777 copies = ['%s (%s)' % c for c in copies]
778 self.ui.write(_("copies: %s\n") % ' '.join(copies),
778 self.ui.write(_("copies: %s\n") % ' '.join(copies),
779 label='ui.note log.copies')
779 label='ui.note log.copies')
780
780
781 extra = ctx.extra()
781 extra = ctx.extra()
782 if extra and self.ui.debugflag:
782 if extra and self.ui.debugflag:
783 for key, value in sorted(extra.items()):
783 for key, value in sorted(extra.items()):
784 self.ui.write(_("extra: %s=%s\n")
784 self.ui.write(_("extra: %s=%s\n")
785 % (key, value.encode('string_escape')),
785 % (key, value.encode('string_escape')),
786 label='ui.debug log.extra')
786 label='ui.debug log.extra')
787
787
788 description = ctx.description().strip()
788 description = ctx.description().strip()
789 if description:
789 if description:
790 if self.ui.verbose:
790 if self.ui.verbose:
791 self.ui.write(_("description:\n"),
791 self.ui.write(_("description:\n"),
792 label='ui.note log.description')
792 label='ui.note log.description')
793 self.ui.write(description,
793 self.ui.write(description,
794 label='ui.note log.description')
794 label='ui.note log.description')
795 self.ui.write("\n\n")
795 self.ui.write("\n\n")
796 else:
796 else:
797 self.ui.write(_("summary: %s\n") %
797 self.ui.write(_("summary: %s\n") %
798 description.splitlines()[0],
798 description.splitlines()[0],
799 label='log.summary')
799 label='log.summary')
800 self.ui.write("\n")
800 self.ui.write("\n")
801
801
802 self.showpatch(changenode)
802 self.showpatch(changenode)
803
803
804 def showpatch(self, node):
804 def showpatch(self, node):
805 if self.patch:
805 if self.patch:
806 stat = self.diffopts.get('stat')
807 diffopts = patch.diffopts(self.ui, self.diffopts)
806 prev = self.repo.changelog.parents(node)[0]
808 prev = self.repo.changelog.parents(node)[0]
807 chunks = patch.diffui(self.repo, prev, node, match=self.patch,
809 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
808 opts=patch.diffopts(self.ui, self.diffopts))
810 match=self.patch, stat=stat)
809 for chunk, label in chunks:
810 self.ui.write(chunk, label=label)
811 self.ui.write("\n")
811 self.ui.write("\n")
812
812
813 def _meaningful_parentrevs(self, log, rev):
813 def _meaningful_parentrevs(self, log, rev):
814 """Return list of meaningful (or all if debug) parentrevs for rev.
814 """Return list of meaningful (or all if debug) parentrevs for rev.
815
815
816 For merges (two non-nullrev revisions) both parents are meaningful.
816 For merges (two non-nullrev revisions) both parents are meaningful.
817 Otherwise the first parent revision is considered meaningful if it
817 Otherwise the first parent revision is considered meaningful if it
818 is not the preceding revision.
818 is not the preceding revision.
819 """
819 """
820 parents = log.parentrevs(rev)
820 parents = log.parentrevs(rev)
821 if not self.ui.debugflag and parents[1] == nullrev:
821 if not self.ui.debugflag and parents[1] == nullrev:
822 if parents[0] >= rev - 1:
822 if parents[0] >= rev - 1:
823 parents = []
823 parents = []
824 else:
824 else:
825 parents = [parents[0]]
825 parents = [parents[0]]
826 return parents
826 return parents
827
827
828
828
829 class changeset_templater(changeset_printer):
829 class changeset_templater(changeset_printer):
830 '''format changeset information.'''
830 '''format changeset information.'''
831
831
832 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
832 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
833 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
833 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
834 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
834 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
835 defaulttempl = {
835 defaulttempl = {
836 'parent': '{rev}:{node|formatnode} ',
836 'parent': '{rev}:{node|formatnode} ',
837 'manifest': '{rev}:{node|formatnode}',
837 'manifest': '{rev}:{node|formatnode}',
838 'file_copy': '{name} ({source})',
838 'file_copy': '{name} ({source})',
839 'extra': '{key}={value|stringescape}'
839 'extra': '{key}={value|stringescape}'
840 }
840 }
841 # filecopy is preserved for compatibility reasons
841 # filecopy is preserved for compatibility reasons
842 defaulttempl['filecopy'] = defaulttempl['file_copy']
842 defaulttempl['filecopy'] = defaulttempl['file_copy']
843 self.t = templater.templater(mapfile, {'formatnode': formatnode},
843 self.t = templater.templater(mapfile, {'formatnode': formatnode},
844 cache=defaulttempl)
844 cache=defaulttempl)
845 self.cache = {}
845 self.cache = {}
846
846
847 def use_template(self, t):
847 def use_template(self, t):
848 '''set template string to use'''
848 '''set template string to use'''
849 self.t.cache['changeset'] = t
849 self.t.cache['changeset'] = t
850
850
851 def _meaningful_parentrevs(self, ctx):
851 def _meaningful_parentrevs(self, ctx):
852 """Return list of meaningful (or all if debug) parentrevs for rev.
852 """Return list of meaningful (or all if debug) parentrevs for rev.
853 """
853 """
854 parents = ctx.parents()
854 parents = ctx.parents()
855 if len(parents) > 1:
855 if len(parents) > 1:
856 return parents
856 return parents
857 if self.ui.debugflag:
857 if self.ui.debugflag:
858 return [parents[0], self.repo['null']]
858 return [parents[0], self.repo['null']]
859 if parents[0].rev() >= ctx.rev() - 1:
859 if parents[0].rev() >= ctx.rev() - 1:
860 return []
860 return []
861 return parents
861 return parents
862
862
863 def _show(self, ctx, copies, props):
863 def _show(self, ctx, copies, props):
864 '''show a single changeset or file revision'''
864 '''show a single changeset or file revision'''
865
865
866 showlist = templatekw.showlist
866 showlist = templatekw.showlist
867
867
868 # showparents() behaviour depends on ui trace level which
868 # showparents() behaviour depends on ui trace level which
869 # causes unexpected behaviours at templating level and makes
869 # causes unexpected behaviours at templating level and makes
870 # it harder to extract it in a standalone function. Its
870 # it harder to extract it in a standalone function. Its
871 # behaviour cannot be changed so leave it here for now.
871 # behaviour cannot be changed so leave it here for now.
872 def showparents(**args):
872 def showparents(**args):
873 ctx = args['ctx']
873 ctx = args['ctx']
874 parents = [[('rev', p.rev()), ('node', p.hex())]
874 parents = [[('rev', p.rev()), ('node', p.hex())]
875 for p in self._meaningful_parentrevs(ctx)]
875 for p in self._meaningful_parentrevs(ctx)]
876 return showlist('parent', parents, **args)
876 return showlist('parent', parents, **args)
877
877
878 props = props.copy()
878 props = props.copy()
879 props.update(templatekw.keywords)
879 props.update(templatekw.keywords)
880 props['parents'] = showparents
880 props['parents'] = showparents
881 props['templ'] = self.t
881 props['templ'] = self.t
882 props['ctx'] = ctx
882 props['ctx'] = ctx
883 props['repo'] = self.repo
883 props['repo'] = self.repo
884 props['revcache'] = {'copies': copies}
884 props['revcache'] = {'copies': copies}
885 props['cache'] = self.cache
885 props['cache'] = self.cache
886
886
887 # find correct templates for current mode
887 # find correct templates for current mode
888
888
889 tmplmodes = [
889 tmplmodes = [
890 (True, None),
890 (True, None),
891 (self.ui.verbose, 'verbose'),
891 (self.ui.verbose, 'verbose'),
892 (self.ui.quiet, 'quiet'),
892 (self.ui.quiet, 'quiet'),
893 (self.ui.debugflag, 'debug'),
893 (self.ui.debugflag, 'debug'),
894 ]
894 ]
895
895
896 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
896 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
897 for mode, postfix in tmplmodes:
897 for mode, postfix in tmplmodes:
898 for type in types:
898 for type in types:
899 cur = postfix and ('%s_%s' % (type, postfix)) or type
899 cur = postfix and ('%s_%s' % (type, postfix)) or type
900 if mode and cur in self.t:
900 if mode and cur in self.t:
901 types[type] = cur
901 types[type] = cur
902
902
903 try:
903 try:
904
904
905 # write header
905 # write header
906 if types['header']:
906 if types['header']:
907 h = templater.stringify(self.t(types['header'], **props))
907 h = templater.stringify(self.t(types['header'], **props))
908 if self.buffered:
908 if self.buffered:
909 self.header[ctx.rev()] = h
909 self.header[ctx.rev()] = h
910 else:
910 else:
911 self.ui.write(h)
911 self.ui.write(h)
912
912
913 # write changeset metadata, then patch if requested
913 # write changeset metadata, then patch if requested
914 key = types['changeset']
914 key = types['changeset']
915 self.ui.write(templater.stringify(self.t(key, **props)))
915 self.ui.write(templater.stringify(self.t(key, **props)))
916 self.showpatch(ctx.node())
916 self.showpatch(ctx.node())
917
917
918 if types['footer']:
918 if types['footer']:
919 if not self.footer:
919 if not self.footer:
920 self.footer = templater.stringify(self.t(types['footer'],
920 self.footer = templater.stringify(self.t(types['footer'],
921 **props))
921 **props))
922
922
923 except KeyError, inst:
923 except KeyError, inst:
924 msg = _("%s: no key named '%s'")
924 msg = _("%s: no key named '%s'")
925 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
925 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
926 except SyntaxError, inst:
926 except SyntaxError, inst:
927 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
927 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
928
928
929 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
929 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
930 """show one changeset using template or regular display.
930 """show one changeset using template or regular display.
931
931
932 Display format will be the first non-empty hit of:
932 Display format will be the first non-empty hit of:
933 1. option 'template'
933 1. option 'template'
934 2. option 'style'
934 2. option 'style'
935 3. [ui] setting 'logtemplate'
935 3. [ui] setting 'logtemplate'
936 4. [ui] setting 'style'
936 4. [ui] setting 'style'
937 If all of these values are either the unset or the empty string,
937 If all of these values are either the unset or the empty string,
938 regular display via changeset_printer() is done.
938 regular display via changeset_printer() is done.
939 """
939 """
940 # options
940 # options
941 patch = False
941 patch = False
942 if opts.get('patch'):
942 if opts.get('patch') or opts.get('stat'):
943 patch = matchfn or matchall(repo)
943 patch = matchfn or matchall(repo)
944
944
945 tmpl = opts.get('template')
945 tmpl = opts.get('template')
946 style = None
946 style = None
947 if tmpl:
947 if tmpl:
948 tmpl = templater.parsestring(tmpl, quoted=False)
948 tmpl = templater.parsestring(tmpl, quoted=False)
949 else:
949 else:
950 style = opts.get('style')
950 style = opts.get('style')
951
951
952 # ui settings
952 # ui settings
953 if not (tmpl or style):
953 if not (tmpl or style):
954 tmpl = ui.config('ui', 'logtemplate')
954 tmpl = ui.config('ui', 'logtemplate')
955 if tmpl:
955 if tmpl:
956 tmpl = templater.parsestring(tmpl)
956 tmpl = templater.parsestring(tmpl)
957 else:
957 else:
958 style = util.expandpath(ui.config('ui', 'style', ''))
958 style = util.expandpath(ui.config('ui', 'style', ''))
959
959
960 if not (tmpl or style):
960 if not (tmpl or style):
961 return changeset_printer(ui, repo, patch, opts, buffered)
961 return changeset_printer(ui, repo, patch, opts, buffered)
962
962
963 mapfile = None
963 mapfile = None
964 if style and not tmpl:
964 if style and not tmpl:
965 mapfile = style
965 mapfile = style
966 if not os.path.split(mapfile)[0]:
966 if not os.path.split(mapfile)[0]:
967 mapname = (templater.templatepath('map-cmdline.' + mapfile)
967 mapname = (templater.templatepath('map-cmdline.' + mapfile)
968 or templater.templatepath(mapfile))
968 or templater.templatepath(mapfile))
969 if mapname:
969 if mapname:
970 mapfile = mapname
970 mapfile = mapname
971
971
972 try:
972 try:
973 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
973 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
974 except SyntaxError, inst:
974 except SyntaxError, inst:
975 raise util.Abort(inst.args[0])
975 raise util.Abort(inst.args[0])
976 if tmpl:
976 if tmpl:
977 t.use_template(tmpl)
977 t.use_template(tmpl)
978 return t
978 return t
979
979
980 def finddate(ui, repo, date):
980 def finddate(ui, repo, date):
981 """Find the tipmost changeset that matches the given date spec"""
981 """Find the tipmost changeset that matches the given date spec"""
982
982
983 df = util.matchdate(date)
983 df = util.matchdate(date)
984 m = matchall(repo)
984 m = matchall(repo)
985 results = {}
985 results = {}
986
986
987 def prep(ctx, fns):
987 def prep(ctx, fns):
988 d = ctx.date()
988 d = ctx.date()
989 if df(d[0]):
989 if df(d[0]):
990 results[ctx.rev()] = d
990 results[ctx.rev()] = d
991
991
992 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
992 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
993 rev = ctx.rev()
993 rev = ctx.rev()
994 if rev in results:
994 if rev in results:
995 ui.status(_("Found revision %s from %s\n") %
995 ui.status(_("Found revision %s from %s\n") %
996 (rev, util.datestr(results[rev])))
996 (rev, util.datestr(results[rev])))
997 return str(rev)
997 return str(rev)
998
998
999 raise util.Abort(_("revision matching date not found"))
999 raise util.Abort(_("revision matching date not found"))
1000
1000
1001 def walkchangerevs(repo, match, opts, prepare):
1001 def walkchangerevs(repo, match, opts, prepare):
1002 '''Iterate over files and the revs in which they changed.
1002 '''Iterate over files and the revs in which they changed.
1003
1003
1004 Callers most commonly need to iterate backwards over the history
1004 Callers most commonly need to iterate backwards over the history
1005 in which they are interested. Doing so has awful (quadratic-looking)
1005 in which they are interested. Doing so has awful (quadratic-looking)
1006 performance, so we use iterators in a "windowed" way.
1006 performance, so we use iterators in a "windowed" way.
1007
1007
1008 We walk a window of revisions in the desired order. Within the
1008 We walk a window of revisions in the desired order. Within the
1009 window, we first walk forwards to gather data, then in the desired
1009 window, we first walk forwards to gather data, then in the desired
1010 order (usually backwards) to display it.
1010 order (usually backwards) to display it.
1011
1011
1012 This function returns an iterator yielding contexts. Before
1012 This function returns an iterator yielding contexts. Before
1013 yielding each context, the iterator will first call the prepare
1013 yielding each context, the iterator will first call the prepare
1014 function on each context in the window in forward order.'''
1014 function on each context in the window in forward order.'''
1015
1015
1016 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1016 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1017 if start < end:
1017 if start < end:
1018 while start < end:
1018 while start < end:
1019 yield start, min(windowsize, end - start)
1019 yield start, min(windowsize, end - start)
1020 start += windowsize
1020 start += windowsize
1021 if windowsize < sizelimit:
1021 if windowsize < sizelimit:
1022 windowsize *= 2
1022 windowsize *= 2
1023 else:
1023 else:
1024 while start > end:
1024 while start > end:
1025 yield start, min(windowsize, start - end - 1)
1025 yield start, min(windowsize, start - end - 1)
1026 start -= windowsize
1026 start -= windowsize
1027 if windowsize < sizelimit:
1027 if windowsize < sizelimit:
1028 windowsize *= 2
1028 windowsize *= 2
1029
1029
1030 follow = opts.get('follow') or opts.get('follow_first')
1030 follow = opts.get('follow') or opts.get('follow_first')
1031
1031
1032 if not len(repo):
1032 if not len(repo):
1033 return []
1033 return []
1034
1034
1035 if follow:
1035 if follow:
1036 defrange = '%s:0' % repo['.'].rev()
1036 defrange = '%s:0' % repo['.'].rev()
1037 else:
1037 else:
1038 defrange = '-1:0'
1038 defrange = '-1:0'
1039 revs = revrange(repo, opts['rev'] or [defrange])
1039 revs = revrange(repo, opts['rev'] or [defrange])
1040 wanted = set()
1040 wanted = set()
1041 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1041 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1042 fncache = {}
1042 fncache = {}
1043 change = util.cachefunc(repo.changectx)
1043 change = util.cachefunc(repo.changectx)
1044
1044
1045 if not slowpath and not match.files():
1045 if not slowpath and not match.files():
1046 # No files, no patterns. Display all revs.
1046 # No files, no patterns. Display all revs.
1047 wanted = set(revs)
1047 wanted = set(revs)
1048 copies = []
1048 copies = []
1049
1049
1050 if not slowpath:
1050 if not slowpath:
1051 # Only files, no patterns. Check the history of each file.
1051 # Only files, no patterns. Check the history of each file.
1052 def filerevgen(filelog, node):
1052 def filerevgen(filelog, node):
1053 cl_count = len(repo)
1053 cl_count = len(repo)
1054 if node is None:
1054 if node is None:
1055 last = len(filelog) - 1
1055 last = len(filelog) - 1
1056 else:
1056 else:
1057 last = filelog.rev(node)
1057 last = filelog.rev(node)
1058 for i, window in increasing_windows(last, nullrev):
1058 for i, window in increasing_windows(last, nullrev):
1059 revs = []
1059 revs = []
1060 for j in xrange(i - window, i + 1):
1060 for j in xrange(i - window, i + 1):
1061 n = filelog.node(j)
1061 n = filelog.node(j)
1062 revs.append((filelog.linkrev(j),
1062 revs.append((filelog.linkrev(j),
1063 follow and filelog.renamed(n)))
1063 follow and filelog.renamed(n)))
1064 for rev in reversed(revs):
1064 for rev in reversed(revs):
1065 # only yield rev for which we have the changelog, it can
1065 # only yield rev for which we have the changelog, it can
1066 # happen while doing "hg log" during a pull or commit
1066 # happen while doing "hg log" during a pull or commit
1067 if rev[0] < cl_count:
1067 if rev[0] < cl_count:
1068 yield rev
1068 yield rev
1069 def iterfiles():
1069 def iterfiles():
1070 for filename in match.files():
1070 for filename in match.files():
1071 yield filename, None
1071 yield filename, None
1072 for filename_node in copies:
1072 for filename_node in copies:
1073 yield filename_node
1073 yield filename_node
1074 minrev, maxrev = min(revs), max(revs)
1074 minrev, maxrev = min(revs), max(revs)
1075 for file_, node in iterfiles():
1075 for file_, node in iterfiles():
1076 filelog = repo.file(file_)
1076 filelog = repo.file(file_)
1077 if not len(filelog):
1077 if not len(filelog):
1078 if node is None:
1078 if node is None:
1079 # A zero count may be a directory or deleted file, so
1079 # A zero count may be a directory or deleted file, so
1080 # try to find matching entries on the slow path.
1080 # try to find matching entries on the slow path.
1081 if follow:
1081 if follow:
1082 raise util.Abort(
1082 raise util.Abort(
1083 _('cannot follow nonexistent file: "%s"') % file_)
1083 _('cannot follow nonexistent file: "%s"') % file_)
1084 slowpath = True
1084 slowpath = True
1085 break
1085 break
1086 else:
1086 else:
1087 continue
1087 continue
1088 for rev, copied in filerevgen(filelog, node):
1088 for rev, copied in filerevgen(filelog, node):
1089 if rev <= maxrev:
1089 if rev <= maxrev:
1090 if rev < minrev:
1090 if rev < minrev:
1091 break
1091 break
1092 fncache.setdefault(rev, [])
1092 fncache.setdefault(rev, [])
1093 fncache[rev].append(file_)
1093 fncache[rev].append(file_)
1094 wanted.add(rev)
1094 wanted.add(rev)
1095 if copied:
1095 if copied:
1096 copies.append(copied)
1096 copies.append(copied)
1097 if slowpath:
1097 if slowpath:
1098 if follow:
1098 if follow:
1099 raise util.Abort(_('can only follow copies/renames for explicit '
1099 raise util.Abort(_('can only follow copies/renames for explicit '
1100 'filenames'))
1100 'filenames'))
1101
1101
1102 # The slow path checks files modified in every changeset.
1102 # The slow path checks files modified in every changeset.
1103 def changerevgen():
1103 def changerevgen():
1104 for i, window in increasing_windows(len(repo) - 1, nullrev):
1104 for i, window in increasing_windows(len(repo) - 1, nullrev):
1105 for j in xrange(i - window, i + 1):
1105 for j in xrange(i - window, i + 1):
1106 yield change(j)
1106 yield change(j)
1107
1107
1108 for ctx in changerevgen():
1108 for ctx in changerevgen():
1109 matches = filter(match, ctx.files())
1109 matches = filter(match, ctx.files())
1110 if matches:
1110 if matches:
1111 fncache[ctx.rev()] = matches
1111 fncache[ctx.rev()] = matches
1112 wanted.add(ctx.rev())
1112 wanted.add(ctx.rev())
1113
1113
1114 class followfilter(object):
1114 class followfilter(object):
1115 def __init__(self, onlyfirst=False):
1115 def __init__(self, onlyfirst=False):
1116 self.startrev = nullrev
1116 self.startrev = nullrev
1117 self.roots = set()
1117 self.roots = set()
1118 self.onlyfirst = onlyfirst
1118 self.onlyfirst = onlyfirst
1119
1119
1120 def match(self, rev):
1120 def match(self, rev):
1121 def realparents(rev):
1121 def realparents(rev):
1122 if self.onlyfirst:
1122 if self.onlyfirst:
1123 return repo.changelog.parentrevs(rev)[0:1]
1123 return repo.changelog.parentrevs(rev)[0:1]
1124 else:
1124 else:
1125 return filter(lambda x: x != nullrev,
1125 return filter(lambda x: x != nullrev,
1126 repo.changelog.parentrevs(rev))
1126 repo.changelog.parentrevs(rev))
1127
1127
1128 if self.startrev == nullrev:
1128 if self.startrev == nullrev:
1129 self.startrev = rev
1129 self.startrev = rev
1130 return True
1130 return True
1131
1131
1132 if rev > self.startrev:
1132 if rev > self.startrev:
1133 # forward: all descendants
1133 # forward: all descendants
1134 if not self.roots:
1134 if not self.roots:
1135 self.roots.add(self.startrev)
1135 self.roots.add(self.startrev)
1136 for parent in realparents(rev):
1136 for parent in realparents(rev):
1137 if parent in self.roots:
1137 if parent in self.roots:
1138 self.roots.add(rev)
1138 self.roots.add(rev)
1139 return True
1139 return True
1140 else:
1140 else:
1141 # backwards: all parents
1141 # backwards: all parents
1142 if not self.roots:
1142 if not self.roots:
1143 self.roots.update(realparents(self.startrev))
1143 self.roots.update(realparents(self.startrev))
1144 if rev in self.roots:
1144 if rev in self.roots:
1145 self.roots.remove(rev)
1145 self.roots.remove(rev)
1146 self.roots.update(realparents(rev))
1146 self.roots.update(realparents(rev))
1147 return True
1147 return True
1148
1148
1149 return False
1149 return False
1150
1150
1151 # it might be worthwhile to do this in the iterator if the rev range
1151 # it might be worthwhile to do this in the iterator if the rev range
1152 # is descending and the prune args are all within that range
1152 # is descending and the prune args are all within that range
1153 for rev in opts.get('prune', ()):
1153 for rev in opts.get('prune', ()):
1154 rev = repo.changelog.rev(repo.lookup(rev))
1154 rev = repo.changelog.rev(repo.lookup(rev))
1155 ff = followfilter()
1155 ff = followfilter()
1156 stop = min(revs[0], revs[-1])
1156 stop = min(revs[0], revs[-1])
1157 for x in xrange(rev, stop - 1, -1):
1157 for x in xrange(rev, stop - 1, -1):
1158 if ff.match(x):
1158 if ff.match(x):
1159 wanted.discard(x)
1159 wanted.discard(x)
1160
1160
1161 def iterate():
1161 def iterate():
1162 if follow and not match.files():
1162 if follow and not match.files():
1163 ff = followfilter(onlyfirst=opts.get('follow_first'))
1163 ff = followfilter(onlyfirst=opts.get('follow_first'))
1164 def want(rev):
1164 def want(rev):
1165 return ff.match(rev) and rev in wanted
1165 return ff.match(rev) and rev in wanted
1166 else:
1166 else:
1167 def want(rev):
1167 def want(rev):
1168 return rev in wanted
1168 return rev in wanted
1169
1169
1170 for i, window in increasing_windows(0, len(revs)):
1170 for i, window in increasing_windows(0, len(revs)):
1171 change = util.cachefunc(repo.changectx)
1171 change = util.cachefunc(repo.changectx)
1172 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1172 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1173 for rev in sorted(nrevs):
1173 for rev in sorted(nrevs):
1174 fns = fncache.get(rev)
1174 fns = fncache.get(rev)
1175 ctx = change(rev)
1175 ctx = change(rev)
1176 if not fns:
1176 if not fns:
1177 def fns_generator():
1177 def fns_generator():
1178 for f in ctx.files():
1178 for f in ctx.files():
1179 if match(f):
1179 if match(f):
1180 yield f
1180 yield f
1181 fns = fns_generator()
1181 fns = fns_generator()
1182 prepare(ctx, fns)
1182 prepare(ctx, fns)
1183 for rev in nrevs:
1183 for rev in nrevs:
1184 yield change(rev)
1184 yield change(rev)
1185 return iterate()
1185 return iterate()
1186
1186
1187 def commit(ui, repo, commitfunc, pats, opts):
1187 def commit(ui, repo, commitfunc, pats, opts):
1188 '''commit the specified files or all outstanding changes'''
1188 '''commit the specified files or all outstanding changes'''
1189 date = opts.get('date')
1189 date = opts.get('date')
1190 if date:
1190 if date:
1191 opts['date'] = util.parsedate(date)
1191 opts['date'] = util.parsedate(date)
1192 message = logmessage(opts)
1192 message = logmessage(opts)
1193
1193
1194 # extract addremove carefully -- this function can be called from a command
1194 # extract addremove carefully -- this function can be called from a command
1195 # that doesn't support addremove
1195 # that doesn't support addremove
1196 if opts.get('addremove'):
1196 if opts.get('addremove'):
1197 addremove(repo, pats, opts)
1197 addremove(repo, pats, opts)
1198
1198
1199 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1199 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1200
1200
1201 def commiteditor(repo, ctx, subs):
1201 def commiteditor(repo, ctx, subs):
1202 if ctx.description():
1202 if ctx.description():
1203 return ctx.description()
1203 return ctx.description()
1204 return commitforceeditor(repo, ctx, subs)
1204 return commitforceeditor(repo, ctx, subs)
1205
1205
1206 def commitforceeditor(repo, ctx, subs):
1206 def commitforceeditor(repo, ctx, subs):
1207 edittext = []
1207 edittext = []
1208 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1208 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1209 if ctx.description():
1209 if ctx.description():
1210 edittext.append(ctx.description())
1210 edittext.append(ctx.description())
1211 edittext.append("")
1211 edittext.append("")
1212 edittext.append("") # Empty line between message and comments.
1212 edittext.append("") # Empty line between message and comments.
1213 edittext.append(_("HG: Enter commit message."
1213 edittext.append(_("HG: Enter commit message."
1214 " Lines beginning with 'HG:' are removed."))
1214 " Lines beginning with 'HG:' are removed."))
1215 edittext.append(_("HG: Leave message empty to abort commit."))
1215 edittext.append(_("HG: Leave message empty to abort commit."))
1216 edittext.append("HG: --")
1216 edittext.append("HG: --")
1217 edittext.append(_("HG: user: %s") % ctx.user())
1217 edittext.append(_("HG: user: %s") % ctx.user())
1218 if ctx.p2():
1218 if ctx.p2():
1219 edittext.append(_("HG: branch merge"))
1219 edittext.append(_("HG: branch merge"))
1220 if ctx.branch():
1220 if ctx.branch():
1221 edittext.append(_("HG: branch '%s'")
1221 edittext.append(_("HG: branch '%s'")
1222 % encoding.tolocal(ctx.branch()))
1222 % encoding.tolocal(ctx.branch()))
1223 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1223 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1224 edittext.extend([_("HG: added %s") % f for f in added])
1224 edittext.extend([_("HG: added %s") % f for f in added])
1225 edittext.extend([_("HG: changed %s") % f for f in modified])
1225 edittext.extend([_("HG: changed %s") % f for f in modified])
1226 edittext.extend([_("HG: removed %s") % f for f in removed])
1226 edittext.extend([_("HG: removed %s") % f for f in removed])
1227 if not added and not modified and not removed:
1227 if not added and not modified and not removed:
1228 edittext.append(_("HG: no files changed"))
1228 edittext.append(_("HG: no files changed"))
1229 edittext.append("")
1229 edittext.append("")
1230 # run editor in the repository root
1230 # run editor in the repository root
1231 olddir = os.getcwd()
1231 olddir = os.getcwd()
1232 os.chdir(repo.root)
1232 os.chdir(repo.root)
1233 text = repo.ui.edit("\n".join(edittext), ctx.user())
1233 text = repo.ui.edit("\n".join(edittext), ctx.user())
1234 text = re.sub("(?m)^HG:.*\n", "", text)
1234 text = re.sub("(?m)^HG:.*\n", "", text)
1235 os.chdir(olddir)
1235 os.chdir(olddir)
1236
1236
1237 if not text.strip():
1237 if not text.strip():
1238 raise util.Abort(_("empty commit message"))
1238 raise util.Abort(_("empty commit message"))
1239
1239
1240 return text
1240 return text
@@ -1,3920 +1,3921 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for 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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, bundlerepo, extensions, copies, error
12 import hg, util, revlog, bundlerepo, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw
13 import patch, help, mdiff, url, encoding, templatekw
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst
16 import minirst
17
17
18 # Commands start here, listed alphabetically
18 # Commands start here, listed alphabetically
19
19
20 def add(ui, repo, *pats, **opts):
20 def add(ui, repo, *pats, **opts):
21 """add the specified files on the next commit
21 """add the specified files on the next commit
22
22
23 Schedule files to be version controlled and added to the
23 Schedule files to be version controlled and added to the
24 repository.
24 repository.
25
25
26 The files will be added to the repository at the next commit. To
26 The files will be added to the repository at the next commit. To
27 undo an add before that, see hg forget.
27 undo an add before that, see hg forget.
28
28
29 If no names are given, add all files to the repository.
29 If no names are given, add all files to the repository.
30
30
31 .. container:: verbose
31 .. container:: verbose
32
32
33 An example showing how new (unknown) files are added
33 An example showing how new (unknown) files are added
34 automatically by :hg:`add`::
34 automatically by :hg:`add`::
35
35
36 $ ls
36 $ ls
37 foo.c
37 foo.c
38 $ hg status
38 $ hg status
39 ? foo.c
39 ? foo.c
40 $ hg add
40 $ hg add
41 adding foo.c
41 adding foo.c
42 $ hg status
42 $ hg status
43 A foo.c
43 A foo.c
44 """
44 """
45
45
46 bad = []
46 bad = []
47 names = []
47 names = []
48 m = cmdutil.match(repo, pats, opts)
48 m = cmdutil.match(repo, pats, opts)
49 oldbad = m.bad
49 oldbad = m.bad
50 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
50 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
51
51
52 for f in repo.walk(m):
52 for f in repo.walk(m):
53 exact = m.exact(f)
53 exact = m.exact(f)
54 if exact or f not in repo.dirstate:
54 if exact or f not in repo.dirstate:
55 names.append(f)
55 names.append(f)
56 if ui.verbose or not exact:
56 if ui.verbose or not exact:
57 ui.status(_('adding %s\n') % m.rel(f))
57 ui.status(_('adding %s\n') % m.rel(f))
58 if not opts.get('dry_run'):
58 if not opts.get('dry_run'):
59 bad += [f for f in repo.add(names) if f in m.files()]
59 bad += [f for f in repo.add(names) if f in m.files()]
60 return bad and 1 or 0
60 return bad and 1 or 0
61
61
62 def addremove(ui, repo, *pats, **opts):
62 def addremove(ui, repo, *pats, **opts):
63 """add all new files, delete all missing files
63 """add all new files, delete all missing files
64
64
65 Add all new files and remove all missing files from the
65 Add all new files and remove all missing files from the
66 repository.
66 repository.
67
67
68 New files are ignored if they match any of the patterns in
68 New files are ignored if they match any of the patterns in
69 .hgignore. As with add, these changes take effect at the next
69 .hgignore. As with add, these changes take effect at the next
70 commit.
70 commit.
71
71
72 Use the -s/--similarity option to detect renamed files. With a
72 Use the -s/--similarity option to detect renamed files. With a
73 parameter greater than 0, this compares every removed file with
73 parameter greater than 0, this compares every removed file with
74 every added file and records those similar enough as renames. This
74 every added file and records those similar enough as renames. This
75 option takes a percentage between 0 (disabled) and 100 (files must
75 option takes a percentage between 0 (disabled) and 100 (files must
76 be identical) as its parameter. Detecting renamed files this way
76 be identical) as its parameter. Detecting renamed files this way
77 can be expensive.
77 can be expensive.
78 """
78 """
79 try:
79 try:
80 sim = float(opts.get('similarity') or 0)
80 sim = float(opts.get('similarity') or 0)
81 except ValueError:
81 except ValueError:
82 raise util.Abort(_('similarity must be a number'))
82 raise util.Abort(_('similarity must be a number'))
83 if sim < 0 or sim > 100:
83 if sim < 0 or sim > 100:
84 raise util.Abort(_('similarity must be between 0 and 100'))
84 raise util.Abort(_('similarity must be between 0 and 100'))
85 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
85 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
86
86
87 def annotate(ui, repo, *pats, **opts):
87 def annotate(ui, repo, *pats, **opts):
88 """show changeset information by line for each file
88 """show changeset information by line for each file
89
89
90 List changes in files, showing the revision id responsible for
90 List changes in files, showing the revision id responsible for
91 each line
91 each line
92
92
93 This command is useful for discovering when a change was made and
93 This command is useful for discovering when a change was made and
94 by whom.
94 by whom.
95
95
96 Without the -a/--text option, annotate will avoid processing files
96 Without the -a/--text option, annotate will avoid processing files
97 it detects as binary. With -a, annotate will annotate the file
97 it detects as binary. With -a, annotate will annotate the file
98 anyway, although the results will probably be neither useful
98 anyway, although the results will probably be neither useful
99 nor desirable.
99 nor desirable.
100 """
100 """
101 if opts.get('follow'):
101 if opts.get('follow'):
102 # --follow is deprecated and now just an alias for -f/--file
102 # --follow is deprecated and now just an alias for -f/--file
103 # to mimic the behavior of Mercurial before version 1.5
103 # to mimic the behavior of Mercurial before version 1.5
104 opts['file'] = 1
104 opts['file'] = 1
105
105
106 datefunc = ui.quiet and util.shortdate or util.datestr
106 datefunc = ui.quiet and util.shortdate or util.datestr
107 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
107 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
108
108
109 if not pats:
109 if not pats:
110 raise util.Abort(_('at least one filename or pattern is required'))
110 raise util.Abort(_('at least one filename or pattern is required'))
111
111
112 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
112 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
113 ('number', lambda x: str(x[0].rev())),
113 ('number', lambda x: str(x[0].rev())),
114 ('changeset', lambda x: short(x[0].node())),
114 ('changeset', lambda x: short(x[0].node())),
115 ('date', getdate),
115 ('date', getdate),
116 ('file', lambda x: x[0].path()),
116 ('file', lambda x: x[0].path()),
117 ]
117 ]
118
118
119 if (not opts.get('user') and not opts.get('changeset')
119 if (not opts.get('user') and not opts.get('changeset')
120 and not opts.get('date') and not opts.get('file')):
120 and not opts.get('date') and not opts.get('file')):
121 opts['number'] = 1
121 opts['number'] = 1
122
122
123 linenumber = opts.get('line_number') is not None
123 linenumber = opts.get('line_number') is not None
124 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
124 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
125 raise util.Abort(_('at least one of -n/-c is required for -l'))
125 raise util.Abort(_('at least one of -n/-c is required for -l'))
126
126
127 funcmap = [func for op, func in opmap if opts.get(op)]
127 funcmap = [func for op, func in opmap if opts.get(op)]
128 if linenumber:
128 if linenumber:
129 lastfunc = funcmap[-1]
129 lastfunc = funcmap[-1]
130 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
130 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
131
131
132 ctx = repo[opts.get('rev')]
132 ctx = repo[opts.get('rev')]
133 m = cmdutil.match(repo, pats, opts)
133 m = cmdutil.match(repo, pats, opts)
134 follow = not opts.get('no_follow')
134 follow = not opts.get('no_follow')
135 for abs in ctx.walk(m):
135 for abs in ctx.walk(m):
136 fctx = ctx[abs]
136 fctx = ctx[abs]
137 if not opts.get('text') and util.binary(fctx.data()):
137 if not opts.get('text') and util.binary(fctx.data()):
138 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
138 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
139 continue
139 continue
140
140
141 lines = fctx.annotate(follow=follow, linenumber=linenumber)
141 lines = fctx.annotate(follow=follow, linenumber=linenumber)
142 pieces = []
142 pieces = []
143
143
144 for f in funcmap:
144 for f in funcmap:
145 l = [f(n) for n, dummy in lines]
145 l = [f(n) for n, dummy in lines]
146 if l:
146 if l:
147 ml = max(map(len, l))
147 ml = max(map(len, l))
148 pieces.append(["%*s" % (ml, x) for x in l])
148 pieces.append(["%*s" % (ml, x) for x in l])
149
149
150 if pieces:
150 if pieces:
151 for p, l in zip(zip(*pieces), lines):
151 for p, l in zip(zip(*pieces), lines):
152 ui.write("%s: %s" % (" ".join(p), l[1]))
152 ui.write("%s: %s" % (" ".join(p), l[1]))
153
153
154 def archive(ui, repo, dest, **opts):
154 def archive(ui, repo, dest, **opts):
155 '''create an unversioned archive of a repository revision
155 '''create an unversioned archive of a repository revision
156
156
157 By default, the revision used is the parent of the working
157 By default, the revision used is the parent of the working
158 directory; use -r/--rev to specify a different revision.
158 directory; use -r/--rev to specify a different revision.
159
159
160 The archive type is automatically detected based on file
160 The archive type is automatically detected based on file
161 extension (or override using -t/--type).
161 extension (or override using -t/--type).
162
162
163 Valid types are:
163 Valid types are:
164
164
165 :``files``: a directory full of files (default)
165 :``files``: a directory full of files (default)
166 :``tar``: tar archive, uncompressed
166 :``tar``: tar archive, uncompressed
167 :``tbz2``: tar archive, compressed using bzip2
167 :``tbz2``: tar archive, compressed using bzip2
168 :``tgz``: tar archive, compressed using gzip
168 :``tgz``: tar archive, compressed using gzip
169 :``uzip``: zip archive, uncompressed
169 :``uzip``: zip archive, uncompressed
170 :``zip``: zip archive, compressed using deflate
170 :``zip``: zip archive, compressed using deflate
171
171
172 The exact name of the destination archive or directory is given
172 The exact name of the destination archive or directory is given
173 using a format string; see :hg:`help export` for details.
173 using a format string; see :hg:`help export` for details.
174
174
175 Each member added to an archive file has a directory prefix
175 Each member added to an archive file has a directory prefix
176 prepended. Use -p/--prefix to specify a format string for the
176 prepended. Use -p/--prefix to specify a format string for the
177 prefix. The default is the basename of the archive, with suffixes
177 prefix. The default is the basename of the archive, with suffixes
178 removed.
178 removed.
179 '''
179 '''
180
180
181 ctx = repo[opts.get('rev')]
181 ctx = repo[opts.get('rev')]
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 def guess_type():
189 def guess_type():
190 exttypes = {
190 exttypes = {
191 'tar': ['.tar'],
191 'tar': ['.tar'],
192 'tbz2': ['.tbz2', '.tar.bz2'],
192 'tbz2': ['.tbz2', '.tar.bz2'],
193 'tgz': ['.tgz', '.tar.gz'],
193 'tgz': ['.tgz', '.tar.gz'],
194 'zip': ['.zip'],
194 'zip': ['.zip'],
195 }
195 }
196
196
197 for type, extensions in exttypes.items():
197 for type, extensions in exttypes.items():
198 if util.any(dest.endswith(ext) for ext in extensions):
198 if util.any(dest.endswith(ext) for ext in extensions):
199 return type
199 return type
200 return None
200 return None
201
201
202 kind = opts.get('type') or guess_type() or 'files'
202 kind = opts.get('type') or guess_type() or 'files'
203 prefix = opts.get('prefix')
203 prefix = opts.get('prefix')
204
204
205 if dest == '-':
205 if dest == '-':
206 if kind == 'files':
206 if kind == 'files':
207 raise util.Abort(_('cannot archive plain files to stdout'))
207 raise util.Abort(_('cannot archive plain files to stdout'))
208 dest = sys.stdout
208 dest = sys.stdout
209 if not prefix:
209 if not prefix:
210 prefix = os.path.basename(repo.root) + '-%h'
210 prefix = os.path.basename(repo.root) + '-%h'
211
211
212 prefix = cmdutil.make_filename(repo, prefix, node)
212 prefix = cmdutil.make_filename(repo, prefix, node)
213 matchfn = cmdutil.match(repo, [], opts)
213 matchfn = cmdutil.match(repo, [], opts)
214 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
214 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
215 matchfn, prefix)
215 matchfn, prefix)
216
216
217 def backout(ui, repo, node=None, rev=None, **opts):
217 def backout(ui, repo, node=None, rev=None, **opts):
218 '''reverse effect of earlier changeset
218 '''reverse effect of earlier changeset
219
219
220 Commit the backed out changes as a new changeset. The new
220 Commit the backed out changes as a new changeset. The new
221 changeset is a child of the backed out changeset.
221 changeset is a child of the backed out changeset.
222
222
223 If you backout a changeset other than the tip, a new head is
223 If you backout a changeset other than the tip, a new head is
224 created. This head will be the new tip and you should merge this
224 created. This head will be the new tip and you should merge this
225 backout changeset with another head.
225 backout changeset with another head.
226
226
227 The --merge option remembers the parent of the working directory
227 The --merge option remembers the parent of the working directory
228 before starting the backout, then merges the new head with that
228 before starting the backout, then merges the new head with that
229 changeset afterwards. This saves you from doing the merge by hand.
229 changeset afterwards. This saves you from doing the merge by hand.
230 The result of this merge is not committed, as with a normal merge.
230 The result of this merge is not committed, as with a normal merge.
231
231
232 See :hg:`help dates` for a list of formats valid for -d/--date.
232 See :hg:`help dates` for a list of formats valid for -d/--date.
233 '''
233 '''
234 if rev and node:
234 if rev and node:
235 raise util.Abort(_("please specify just one revision"))
235 raise util.Abort(_("please specify just one revision"))
236
236
237 if not rev:
237 if not rev:
238 rev = node
238 rev = node
239
239
240 if not rev:
240 if not rev:
241 raise util.Abort(_("please specify a revision to backout"))
241 raise util.Abort(_("please specify a revision to backout"))
242
242
243 date = opts.get('date')
243 date = opts.get('date')
244 if date:
244 if date:
245 opts['date'] = util.parsedate(date)
245 opts['date'] = util.parsedate(date)
246
246
247 cmdutil.bail_if_changed(repo)
247 cmdutil.bail_if_changed(repo)
248 node = repo.lookup(rev)
248 node = repo.lookup(rev)
249
249
250 op1, op2 = repo.dirstate.parents()
250 op1, op2 = repo.dirstate.parents()
251 a = repo.changelog.ancestor(op1, node)
251 a = repo.changelog.ancestor(op1, node)
252 if a != node:
252 if a != node:
253 raise util.Abort(_('cannot backout change on a different branch'))
253 raise util.Abort(_('cannot backout change on a different branch'))
254
254
255 p1, p2 = repo.changelog.parents(node)
255 p1, p2 = repo.changelog.parents(node)
256 if p1 == nullid:
256 if p1 == nullid:
257 raise util.Abort(_('cannot backout a change with no parents'))
257 raise util.Abort(_('cannot backout a change with no parents'))
258 if p2 != nullid:
258 if p2 != nullid:
259 if not opts.get('parent'):
259 if not opts.get('parent'):
260 raise util.Abort(_('cannot backout a merge changeset without '
260 raise util.Abort(_('cannot backout a merge changeset without '
261 '--parent'))
261 '--parent'))
262 p = repo.lookup(opts['parent'])
262 p = repo.lookup(opts['parent'])
263 if p not in (p1, p2):
263 if p not in (p1, p2):
264 raise util.Abort(_('%s is not a parent of %s') %
264 raise util.Abort(_('%s is not a parent of %s') %
265 (short(p), short(node)))
265 (short(p), short(node)))
266 parent = p
266 parent = p
267 else:
267 else:
268 if opts.get('parent'):
268 if opts.get('parent'):
269 raise util.Abort(_('cannot use --parent on non-merge changeset'))
269 raise util.Abort(_('cannot use --parent on non-merge changeset'))
270 parent = p1
270 parent = p1
271
271
272 # the backout should appear on the same branch
272 # the backout should appear on the same branch
273 branch = repo.dirstate.branch()
273 branch = repo.dirstate.branch()
274 hg.clean(repo, node, show_stats=False)
274 hg.clean(repo, node, show_stats=False)
275 repo.dirstate.setbranch(branch)
275 repo.dirstate.setbranch(branch)
276 revert_opts = opts.copy()
276 revert_opts = opts.copy()
277 revert_opts['date'] = None
277 revert_opts['date'] = None
278 revert_opts['all'] = True
278 revert_opts['all'] = True
279 revert_opts['rev'] = hex(parent)
279 revert_opts['rev'] = hex(parent)
280 revert_opts['no_backup'] = None
280 revert_opts['no_backup'] = None
281 revert(ui, repo, **revert_opts)
281 revert(ui, repo, **revert_opts)
282 commit_opts = opts.copy()
282 commit_opts = opts.copy()
283 commit_opts['addremove'] = False
283 commit_opts['addremove'] = False
284 if not commit_opts['message'] and not commit_opts['logfile']:
284 if not commit_opts['message'] and not commit_opts['logfile']:
285 # we don't translate commit messages
285 # we don't translate commit messages
286 commit_opts['message'] = "Backed out changeset %s" % short(node)
286 commit_opts['message'] = "Backed out changeset %s" % short(node)
287 commit_opts['force_editor'] = True
287 commit_opts['force_editor'] = True
288 commit(ui, repo, **commit_opts)
288 commit(ui, repo, **commit_opts)
289 def nice(node):
289 def nice(node):
290 return '%d:%s' % (repo.changelog.rev(node), short(node))
290 return '%d:%s' % (repo.changelog.rev(node), short(node))
291 ui.status(_('changeset %s backs out changeset %s\n') %
291 ui.status(_('changeset %s backs out changeset %s\n') %
292 (nice(repo.changelog.tip()), nice(node)))
292 (nice(repo.changelog.tip()), nice(node)))
293 if op1 != node:
293 if op1 != node:
294 hg.clean(repo, op1, show_stats=False)
294 hg.clean(repo, op1, show_stats=False)
295 if opts.get('merge'):
295 if opts.get('merge'):
296 ui.status(_('merging with changeset %s\n')
296 ui.status(_('merging with changeset %s\n')
297 % nice(repo.changelog.tip()))
297 % nice(repo.changelog.tip()))
298 hg.merge(repo, hex(repo.changelog.tip()))
298 hg.merge(repo, hex(repo.changelog.tip()))
299 else:
299 else:
300 ui.status(_('the backout changeset is a new head - '
300 ui.status(_('the backout changeset is a new head - '
301 'do not forget to merge\n'))
301 'do not forget to merge\n'))
302 ui.status(_('(use "backout --merge" '
302 ui.status(_('(use "backout --merge" '
303 'if you want to auto-merge)\n'))
303 'if you want to auto-merge)\n'))
304
304
305 def bisect(ui, repo, rev=None, extra=None, command=None,
305 def bisect(ui, repo, rev=None, extra=None, command=None,
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
307 """subdivision search of changesets
307 """subdivision search of changesets
308
308
309 This command helps to find changesets which introduce problems. To
309 This command helps to find changesets which introduce problems. To
310 use, mark the earliest changeset you know exhibits the problem as
310 use, mark the earliest changeset you know exhibits the problem as
311 bad, then mark the latest changeset which is free from the problem
311 bad, then mark the latest changeset which is free from the problem
312 as good. Bisect will update your working directory to a revision
312 as good. Bisect will update your working directory to a revision
313 for testing (unless the -U/--noupdate option is specified). Once
313 for testing (unless the -U/--noupdate option is specified). Once
314 you have performed tests, mark the working directory as good or
314 you have performed tests, mark the working directory as good or
315 bad, and bisect will either update to another candidate changeset
315 bad, and bisect will either update to another candidate changeset
316 or announce that it has found the bad revision.
316 or announce that it has found the bad revision.
317
317
318 As a shortcut, you can also use the revision argument to mark a
318 As a shortcut, you can also use the revision argument to mark a
319 revision as good or bad without checking it out first.
319 revision as good or bad without checking it out first.
320
320
321 If you supply a command, it will be used for automatic bisection.
321 If you supply a command, it will be used for automatic bisection.
322 Its exit status will be used to mark revisions as good or bad:
322 Its exit status will be used to mark revisions as good or bad:
323 status 0 means good, 125 means to skip the revision, 127
323 status 0 means good, 125 means to skip the revision, 127
324 (command not found) will abort the bisection, and any other
324 (command not found) will abort the bisection, and any other
325 non-zero exit status means the revision is bad.
325 non-zero exit status means the revision is bad.
326 """
326 """
327 def print_result(nodes, good):
327 def print_result(nodes, good):
328 displayer = cmdutil.show_changeset(ui, repo, {})
328 displayer = cmdutil.show_changeset(ui, repo, {})
329 if len(nodes) == 1:
329 if len(nodes) == 1:
330 # narrowed it down to a single revision
330 # narrowed it down to a single revision
331 if good:
331 if good:
332 ui.write(_("The first good revision is:\n"))
332 ui.write(_("The first good revision is:\n"))
333 else:
333 else:
334 ui.write(_("The first bad revision is:\n"))
334 ui.write(_("The first bad revision is:\n"))
335 displayer.show(repo[nodes[0]])
335 displayer.show(repo[nodes[0]])
336 else:
336 else:
337 # multiple possible revisions
337 # multiple possible revisions
338 if good:
338 if good:
339 ui.write(_("Due to skipped revisions, the first "
339 ui.write(_("Due to skipped revisions, the first "
340 "good revision could be any of:\n"))
340 "good revision could be any of:\n"))
341 else:
341 else:
342 ui.write(_("Due to skipped revisions, the first "
342 ui.write(_("Due to skipped revisions, the first "
343 "bad revision could be any of:\n"))
343 "bad revision could be any of:\n"))
344 for n in nodes:
344 for n in nodes:
345 displayer.show(repo[n])
345 displayer.show(repo[n])
346 displayer.close()
346 displayer.close()
347
347
348 def check_state(state, interactive=True):
348 def check_state(state, interactive=True):
349 if not state['good'] or not state['bad']:
349 if not state['good'] or not state['bad']:
350 if (good or bad or skip or reset) and interactive:
350 if (good or bad or skip or reset) and interactive:
351 return
351 return
352 if not state['good']:
352 if not state['good']:
353 raise util.Abort(_('cannot bisect (no known good revisions)'))
353 raise util.Abort(_('cannot bisect (no known good revisions)'))
354 else:
354 else:
355 raise util.Abort(_('cannot bisect (no known bad revisions)'))
355 raise util.Abort(_('cannot bisect (no known bad revisions)'))
356 return True
356 return True
357
357
358 # backward compatibility
358 # backward compatibility
359 if rev in "good bad reset init".split():
359 if rev in "good bad reset init".split():
360 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
360 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
361 cmd, rev, extra = rev, extra, None
361 cmd, rev, extra = rev, extra, None
362 if cmd == "good":
362 if cmd == "good":
363 good = True
363 good = True
364 elif cmd == "bad":
364 elif cmd == "bad":
365 bad = True
365 bad = True
366 else:
366 else:
367 reset = True
367 reset = True
368 elif extra or good + bad + skip + reset + bool(command) > 1:
368 elif extra or good + bad + skip + reset + bool(command) > 1:
369 raise util.Abort(_('incompatible arguments'))
369 raise util.Abort(_('incompatible arguments'))
370
370
371 if reset:
371 if reset:
372 p = repo.join("bisect.state")
372 p = repo.join("bisect.state")
373 if os.path.exists(p):
373 if os.path.exists(p):
374 os.unlink(p)
374 os.unlink(p)
375 return
375 return
376
376
377 state = hbisect.load_state(repo)
377 state = hbisect.load_state(repo)
378
378
379 if command:
379 if command:
380 changesets = 1
380 changesets = 1
381 try:
381 try:
382 while changesets:
382 while changesets:
383 # update state
383 # update state
384 status = util.system(command)
384 status = util.system(command)
385 if status == 125:
385 if status == 125:
386 transition = "skip"
386 transition = "skip"
387 elif status == 0:
387 elif status == 0:
388 transition = "good"
388 transition = "good"
389 # status < 0 means process was killed
389 # status < 0 means process was killed
390 elif status == 127:
390 elif status == 127:
391 raise util.Abort(_("failed to execute %s") % command)
391 raise util.Abort(_("failed to execute %s") % command)
392 elif status < 0:
392 elif status < 0:
393 raise util.Abort(_("%s killed") % command)
393 raise util.Abort(_("%s killed") % command)
394 else:
394 else:
395 transition = "bad"
395 transition = "bad"
396 ctx = repo[rev or '.']
396 ctx = repo[rev or '.']
397 state[transition].append(ctx.node())
397 state[transition].append(ctx.node())
398 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
398 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
399 check_state(state, interactive=False)
399 check_state(state, interactive=False)
400 # bisect
400 # bisect
401 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
401 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
402 # update to next check
402 # update to next check
403 cmdutil.bail_if_changed(repo)
403 cmdutil.bail_if_changed(repo)
404 hg.clean(repo, nodes[0], show_stats=False)
404 hg.clean(repo, nodes[0], show_stats=False)
405 finally:
405 finally:
406 hbisect.save_state(repo, state)
406 hbisect.save_state(repo, state)
407 return print_result(nodes, good)
407 return print_result(nodes, good)
408
408
409 # update state
409 # update state
410 node = repo.lookup(rev or '.')
410 node = repo.lookup(rev or '.')
411 if good or bad or skip:
411 if good or bad or skip:
412 if good:
412 if good:
413 state['good'].append(node)
413 state['good'].append(node)
414 elif bad:
414 elif bad:
415 state['bad'].append(node)
415 state['bad'].append(node)
416 elif skip:
416 elif skip:
417 state['skip'].append(node)
417 state['skip'].append(node)
418 hbisect.save_state(repo, state)
418 hbisect.save_state(repo, state)
419
419
420 if not check_state(state):
420 if not check_state(state):
421 return
421 return
422
422
423 # actually bisect
423 # actually bisect
424 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
424 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
425 if changesets == 0:
425 if changesets == 0:
426 print_result(nodes, good)
426 print_result(nodes, good)
427 else:
427 else:
428 assert len(nodes) == 1 # only a single node can be tested next
428 assert len(nodes) == 1 # only a single node can be tested next
429 node = nodes[0]
429 node = nodes[0]
430 # compute the approximate number of remaining tests
430 # compute the approximate number of remaining tests
431 tests, size = 0, 2
431 tests, size = 0, 2
432 while size <= changesets:
432 while size <= changesets:
433 tests, size = tests + 1, size * 2
433 tests, size = tests + 1, size * 2
434 rev = repo.changelog.rev(node)
434 rev = repo.changelog.rev(node)
435 ui.write(_("Testing changeset %d:%s "
435 ui.write(_("Testing changeset %d:%s "
436 "(%d changesets remaining, ~%d tests)\n")
436 "(%d changesets remaining, ~%d tests)\n")
437 % (rev, short(node), changesets, tests))
437 % (rev, short(node), changesets, tests))
438 if not noupdate:
438 if not noupdate:
439 cmdutil.bail_if_changed(repo)
439 cmdutil.bail_if_changed(repo)
440 return hg.clean(repo, node)
440 return hg.clean(repo, node)
441
441
442 def branch(ui, repo, label=None, **opts):
442 def branch(ui, repo, label=None, **opts):
443 """set or show the current branch name
443 """set or show the current branch name
444
444
445 With no argument, show the current branch name. With one argument,
445 With no argument, show the current branch name. With one argument,
446 set the working directory branch name (the branch will not exist
446 set the working directory branch name (the branch will not exist
447 in the repository until the next commit). Standard practice
447 in the repository until the next commit). Standard practice
448 recommends that primary development take place on the 'default'
448 recommends that primary development take place on the 'default'
449 branch.
449 branch.
450
450
451 Unless -f/--force is specified, branch will not let you set a
451 Unless -f/--force is specified, branch will not let you set a
452 branch name that already exists, even if it's inactive.
452 branch name that already exists, even if it's inactive.
453
453
454 Use -C/--clean to reset the working directory branch to that of
454 Use -C/--clean to reset the working directory branch to that of
455 the parent of the working directory, negating a previous branch
455 the parent of the working directory, negating a previous branch
456 change.
456 change.
457
457
458 Use the command :hg:`update` to switch to an existing branch. Use
458 Use the command :hg:`update` to switch to an existing branch. Use
459 :hg:`commit --close-branch` to mark this branch as closed.
459 :hg:`commit --close-branch` to mark this branch as closed.
460 """
460 """
461
461
462 if opts.get('clean'):
462 if opts.get('clean'):
463 label = repo[None].parents()[0].branch()
463 label = repo[None].parents()[0].branch()
464 repo.dirstate.setbranch(label)
464 repo.dirstate.setbranch(label)
465 ui.status(_('reset working directory to branch %s\n') % label)
465 ui.status(_('reset working directory to branch %s\n') % label)
466 elif label:
466 elif label:
467 utflabel = encoding.fromlocal(label)
467 utflabel = encoding.fromlocal(label)
468 if not opts.get('force') and utflabel in repo.branchtags():
468 if not opts.get('force') and utflabel in repo.branchtags():
469 if label not in [p.branch() for p in repo.parents()]:
469 if label not in [p.branch() for p in repo.parents()]:
470 raise util.Abort(_('a branch of the same name already exists'
470 raise util.Abort(_('a branch of the same name already exists'
471 " (use 'hg update' to switch to it)"))
471 " (use 'hg update' to switch to it)"))
472 repo.dirstate.setbranch(utflabel)
472 repo.dirstate.setbranch(utflabel)
473 ui.status(_('marked working directory as branch %s\n') % label)
473 ui.status(_('marked working directory as branch %s\n') % label)
474 else:
474 else:
475 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
475 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
476
476
477 def branches(ui, repo, active=False, closed=False):
477 def branches(ui, repo, active=False, closed=False):
478 """list repository named branches
478 """list repository named branches
479
479
480 List the repository's named branches, indicating which ones are
480 List the repository's named branches, indicating which ones are
481 inactive. If -c/--closed is specified, also list branches which have
481 inactive. If -c/--closed is specified, also list branches which have
482 been marked closed (see hg commit --close-branch).
482 been marked closed (see hg commit --close-branch).
483
483
484 If -a/--active is specified, only show active branches. A branch
484 If -a/--active is specified, only show active branches. A branch
485 is considered active if it contains repository heads.
485 is considered active if it contains repository heads.
486
486
487 Use the command :hg:`update` to switch to an existing branch.
487 Use the command :hg:`update` to switch to an existing branch.
488 """
488 """
489
489
490 hexfunc = ui.debugflag and hex or short
490 hexfunc = ui.debugflag and hex or short
491 activebranches = [repo[n].branch() for n in repo.heads()]
491 activebranches = [repo[n].branch() for n in repo.heads()]
492 def testactive(tag, node):
492 def testactive(tag, node):
493 realhead = tag in activebranches
493 realhead = tag in activebranches
494 open = node in repo.branchheads(tag, closed=False)
494 open = node in repo.branchheads(tag, closed=False)
495 return realhead and open
495 return realhead and open
496 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
496 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
497 for tag, node in repo.branchtags().items()],
497 for tag, node in repo.branchtags().items()],
498 reverse=True)
498 reverse=True)
499
499
500 for isactive, node, tag in branches:
500 for isactive, node, tag in branches:
501 if (not active) or isactive:
501 if (not active) or isactive:
502 encodedtag = encoding.tolocal(tag)
502 encodedtag = encoding.tolocal(tag)
503 if ui.quiet:
503 if ui.quiet:
504 ui.write("%s\n" % encodedtag)
504 ui.write("%s\n" % encodedtag)
505 else:
505 else:
506 hn = repo.lookup(node)
506 hn = repo.lookup(node)
507 if isactive:
507 if isactive:
508 notice = ''
508 notice = ''
509 elif hn not in repo.branchheads(tag, closed=False):
509 elif hn not in repo.branchheads(tag, closed=False):
510 if not closed:
510 if not closed:
511 continue
511 continue
512 notice = _(' (closed)')
512 notice = _(' (closed)')
513 else:
513 else:
514 notice = _(' (inactive)')
514 notice = _(' (inactive)')
515 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
515 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
516 data = encodedtag, rev, hexfunc(hn), notice
516 data = encodedtag, rev, hexfunc(hn), notice
517 ui.write("%s %s:%s%s\n" % data)
517 ui.write("%s %s:%s%s\n" % data)
518
518
519 def bundle(ui, repo, fname, dest=None, **opts):
519 def bundle(ui, repo, fname, dest=None, **opts):
520 """create a changegroup file
520 """create a changegroup file
521
521
522 Generate a compressed changegroup file collecting changesets not
522 Generate a compressed changegroup file collecting changesets not
523 known to be in another repository.
523 known to be in another repository.
524
524
525 If you omit the destination repository, then hg assumes the
525 If you omit the destination repository, then hg assumes the
526 destination will have all the nodes you specify with --base
526 destination will have all the nodes you specify with --base
527 parameters. To create a bundle containing all changesets, use
527 parameters. To create a bundle containing all changesets, use
528 -a/--all (or --base null).
528 -a/--all (or --base null).
529
529
530 You can change compression method with the -t/--type option.
530 You can change compression method with the -t/--type option.
531 The available compression methods are: none, bzip2, and
531 The available compression methods are: none, bzip2, and
532 gzip (by default, bundles are compressed using bzip2).
532 gzip (by default, bundles are compressed using bzip2).
533
533
534 The bundle file can then be transferred using conventional means
534 The bundle file can then be transferred using conventional means
535 and applied to another repository with the unbundle or pull
535 and applied to another repository with the unbundle or pull
536 command. This is useful when direct push and pull are not
536 command. This is useful when direct push and pull are not
537 available or when exporting an entire repository is undesirable.
537 available or when exporting an entire repository is undesirable.
538
538
539 Applying bundles preserves all changeset contents including
539 Applying bundles preserves all changeset contents including
540 permissions, copy/rename information, and revision history.
540 permissions, copy/rename information, and revision history.
541 """
541 """
542 revs = opts.get('rev') or None
542 revs = opts.get('rev') or None
543 if revs:
543 if revs:
544 revs = [repo.lookup(rev) for rev in revs]
544 revs = [repo.lookup(rev) for rev in revs]
545 if opts.get('all'):
545 if opts.get('all'):
546 base = ['null']
546 base = ['null']
547 else:
547 else:
548 base = opts.get('base')
548 base = opts.get('base')
549 if base:
549 if base:
550 if dest:
550 if dest:
551 raise util.Abort(_("--base is incompatible with specifying "
551 raise util.Abort(_("--base is incompatible with specifying "
552 "a destination"))
552 "a destination"))
553 base = [repo.lookup(rev) for rev in base]
553 base = [repo.lookup(rev) for rev in base]
554 # create the right base
554 # create the right base
555 # XXX: nodesbetween / changegroup* should be "fixed" instead
555 # XXX: nodesbetween / changegroup* should be "fixed" instead
556 o = []
556 o = []
557 has = set((nullid,))
557 has = set((nullid,))
558 for n in base:
558 for n in base:
559 has.update(repo.changelog.reachable(n))
559 has.update(repo.changelog.reachable(n))
560 if revs:
560 if revs:
561 visit = list(revs)
561 visit = list(revs)
562 has.difference_update(revs)
562 has.difference_update(revs)
563 else:
563 else:
564 visit = repo.changelog.heads()
564 visit = repo.changelog.heads()
565 seen = {}
565 seen = {}
566 while visit:
566 while visit:
567 n = visit.pop(0)
567 n = visit.pop(0)
568 parents = [p for p in repo.changelog.parents(n) if p not in has]
568 parents = [p for p in repo.changelog.parents(n) if p not in has]
569 if len(parents) == 0:
569 if len(parents) == 0:
570 if n not in has:
570 if n not in has:
571 o.append(n)
571 o.append(n)
572 else:
572 else:
573 for p in parents:
573 for p in parents:
574 if p not in seen:
574 if p not in seen:
575 seen[p] = 1
575 seen[p] = 1
576 visit.append(p)
576 visit.append(p)
577 else:
577 else:
578 dest = ui.expandpath(dest or 'default-push', dest or 'default')
578 dest = ui.expandpath(dest or 'default-push', dest or 'default')
579 dest, branches = hg.parseurl(dest, opts.get('branch'))
579 dest, branches = hg.parseurl(dest, opts.get('branch'))
580 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
580 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
581 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
581 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
582 o = repo.findoutgoing(other, force=opts.get('force'))
582 o = repo.findoutgoing(other, force=opts.get('force'))
583
583
584 if not o:
584 if not o:
585 ui.status(_("no changes found\n"))
585 ui.status(_("no changes found\n"))
586 return
586 return
587
587
588 if revs:
588 if revs:
589 cg = repo.changegroupsubset(o, revs, 'bundle')
589 cg = repo.changegroupsubset(o, revs, 'bundle')
590 else:
590 else:
591 cg = repo.changegroup(o, 'bundle')
591 cg = repo.changegroup(o, 'bundle')
592
592
593 bundletype = opts.get('type', 'bzip2').lower()
593 bundletype = opts.get('type', 'bzip2').lower()
594 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
594 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
595 bundletype = btypes.get(bundletype)
595 bundletype = btypes.get(bundletype)
596 if bundletype not in changegroup.bundletypes:
596 if bundletype not in changegroup.bundletypes:
597 raise util.Abort(_('unknown bundle type specified with --type'))
597 raise util.Abort(_('unknown bundle type specified with --type'))
598
598
599 changegroup.writebundle(cg, fname, bundletype)
599 changegroup.writebundle(cg, fname, bundletype)
600
600
601 def cat(ui, repo, file1, *pats, **opts):
601 def cat(ui, repo, file1, *pats, **opts):
602 """output the current or given revision of files
602 """output the current or given revision of files
603
603
604 Print the specified files as they were at the given revision. If
604 Print the specified files as they were at the given revision. If
605 no revision is given, the parent of the working directory is used,
605 no revision is given, the parent of the working directory is used,
606 or tip if no revision is checked out.
606 or tip if no revision is checked out.
607
607
608 Output may be to a file, in which case the name of the file is
608 Output may be to a file, in which case the name of the file is
609 given using a format string. The formatting rules are the same as
609 given using a format string. The formatting rules are the same as
610 for the export command, with the following additions:
610 for the export command, with the following additions:
611
611
612 :``%s``: basename of file being printed
612 :``%s``: basename of file being printed
613 :``%d``: dirname of file being printed, or '.' if in repository root
613 :``%d``: dirname of file being printed, or '.' if in repository root
614 :``%p``: root-relative path name of file being printed
614 :``%p``: root-relative path name of file being printed
615 """
615 """
616 ctx = repo[opts.get('rev')]
616 ctx = repo[opts.get('rev')]
617 err = 1
617 err = 1
618 m = cmdutil.match(repo, (file1,) + pats, opts)
618 m = cmdutil.match(repo, (file1,) + pats, opts)
619 for abs in ctx.walk(m):
619 for abs in ctx.walk(m):
620 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
620 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
621 data = ctx[abs].data()
621 data = ctx[abs].data()
622 if opts.get('decode'):
622 if opts.get('decode'):
623 data = repo.wwritedata(abs, data)
623 data = repo.wwritedata(abs, data)
624 fp.write(data)
624 fp.write(data)
625 err = 0
625 err = 0
626 return err
626 return err
627
627
628 def clone(ui, source, dest=None, **opts):
628 def clone(ui, source, dest=None, **opts):
629 """make a copy of an existing repository
629 """make a copy of an existing repository
630
630
631 Create a copy of an existing repository in a new directory.
631 Create a copy of an existing repository in a new directory.
632
632
633 If no destination directory name is specified, it defaults to the
633 If no destination directory name is specified, it defaults to the
634 basename of the source.
634 basename of the source.
635
635
636 The location of the source is added to the new repository's
636 The location of the source is added to the new repository's
637 .hg/hgrc file, as the default to be used for future pulls.
637 .hg/hgrc file, as the default to be used for future pulls.
638
638
639 See :hg:`help urls` for valid source format details.
639 See :hg:`help urls` for valid source format details.
640
640
641 It is possible to specify an ``ssh://`` URL as the destination, but no
641 It is possible to specify an ``ssh://`` URL as the destination, but no
642 .hg/hgrc and working directory will be created on the remote side.
642 .hg/hgrc and working directory will be created on the remote side.
643 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
643 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
644
644
645 A set of changesets (tags, or branch names) to pull may be specified
645 A set of changesets (tags, or branch names) to pull may be specified
646 by listing each changeset (tag, or branch name) with -r/--rev.
646 by listing each changeset (tag, or branch name) with -r/--rev.
647 If -r/--rev is used, the cloned repository will contain only a subset
647 If -r/--rev is used, the cloned repository will contain only a subset
648 of the changesets of the source repository. Only the set of changesets
648 of the changesets of the source repository. Only the set of changesets
649 defined by all -r/--rev options (including all their ancestors)
649 defined by all -r/--rev options (including all their ancestors)
650 will be pulled into the destination repository.
650 will be pulled into the destination repository.
651 No subsequent changesets (including subsequent tags) will be present
651 No subsequent changesets (including subsequent tags) will be present
652 in the destination.
652 in the destination.
653
653
654 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
654 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
655 local source repositories.
655 local source repositories.
656
656
657 For efficiency, hardlinks are used for cloning whenever the source
657 For efficiency, hardlinks are used for cloning whenever the source
658 and destination are on the same filesystem (note this applies only
658 and destination are on the same filesystem (note this applies only
659 to the repository data, not to the working directory). Some
659 to the repository data, not to the working directory). Some
660 filesystems, such as AFS, implement hardlinking incorrectly, but
660 filesystems, such as AFS, implement hardlinking incorrectly, but
661 do not report errors. In these cases, use the --pull option to
661 do not report errors. In these cases, use the --pull option to
662 avoid hardlinking.
662 avoid hardlinking.
663
663
664 In some cases, you can clone repositories and the working directory
664 In some cases, you can clone repositories and the working directory
665 using full hardlinks with ::
665 using full hardlinks with ::
666
666
667 $ cp -al REPO REPOCLONE
667 $ cp -al REPO REPOCLONE
668
668
669 This is the fastest way to clone, but it is not always safe. The
669 This is the fastest way to clone, but it is not always safe. The
670 operation is not atomic (making sure REPO is not modified during
670 operation is not atomic (making sure REPO is not modified during
671 the operation is up to you) and you have to make sure your editor
671 the operation is up to you) and you have to make sure your editor
672 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
672 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
673 this is not compatible with certain extensions that place their
673 this is not compatible with certain extensions that place their
674 metadata under the .hg directory, such as mq.
674 metadata under the .hg directory, such as mq.
675
675
676 Mercurial will update the working directory to the first applicable
676 Mercurial will update the working directory to the first applicable
677 revision from this list:
677 revision from this list:
678
678
679 a) null if -U or the source repository has no changesets
679 a) null if -U or the source repository has no changesets
680 b) if -u . and the source repository is local, the first parent of
680 b) if -u . and the source repository is local, the first parent of
681 the source repository's working directory
681 the source repository's working directory
682 c) the changeset specified with -u (if a branch name, this means the
682 c) the changeset specified with -u (if a branch name, this means the
683 latest head of that branch)
683 latest head of that branch)
684 d) the changeset specified with -r
684 d) the changeset specified with -r
685 e) the tipmost head specified with -b
685 e) the tipmost head specified with -b
686 f) the tipmost head specified with the url#branch source syntax
686 f) the tipmost head specified with the url#branch source syntax
687 g) the tipmost head of the default branch
687 g) the tipmost head of the default branch
688 h) tip
688 h) tip
689 """
689 """
690 if opts.get('noupdate') and opts.get('updaterev'):
690 if opts.get('noupdate') and opts.get('updaterev'):
691 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
691 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
692
692
693 hg.clone(cmdutil.remoteui(ui, opts), source, dest,
693 hg.clone(cmdutil.remoteui(ui, opts), source, dest,
694 pull=opts.get('pull'),
694 pull=opts.get('pull'),
695 stream=opts.get('uncompressed'),
695 stream=opts.get('uncompressed'),
696 rev=opts.get('rev'),
696 rev=opts.get('rev'),
697 update=opts.get('updaterev') or not opts.get('noupdate'),
697 update=opts.get('updaterev') or not opts.get('noupdate'),
698 branch=opts.get('branch'))
698 branch=opts.get('branch'))
699
699
700 def commit(ui, repo, *pats, **opts):
700 def commit(ui, repo, *pats, **opts):
701 """commit the specified files or all outstanding changes
701 """commit the specified files or all outstanding changes
702
702
703 Commit changes to the given files into the repository. Unlike a
703 Commit changes to the given files into the repository. Unlike a
704 centralized RCS, this operation is a local operation. See hg push
704 centralized RCS, this operation is a local operation. See hg push
705 for a way to actively distribute your changes.
705 for a way to actively distribute your changes.
706
706
707 If a list of files is omitted, all changes reported by :hg:`status`
707 If a list of files is omitted, all changes reported by :hg:`status`
708 will be committed.
708 will be committed.
709
709
710 If you are committing the result of a merge, do not provide any
710 If you are committing the result of a merge, do not provide any
711 filenames or -I/-X filters.
711 filenames or -I/-X filters.
712
712
713 If no commit message is specified, the configured editor is
713 If no commit message is specified, the configured editor is
714 started to prompt you for a message.
714 started to prompt you for a message.
715
715
716 See :hg:`help dates` for a list of formats valid for -d/--date.
716 See :hg:`help dates` for a list of formats valid for -d/--date.
717 """
717 """
718 extra = {}
718 extra = {}
719 if opts.get('close_branch'):
719 if opts.get('close_branch'):
720 extra['close'] = 1
720 extra['close'] = 1
721 e = cmdutil.commiteditor
721 e = cmdutil.commiteditor
722 if opts.get('force_editor'):
722 if opts.get('force_editor'):
723 e = cmdutil.commitforceeditor
723 e = cmdutil.commitforceeditor
724
724
725 def commitfunc(ui, repo, message, match, opts):
725 def commitfunc(ui, repo, message, match, opts):
726 return repo.commit(message, opts.get('user'), opts.get('date'), match,
726 return repo.commit(message, opts.get('user'), opts.get('date'), match,
727 editor=e, extra=extra)
727 editor=e, extra=extra)
728
728
729 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
729 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
730 if not node:
730 if not node:
731 ui.status(_("nothing changed\n"))
731 ui.status(_("nothing changed\n"))
732 return
732 return
733 cl = repo.changelog
733 cl = repo.changelog
734 rev = cl.rev(node)
734 rev = cl.rev(node)
735 parents = cl.parentrevs(rev)
735 parents = cl.parentrevs(rev)
736 if rev - 1 in parents:
736 if rev - 1 in parents:
737 # one of the parents was the old tip
737 # one of the parents was the old tip
738 pass
738 pass
739 elif (parents == (nullrev, nullrev) or
739 elif (parents == (nullrev, nullrev) or
740 len(cl.heads(cl.node(parents[0]))) > 1 and
740 len(cl.heads(cl.node(parents[0]))) > 1 and
741 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
741 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
742 ui.status(_('created new head\n'))
742 ui.status(_('created new head\n'))
743
743
744 if ui.debugflag:
744 if ui.debugflag:
745 ui.write(_('committed changeset %d:%s\n') % (rev, hex(node)))
745 ui.write(_('committed changeset %d:%s\n') % (rev, hex(node)))
746 elif ui.verbose:
746 elif ui.verbose:
747 ui.write(_('committed changeset %d:%s\n') % (rev, short(node)))
747 ui.write(_('committed changeset %d:%s\n') % (rev, short(node)))
748
748
749 def copy(ui, repo, *pats, **opts):
749 def copy(ui, repo, *pats, **opts):
750 """mark files as copied for the next commit
750 """mark files as copied for the next commit
751
751
752 Mark dest as having copies of source files. If dest is a
752 Mark dest as having copies of source files. If dest is a
753 directory, copies are put in that directory. If dest is a file,
753 directory, copies are put in that directory. If dest is a file,
754 the source must be a single file.
754 the source must be a single file.
755
755
756 By default, this command copies the contents of files as they
756 By default, this command copies the contents of files as they
757 exist in the working directory. If invoked with -A/--after, the
757 exist in the working directory. If invoked with -A/--after, the
758 operation is recorded, but no copying is performed.
758 operation is recorded, but no copying is performed.
759
759
760 This command takes effect with the next commit. To undo a copy
760 This command takes effect with the next commit. To undo a copy
761 before that, see hg revert.
761 before that, see hg revert.
762 """
762 """
763 wlock = repo.wlock(False)
763 wlock = repo.wlock(False)
764 try:
764 try:
765 return cmdutil.copy(ui, repo, pats, opts)
765 return cmdutil.copy(ui, repo, pats, opts)
766 finally:
766 finally:
767 wlock.release()
767 wlock.release()
768
768
769 def debugancestor(ui, repo, *args):
769 def debugancestor(ui, repo, *args):
770 """find the ancestor revision of two revisions in a given index"""
770 """find the ancestor revision of two revisions in a given index"""
771 if len(args) == 3:
771 if len(args) == 3:
772 index, rev1, rev2 = args
772 index, rev1, rev2 = args
773 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
773 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
774 lookup = r.lookup
774 lookup = r.lookup
775 elif len(args) == 2:
775 elif len(args) == 2:
776 if not repo:
776 if not repo:
777 raise util.Abort(_("There is no Mercurial repository here "
777 raise util.Abort(_("There is no Mercurial repository here "
778 "(.hg not found)"))
778 "(.hg not found)"))
779 rev1, rev2 = args
779 rev1, rev2 = args
780 r = repo.changelog
780 r = repo.changelog
781 lookup = repo.lookup
781 lookup = repo.lookup
782 else:
782 else:
783 raise util.Abort(_('either two or three arguments required'))
783 raise util.Abort(_('either two or three arguments required'))
784 a = r.ancestor(lookup(rev1), lookup(rev2))
784 a = r.ancestor(lookup(rev1), lookup(rev2))
785 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
785 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
786
786
787 def debugcommands(ui, cmd='', *args):
787 def debugcommands(ui, cmd='', *args):
788 for cmd, vals in sorted(table.iteritems()):
788 for cmd, vals in sorted(table.iteritems()):
789 cmd = cmd.split('|')[0].strip('^')
789 cmd = cmd.split('|')[0].strip('^')
790 opts = ', '.join([i[1] for i in vals[1]])
790 opts = ', '.join([i[1] for i in vals[1]])
791 ui.write('%s: %s\n' % (cmd, opts))
791 ui.write('%s: %s\n' % (cmd, opts))
792
792
793 def debugcomplete(ui, cmd='', **opts):
793 def debugcomplete(ui, cmd='', **opts):
794 """returns the completion list associated with the given command"""
794 """returns the completion list associated with the given command"""
795
795
796 if opts.get('options'):
796 if opts.get('options'):
797 options = []
797 options = []
798 otables = [globalopts]
798 otables = [globalopts]
799 if cmd:
799 if cmd:
800 aliases, entry = cmdutil.findcmd(cmd, table, False)
800 aliases, entry = cmdutil.findcmd(cmd, table, False)
801 otables.append(entry[1])
801 otables.append(entry[1])
802 for t in otables:
802 for t in otables:
803 for o in t:
803 for o in t:
804 if "(DEPRECATED)" in o[3]:
804 if "(DEPRECATED)" in o[3]:
805 continue
805 continue
806 if o[0]:
806 if o[0]:
807 options.append('-%s' % o[0])
807 options.append('-%s' % o[0])
808 options.append('--%s' % o[1])
808 options.append('--%s' % o[1])
809 ui.write("%s\n" % "\n".join(options))
809 ui.write("%s\n" % "\n".join(options))
810 return
810 return
811
811
812 cmdlist = cmdutil.findpossible(cmd, table)
812 cmdlist = cmdutil.findpossible(cmd, table)
813 if ui.verbose:
813 if ui.verbose:
814 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
814 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
815 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
815 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
816
816
817 def debugfsinfo(ui, path = "."):
817 def debugfsinfo(ui, path = "."):
818 open('.debugfsinfo', 'w').write('')
818 open('.debugfsinfo', 'w').write('')
819 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
819 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
820 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
820 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
821 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
821 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
822 and 'yes' or 'no'))
822 and 'yes' or 'no'))
823 os.unlink('.debugfsinfo')
823 os.unlink('.debugfsinfo')
824
824
825 def debugrebuildstate(ui, repo, rev="tip"):
825 def debugrebuildstate(ui, repo, rev="tip"):
826 """rebuild the dirstate as it would look like for the given revision"""
826 """rebuild the dirstate as it would look like for the given revision"""
827 ctx = repo[rev]
827 ctx = repo[rev]
828 wlock = repo.wlock()
828 wlock = repo.wlock()
829 try:
829 try:
830 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
830 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
831 finally:
831 finally:
832 wlock.release()
832 wlock.release()
833
833
834 def debugcheckstate(ui, repo):
834 def debugcheckstate(ui, repo):
835 """validate the correctness of the current dirstate"""
835 """validate the correctness of the current dirstate"""
836 parent1, parent2 = repo.dirstate.parents()
836 parent1, parent2 = repo.dirstate.parents()
837 m1 = repo[parent1].manifest()
837 m1 = repo[parent1].manifest()
838 m2 = repo[parent2].manifest()
838 m2 = repo[parent2].manifest()
839 errors = 0
839 errors = 0
840 for f in repo.dirstate:
840 for f in repo.dirstate:
841 state = repo.dirstate[f]
841 state = repo.dirstate[f]
842 if state in "nr" and f not in m1:
842 if state in "nr" and f not in m1:
843 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
843 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
844 errors += 1
844 errors += 1
845 if state in "a" and f in m1:
845 if state in "a" and f in m1:
846 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
846 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
847 errors += 1
847 errors += 1
848 if state in "m" and f not in m1 and f not in m2:
848 if state in "m" and f not in m1 and f not in m2:
849 ui.warn(_("%s in state %s, but not in either manifest\n") %
849 ui.warn(_("%s in state %s, but not in either manifest\n") %
850 (f, state))
850 (f, state))
851 errors += 1
851 errors += 1
852 for f in m1:
852 for f in m1:
853 state = repo.dirstate[f]
853 state = repo.dirstate[f]
854 if state not in "nrm":
854 if state not in "nrm":
855 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
855 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
856 errors += 1
856 errors += 1
857 if errors:
857 if errors:
858 error = _(".hg/dirstate inconsistent with current parent's manifest")
858 error = _(".hg/dirstate inconsistent with current parent's manifest")
859 raise util.Abort(error)
859 raise util.Abort(error)
860
860
861 def showconfig(ui, repo, *values, **opts):
861 def showconfig(ui, repo, *values, **opts):
862 """show combined config settings from all hgrc files
862 """show combined config settings from all hgrc files
863
863
864 With no arguments, print names and values of all config items.
864 With no arguments, print names and values of all config items.
865
865
866 With one argument of the form section.name, print just the value
866 With one argument of the form section.name, print just the value
867 of that config item.
867 of that config item.
868
868
869 With multiple arguments, print names and values of all config
869 With multiple arguments, print names and values of all config
870 items with matching section names.
870 items with matching section names.
871
871
872 With --debug, the source (filename and line number) is printed
872 With --debug, the source (filename and line number) is printed
873 for each config item.
873 for each config item.
874 """
874 """
875
875
876 for f in util.rcpath():
876 for f in util.rcpath():
877 ui.debug(_('read config from: %s\n') % f)
877 ui.debug(_('read config from: %s\n') % f)
878 untrusted = bool(opts.get('untrusted'))
878 untrusted = bool(opts.get('untrusted'))
879 if values:
879 if values:
880 if len([v for v in values if '.' in v]) > 1:
880 if len([v for v in values if '.' in v]) > 1:
881 raise util.Abort(_('only one config item permitted'))
881 raise util.Abort(_('only one config item permitted'))
882 for section, name, value in ui.walkconfig(untrusted=untrusted):
882 for section, name, value in ui.walkconfig(untrusted=untrusted):
883 sectname = section + '.' + name
883 sectname = section + '.' + name
884 if values:
884 if values:
885 for v in values:
885 for v in values:
886 if v == section:
886 if v == section:
887 ui.debug('%s: ' %
887 ui.debug('%s: ' %
888 ui.configsource(section, name, untrusted))
888 ui.configsource(section, name, untrusted))
889 ui.write('%s=%s\n' % (sectname, value))
889 ui.write('%s=%s\n' % (sectname, value))
890 elif v == sectname:
890 elif v == sectname:
891 ui.debug('%s: ' %
891 ui.debug('%s: ' %
892 ui.configsource(section, name, untrusted))
892 ui.configsource(section, name, untrusted))
893 ui.write(value, '\n')
893 ui.write(value, '\n')
894 else:
894 else:
895 ui.debug('%s: ' %
895 ui.debug('%s: ' %
896 ui.configsource(section, name, untrusted))
896 ui.configsource(section, name, untrusted))
897 ui.write('%s=%s\n' % (sectname, value))
897 ui.write('%s=%s\n' % (sectname, value))
898
898
899 def debugsetparents(ui, repo, rev1, rev2=None):
899 def debugsetparents(ui, repo, rev1, rev2=None):
900 """manually set the parents of the current working directory
900 """manually set the parents of the current working directory
901
901
902 This is useful for writing repository conversion tools, but should
902 This is useful for writing repository conversion tools, but should
903 be used with care.
903 be used with care.
904 """
904 """
905
905
906 if not rev2:
906 if not rev2:
907 rev2 = hex(nullid)
907 rev2 = hex(nullid)
908
908
909 wlock = repo.wlock()
909 wlock = repo.wlock()
910 try:
910 try:
911 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
911 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
912 finally:
912 finally:
913 wlock.release()
913 wlock.release()
914
914
915 def debugstate(ui, repo, nodates=None):
915 def debugstate(ui, repo, nodates=None):
916 """show the contents of the current dirstate"""
916 """show the contents of the current dirstate"""
917 timestr = ""
917 timestr = ""
918 showdate = not nodates
918 showdate = not nodates
919 for file_, ent in sorted(repo.dirstate._map.iteritems()):
919 for file_, ent in sorted(repo.dirstate._map.iteritems()):
920 if showdate:
920 if showdate:
921 if ent[3] == -1:
921 if ent[3] == -1:
922 # Pad or slice to locale representation
922 # Pad or slice to locale representation
923 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
923 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
924 time.localtime(0)))
924 time.localtime(0)))
925 timestr = 'unset'
925 timestr = 'unset'
926 timestr = (timestr[:locale_len] +
926 timestr = (timestr[:locale_len] +
927 ' ' * (locale_len - len(timestr)))
927 ' ' * (locale_len - len(timestr)))
928 else:
928 else:
929 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
929 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
930 time.localtime(ent[3]))
930 time.localtime(ent[3]))
931 if ent[1] & 020000:
931 if ent[1] & 020000:
932 mode = 'lnk'
932 mode = 'lnk'
933 else:
933 else:
934 mode = '%3o' % (ent[1] & 0777)
934 mode = '%3o' % (ent[1] & 0777)
935 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
935 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
936 for f in repo.dirstate.copies():
936 for f in repo.dirstate.copies():
937 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
937 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
938
938
939 def debugsub(ui, repo, rev=None):
939 def debugsub(ui, repo, rev=None):
940 if rev == '':
940 if rev == '':
941 rev = None
941 rev = None
942 for k, v in sorted(repo[rev].substate.items()):
942 for k, v in sorted(repo[rev].substate.items()):
943 ui.write('path %s\n' % k)
943 ui.write('path %s\n' % k)
944 ui.write(' source %s\n' % v[0])
944 ui.write(' source %s\n' % v[0])
945 ui.write(' revision %s\n' % v[1])
945 ui.write(' revision %s\n' % v[1])
946
946
947 def debugdata(ui, file_, rev):
947 def debugdata(ui, file_, rev):
948 """dump the contents of a data file revision"""
948 """dump the contents of a data file revision"""
949 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
949 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
950 try:
950 try:
951 ui.write(r.revision(r.lookup(rev)))
951 ui.write(r.revision(r.lookup(rev)))
952 except KeyError:
952 except KeyError:
953 raise util.Abort(_('invalid revision identifier %s') % rev)
953 raise util.Abort(_('invalid revision identifier %s') % rev)
954
954
955 def debugdate(ui, date, range=None, **opts):
955 def debugdate(ui, date, range=None, **opts):
956 """parse and display a date"""
956 """parse and display a date"""
957 if opts["extended"]:
957 if opts["extended"]:
958 d = util.parsedate(date, util.extendeddateformats)
958 d = util.parsedate(date, util.extendeddateformats)
959 else:
959 else:
960 d = util.parsedate(date)
960 d = util.parsedate(date)
961 ui.write("internal: %s %s\n" % d)
961 ui.write("internal: %s %s\n" % d)
962 ui.write("standard: %s\n" % util.datestr(d))
962 ui.write("standard: %s\n" % util.datestr(d))
963 if range:
963 if range:
964 m = util.matchdate(range)
964 m = util.matchdate(range)
965 ui.write("match: %s\n" % m(d[0]))
965 ui.write("match: %s\n" % m(d[0]))
966
966
967 def debugindex(ui, file_):
967 def debugindex(ui, file_):
968 """dump the contents of an index file"""
968 """dump the contents of an index file"""
969 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
969 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
970 ui.write(" rev offset length base linkrev"
970 ui.write(" rev offset length base linkrev"
971 " nodeid p1 p2\n")
971 " nodeid p1 p2\n")
972 for i in r:
972 for i in r:
973 node = r.node(i)
973 node = r.node(i)
974 try:
974 try:
975 pp = r.parents(node)
975 pp = r.parents(node)
976 except:
976 except:
977 pp = [nullid, nullid]
977 pp = [nullid, nullid]
978 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
978 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
979 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
979 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
980 short(node), short(pp[0]), short(pp[1])))
980 short(node), short(pp[0]), short(pp[1])))
981
981
982 def debugindexdot(ui, file_):
982 def debugindexdot(ui, file_):
983 """dump an index DAG as a graphviz dot file"""
983 """dump an index DAG as a graphviz dot file"""
984 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
984 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
985 ui.write("digraph G {\n")
985 ui.write("digraph G {\n")
986 for i in r:
986 for i in r:
987 node = r.node(i)
987 node = r.node(i)
988 pp = r.parents(node)
988 pp = r.parents(node)
989 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
989 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
990 if pp[1] != nullid:
990 if pp[1] != nullid:
991 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
991 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
992 ui.write("}\n")
992 ui.write("}\n")
993
993
994 def debuginstall(ui):
994 def debuginstall(ui):
995 '''test Mercurial installation'''
995 '''test Mercurial installation'''
996
996
997 def writetemp(contents):
997 def writetemp(contents):
998 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
998 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
999 f = os.fdopen(fd, "wb")
999 f = os.fdopen(fd, "wb")
1000 f.write(contents)
1000 f.write(contents)
1001 f.close()
1001 f.close()
1002 return name
1002 return name
1003
1003
1004 problems = 0
1004 problems = 0
1005
1005
1006 # encoding
1006 # encoding
1007 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1007 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1008 try:
1008 try:
1009 encoding.fromlocal("test")
1009 encoding.fromlocal("test")
1010 except util.Abort, inst:
1010 except util.Abort, inst:
1011 ui.write(" %s\n" % inst)
1011 ui.write(" %s\n" % inst)
1012 ui.write(_(" (check that your locale is properly set)\n"))
1012 ui.write(_(" (check that your locale is properly set)\n"))
1013 problems += 1
1013 problems += 1
1014
1014
1015 # compiled modules
1015 # compiled modules
1016 ui.status(_("Checking extensions...\n"))
1016 ui.status(_("Checking extensions...\n"))
1017 try:
1017 try:
1018 import bdiff, mpatch, base85
1018 import bdiff, mpatch, base85
1019 except Exception, inst:
1019 except Exception, inst:
1020 ui.write(" %s\n" % inst)
1020 ui.write(" %s\n" % inst)
1021 ui.write(_(" One or more extensions could not be found"))
1021 ui.write(_(" One or more extensions could not be found"))
1022 ui.write(_(" (check that you compiled the extensions)\n"))
1022 ui.write(_(" (check that you compiled the extensions)\n"))
1023 problems += 1
1023 problems += 1
1024
1024
1025 # templates
1025 # templates
1026 ui.status(_("Checking templates...\n"))
1026 ui.status(_("Checking templates...\n"))
1027 try:
1027 try:
1028 import templater
1028 import templater
1029 templater.templater(templater.templatepath("map-cmdline.default"))
1029 templater.templater(templater.templatepath("map-cmdline.default"))
1030 except Exception, inst:
1030 except Exception, inst:
1031 ui.write(" %s\n" % inst)
1031 ui.write(" %s\n" % inst)
1032 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1032 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1033 problems += 1
1033 problems += 1
1034
1034
1035 # patch
1035 # patch
1036 ui.status(_("Checking patch...\n"))
1036 ui.status(_("Checking patch...\n"))
1037 patchproblems = 0
1037 patchproblems = 0
1038 a = "1\n2\n3\n4\n"
1038 a = "1\n2\n3\n4\n"
1039 b = "1\n2\n3\ninsert\n4\n"
1039 b = "1\n2\n3\ninsert\n4\n"
1040 fa = writetemp(a)
1040 fa = writetemp(a)
1041 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1041 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1042 os.path.basename(fa))
1042 os.path.basename(fa))
1043 fd = writetemp(d)
1043 fd = writetemp(d)
1044
1044
1045 files = {}
1045 files = {}
1046 try:
1046 try:
1047 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1047 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1048 except util.Abort, e:
1048 except util.Abort, e:
1049 ui.write(_(" patch call failed:\n"))
1049 ui.write(_(" patch call failed:\n"))
1050 ui.write(" " + str(e) + "\n")
1050 ui.write(" " + str(e) + "\n")
1051 patchproblems += 1
1051 patchproblems += 1
1052 else:
1052 else:
1053 if list(files) != [os.path.basename(fa)]:
1053 if list(files) != [os.path.basename(fa)]:
1054 ui.write(_(" unexpected patch output!\n"))
1054 ui.write(_(" unexpected patch output!\n"))
1055 patchproblems += 1
1055 patchproblems += 1
1056 a = open(fa).read()
1056 a = open(fa).read()
1057 if a != b:
1057 if a != b:
1058 ui.write(_(" patch test failed!\n"))
1058 ui.write(_(" patch test failed!\n"))
1059 patchproblems += 1
1059 patchproblems += 1
1060
1060
1061 if patchproblems:
1061 if patchproblems:
1062 if ui.config('ui', 'patch'):
1062 if ui.config('ui', 'patch'):
1063 ui.write(_(" (Current patch tool may be incompatible with patch,"
1063 ui.write(_(" (Current patch tool may be incompatible with patch,"
1064 " or misconfigured. Please check your .hgrc file)\n"))
1064 " or misconfigured. Please check your .hgrc file)\n"))
1065 else:
1065 else:
1066 ui.write(_(" Internal patcher failure, please report this error"
1066 ui.write(_(" Internal patcher failure, please report this error"
1067 " to http://mercurial.selenic.com/bts/\n"))
1067 " to http://mercurial.selenic.com/bts/\n"))
1068 problems += patchproblems
1068 problems += patchproblems
1069
1069
1070 os.unlink(fa)
1070 os.unlink(fa)
1071 os.unlink(fd)
1071 os.unlink(fd)
1072
1072
1073 # editor
1073 # editor
1074 ui.status(_("Checking commit editor...\n"))
1074 ui.status(_("Checking commit editor...\n"))
1075 editor = ui.geteditor()
1075 editor = ui.geteditor()
1076 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1076 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1077 if not cmdpath:
1077 if not cmdpath:
1078 if editor == 'vi':
1078 if editor == 'vi':
1079 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1079 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1080 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1080 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1081 else:
1081 else:
1082 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1082 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1083 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1083 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1084 problems += 1
1084 problems += 1
1085
1085
1086 # check username
1086 # check username
1087 ui.status(_("Checking username...\n"))
1087 ui.status(_("Checking username...\n"))
1088 try:
1088 try:
1089 user = ui.username()
1089 user = ui.username()
1090 except util.Abort, e:
1090 except util.Abort, e:
1091 ui.write(" %s\n" % e)
1091 ui.write(" %s\n" % e)
1092 ui.write(_(" (specify a username in your .hgrc file)\n"))
1092 ui.write(_(" (specify a username in your .hgrc file)\n"))
1093 problems += 1
1093 problems += 1
1094
1094
1095 if not problems:
1095 if not problems:
1096 ui.status(_("No problems detected\n"))
1096 ui.status(_("No problems detected\n"))
1097 else:
1097 else:
1098 ui.write(_("%s problems detected,"
1098 ui.write(_("%s problems detected,"
1099 " please check your install!\n") % problems)
1099 " please check your install!\n") % problems)
1100
1100
1101 return problems
1101 return problems
1102
1102
1103 def debugrename(ui, repo, file1, *pats, **opts):
1103 def debugrename(ui, repo, file1, *pats, **opts):
1104 """dump rename information"""
1104 """dump rename information"""
1105
1105
1106 ctx = repo[opts.get('rev')]
1106 ctx = repo[opts.get('rev')]
1107 m = cmdutil.match(repo, (file1,) + pats, opts)
1107 m = cmdutil.match(repo, (file1,) + pats, opts)
1108 for abs in ctx.walk(m):
1108 for abs in ctx.walk(m):
1109 fctx = ctx[abs]
1109 fctx = ctx[abs]
1110 o = fctx.filelog().renamed(fctx.filenode())
1110 o = fctx.filelog().renamed(fctx.filenode())
1111 rel = m.rel(abs)
1111 rel = m.rel(abs)
1112 if o:
1112 if o:
1113 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1113 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1114 else:
1114 else:
1115 ui.write(_("%s not renamed\n") % rel)
1115 ui.write(_("%s not renamed\n") % rel)
1116
1116
1117 def debugwalk(ui, repo, *pats, **opts):
1117 def debugwalk(ui, repo, *pats, **opts):
1118 """show how files match on given patterns"""
1118 """show how files match on given patterns"""
1119 m = cmdutil.match(repo, pats, opts)
1119 m = cmdutil.match(repo, pats, opts)
1120 items = list(repo.walk(m))
1120 items = list(repo.walk(m))
1121 if not items:
1121 if not items:
1122 return
1122 return
1123 fmt = 'f %%-%ds %%-%ds %%s' % (
1123 fmt = 'f %%-%ds %%-%ds %%s' % (
1124 max([len(abs) for abs in items]),
1124 max([len(abs) for abs in items]),
1125 max([len(m.rel(abs)) for abs in items]))
1125 max([len(m.rel(abs)) for abs in items]))
1126 for abs in items:
1126 for abs in items:
1127 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1127 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1128 ui.write("%s\n" % line.rstrip())
1128 ui.write("%s\n" % line.rstrip())
1129
1129
1130 def diff(ui, repo, *pats, **opts):
1130 def diff(ui, repo, *pats, **opts):
1131 """diff repository (or selected files)
1131 """diff repository (or selected files)
1132
1132
1133 Show differences between revisions for the specified files.
1133 Show differences between revisions for the specified files.
1134
1134
1135 Differences between files are shown using the unified diff format.
1135 Differences between files are shown using the unified diff format.
1136
1136
1137 NOTE: diff may generate unexpected results for merges, as it will
1137 NOTE: diff may generate unexpected results for merges, as it will
1138 default to comparing against the working directory's first parent
1138 default to comparing against the working directory's first parent
1139 changeset if no revisions are specified.
1139 changeset if no revisions are specified.
1140
1140
1141 When two revision arguments are given, then changes are shown
1141 When two revision arguments are given, then changes are shown
1142 between those revisions. If only one revision is specified then
1142 between those revisions. If only one revision is specified then
1143 that revision is compared to the working directory, and, when no
1143 that revision is compared to the working directory, and, when no
1144 revisions are specified, the working directory files are compared
1144 revisions are specified, the working directory files are compared
1145 to its parent.
1145 to its parent.
1146
1146
1147 Alternatively you can specify -c/--change with a revision to see
1147 Alternatively you can specify -c/--change with a revision to see
1148 the changes in that changeset relative to its first parent.
1148 the changes in that changeset relative to its first parent.
1149
1149
1150 Without the -a/--text option, diff will avoid generating diffs of
1150 Without the -a/--text option, diff will avoid generating diffs of
1151 files it detects as binary. With -a, diff will generate a diff
1151 files it detects as binary. With -a, diff will generate a diff
1152 anyway, probably with undesirable results.
1152 anyway, probably with undesirable results.
1153
1153
1154 Use the -g/--git option to generate diffs in the git extended diff
1154 Use the -g/--git option to generate diffs in the git extended diff
1155 format. For more information, read :hg:`help diffs`.
1155 format. For more information, read :hg:`help diffs`.
1156 """
1156 """
1157
1157
1158 revs = opts.get('rev')
1158 revs = opts.get('rev')
1159 change = opts.get('change')
1159 change = opts.get('change')
1160 stat = opts.get('stat')
1160 stat = opts.get('stat')
1161 reverse = opts.get('reverse')
1161 reverse = opts.get('reverse')
1162
1162
1163 if revs and change:
1163 if revs and change:
1164 msg = _('cannot specify --rev and --change at the same time')
1164 msg = _('cannot specify --rev and --change at the same time')
1165 raise util.Abort(msg)
1165 raise util.Abort(msg)
1166 elif change:
1166 elif change:
1167 node2 = repo.lookup(change)
1167 node2 = repo.lookup(change)
1168 node1 = repo[node2].parents()[0].node()
1168 node1 = repo[node2].parents()[0].node()
1169 else:
1169 else:
1170 node1, node2 = cmdutil.revpair(repo, revs)
1170 node1, node2 = cmdutil.revpair(repo, revs)
1171
1171
1172 if reverse:
1172 if reverse:
1173 node1, node2 = node2, node1
1173 node1, node2 = node2, node1
1174
1174
1175 diffopts = patch.diffopts(ui, opts)
1175 diffopts = patch.diffopts(ui, opts)
1176 m = cmdutil.match(repo, pats, opts)
1176 m = cmdutil.match(repo, pats, opts)
1177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1178
1178
1179 def export(ui, repo, *changesets, **opts):
1179 def export(ui, repo, *changesets, **opts):
1180 """dump the header and diffs for one or more changesets
1180 """dump the header and diffs for one or more changesets
1181
1181
1182 Print the changeset header and diffs for one or more revisions.
1182 Print the changeset header and diffs for one or more revisions.
1183
1183
1184 The information shown in the changeset header is: author, date,
1184 The information shown in the changeset header is: author, date,
1185 branch name (if non-default), changeset hash, parent(s) and commit
1185 branch name (if non-default), changeset hash, parent(s) and commit
1186 comment.
1186 comment.
1187
1187
1188 NOTE: export may generate unexpected diff output for merge
1188 NOTE: export may generate unexpected diff output for merge
1189 changesets, as it will compare the merge changeset against its
1189 changesets, as it will compare the merge changeset against its
1190 first parent only.
1190 first parent only.
1191
1191
1192 Output may be to a file, in which case the name of the file is
1192 Output may be to a file, in which case the name of the file is
1193 given using a format string. The formatting rules are as follows:
1193 given using a format string. The formatting rules are as follows:
1194
1194
1195 :``%%``: literal "%" character
1195 :``%%``: literal "%" character
1196 :``%H``: changeset hash (40 bytes of hexadecimal)
1196 :``%H``: changeset hash (40 bytes of hexadecimal)
1197 :``%N``: number of patches being generated
1197 :``%N``: number of patches being generated
1198 :``%R``: changeset revision number
1198 :``%R``: changeset revision number
1199 :``%b``: basename of the exporting repository
1199 :``%b``: basename of the exporting repository
1200 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1200 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1201 :``%n``: zero-padded sequence number, starting at 1
1201 :``%n``: zero-padded sequence number, starting at 1
1202 :``%r``: zero-padded changeset revision number
1202 :``%r``: zero-padded changeset revision number
1203
1203
1204 Without the -a/--text option, export will avoid generating diffs
1204 Without the -a/--text option, export will avoid generating diffs
1205 of files it detects as binary. With -a, export will generate a
1205 of files it detects as binary. With -a, export will generate a
1206 diff anyway, probably with undesirable results.
1206 diff anyway, probably with undesirable results.
1207
1207
1208 Use the -g/--git option to generate diffs in the git extended diff
1208 Use the -g/--git option to generate diffs in the git extended diff
1209 format. See :hg:`help diffs` for more information.
1209 format. See :hg:`help diffs` for more information.
1210
1210
1211 With the --switch-parent option, the diff will be against the
1211 With the --switch-parent option, the diff will be against the
1212 second parent. It can be useful to review a merge.
1212 second parent. It can be useful to review a merge.
1213 """
1213 """
1214 changesets += tuple(opts.get('rev', []))
1214 changesets += tuple(opts.get('rev', []))
1215 if not changesets:
1215 if not changesets:
1216 raise util.Abort(_("export requires at least one changeset"))
1216 raise util.Abort(_("export requires at least one changeset"))
1217 revs = cmdutil.revrange(repo, changesets)
1217 revs = cmdutil.revrange(repo, changesets)
1218 if len(revs) > 1:
1218 if len(revs) > 1:
1219 ui.note(_('exporting patches:\n'))
1219 ui.note(_('exporting patches:\n'))
1220 else:
1220 else:
1221 ui.note(_('exporting patch:\n'))
1221 ui.note(_('exporting patch:\n'))
1222 cmdutil.export(repo, revs, template=opts.get('output'),
1222 cmdutil.export(repo, revs, template=opts.get('output'),
1223 switch_parent=opts.get('switch_parent'),
1223 switch_parent=opts.get('switch_parent'),
1224 opts=patch.diffopts(ui, opts))
1224 opts=patch.diffopts(ui, opts))
1225
1225
1226 def forget(ui, repo, *pats, **opts):
1226 def forget(ui, repo, *pats, **opts):
1227 """forget the specified files on the next commit
1227 """forget the specified files on the next commit
1228
1228
1229 Mark the specified files so they will no longer be tracked
1229 Mark the specified files so they will no longer be tracked
1230 after the next commit.
1230 after the next commit.
1231
1231
1232 This only removes files from the current branch, not from the
1232 This only removes files from the current branch, not from the
1233 entire project history, and it does not delete them from the
1233 entire project history, and it does not delete them from the
1234 working directory.
1234 working directory.
1235
1235
1236 To undo a forget before the next commit, see hg add.
1236 To undo a forget before the next commit, see hg add.
1237 """
1237 """
1238
1238
1239 if not pats:
1239 if not pats:
1240 raise util.Abort(_('no files specified'))
1240 raise util.Abort(_('no files specified'))
1241
1241
1242 m = cmdutil.match(repo, pats, opts)
1242 m = cmdutil.match(repo, pats, opts)
1243 s = repo.status(match=m, clean=True)
1243 s = repo.status(match=m, clean=True)
1244 forget = sorted(s[0] + s[1] + s[3] + s[6])
1244 forget = sorted(s[0] + s[1] + s[3] + s[6])
1245
1245
1246 for f in m.files():
1246 for f in m.files():
1247 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1247 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1248 ui.warn(_('not removing %s: file is already untracked\n')
1248 ui.warn(_('not removing %s: file is already untracked\n')
1249 % m.rel(f))
1249 % m.rel(f))
1250
1250
1251 for f in forget:
1251 for f in forget:
1252 if ui.verbose or not m.exact(f):
1252 if ui.verbose or not m.exact(f):
1253 ui.status(_('removing %s\n') % m.rel(f))
1253 ui.status(_('removing %s\n') % m.rel(f))
1254
1254
1255 repo.remove(forget, unlink=False)
1255 repo.remove(forget, unlink=False)
1256
1256
1257 def grep(ui, repo, pattern, *pats, **opts):
1257 def grep(ui, repo, pattern, *pats, **opts):
1258 """search for a pattern in specified files and revisions
1258 """search for a pattern in specified files and revisions
1259
1259
1260 Search revisions of files for a regular expression.
1260 Search revisions of files for a regular expression.
1261
1261
1262 This command behaves differently than Unix grep. It only accepts
1262 This command behaves differently than Unix grep. It only accepts
1263 Python/Perl regexps. It searches repository history, not the
1263 Python/Perl regexps. It searches repository history, not the
1264 working directory. It always prints the revision number in which a
1264 working directory. It always prints the revision number in which a
1265 match appears.
1265 match appears.
1266
1266
1267 By default, grep only prints output for the first revision of a
1267 By default, grep only prints output for the first revision of a
1268 file in which it finds a match. To get it to print every revision
1268 file in which it finds a match. To get it to print every revision
1269 that contains a change in match status ("-" for a match that
1269 that contains a change in match status ("-" for a match that
1270 becomes a non-match, or "+" for a non-match that becomes a match),
1270 becomes a non-match, or "+" for a non-match that becomes a match),
1271 use the --all flag.
1271 use the --all flag.
1272 """
1272 """
1273 reflags = 0
1273 reflags = 0
1274 if opts.get('ignore_case'):
1274 if opts.get('ignore_case'):
1275 reflags |= re.I
1275 reflags |= re.I
1276 try:
1276 try:
1277 regexp = re.compile(pattern, reflags)
1277 regexp = re.compile(pattern, reflags)
1278 except Exception, inst:
1278 except Exception, inst:
1279 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1279 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1280 return None
1280 return None
1281 sep, eol = ':', '\n'
1281 sep, eol = ':', '\n'
1282 if opts.get('print0'):
1282 if opts.get('print0'):
1283 sep = eol = '\0'
1283 sep = eol = '\0'
1284
1284
1285 getfile = util.lrucachefunc(repo.file)
1285 getfile = util.lrucachefunc(repo.file)
1286
1286
1287 def matchlines(body):
1287 def matchlines(body):
1288 begin = 0
1288 begin = 0
1289 linenum = 0
1289 linenum = 0
1290 while True:
1290 while True:
1291 match = regexp.search(body, begin)
1291 match = regexp.search(body, begin)
1292 if not match:
1292 if not match:
1293 break
1293 break
1294 mstart, mend = match.span()
1294 mstart, mend = match.span()
1295 linenum += body.count('\n', begin, mstart) + 1
1295 linenum += body.count('\n', begin, mstart) + 1
1296 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1296 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1297 begin = body.find('\n', mend) + 1 or len(body)
1297 begin = body.find('\n', mend) + 1 or len(body)
1298 lend = begin - 1
1298 lend = begin - 1
1299 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1299 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1300
1300
1301 class linestate(object):
1301 class linestate(object):
1302 def __init__(self, line, linenum, colstart, colend):
1302 def __init__(self, line, linenum, colstart, colend):
1303 self.line = line
1303 self.line = line
1304 self.linenum = linenum
1304 self.linenum = linenum
1305 self.colstart = colstart
1305 self.colstart = colstart
1306 self.colend = colend
1306 self.colend = colend
1307
1307
1308 def __hash__(self):
1308 def __hash__(self):
1309 return hash((self.linenum, self.line))
1309 return hash((self.linenum, self.line))
1310
1310
1311 def __eq__(self, other):
1311 def __eq__(self, other):
1312 return self.line == other.line
1312 return self.line == other.line
1313
1313
1314 matches = {}
1314 matches = {}
1315 copies = {}
1315 copies = {}
1316 def grepbody(fn, rev, body):
1316 def grepbody(fn, rev, body):
1317 matches[rev].setdefault(fn, [])
1317 matches[rev].setdefault(fn, [])
1318 m = matches[rev][fn]
1318 m = matches[rev][fn]
1319 for lnum, cstart, cend, line in matchlines(body):
1319 for lnum, cstart, cend, line in matchlines(body):
1320 s = linestate(line, lnum, cstart, cend)
1320 s = linestate(line, lnum, cstart, cend)
1321 m.append(s)
1321 m.append(s)
1322
1322
1323 def difflinestates(a, b):
1323 def difflinestates(a, b):
1324 sm = difflib.SequenceMatcher(None, a, b)
1324 sm = difflib.SequenceMatcher(None, a, b)
1325 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1325 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1326 if tag == 'insert':
1326 if tag == 'insert':
1327 for i in xrange(blo, bhi):
1327 for i in xrange(blo, bhi):
1328 yield ('+', b[i])
1328 yield ('+', b[i])
1329 elif tag == 'delete':
1329 elif tag == 'delete':
1330 for i in xrange(alo, ahi):
1330 for i in xrange(alo, ahi):
1331 yield ('-', a[i])
1331 yield ('-', a[i])
1332 elif tag == 'replace':
1332 elif tag == 'replace':
1333 for i in xrange(alo, ahi):
1333 for i in xrange(alo, ahi):
1334 yield ('-', a[i])
1334 yield ('-', a[i])
1335 for i in xrange(blo, bhi):
1335 for i in xrange(blo, bhi):
1336 yield ('+', b[i])
1336 yield ('+', b[i])
1337
1337
1338 def display(fn, ctx, pstates, states):
1338 def display(fn, ctx, pstates, states):
1339 rev = ctx.rev()
1339 rev = ctx.rev()
1340 datefunc = ui.quiet and util.shortdate or util.datestr
1340 datefunc = ui.quiet and util.shortdate or util.datestr
1341 found = False
1341 found = False
1342 filerevmatches = {}
1342 filerevmatches = {}
1343 if opts.get('all'):
1343 if opts.get('all'):
1344 iter = difflinestates(pstates, states)
1344 iter = difflinestates(pstates, states)
1345 else:
1345 else:
1346 iter = [('', l) for l in states]
1346 iter = [('', l) for l in states]
1347 for change, l in iter:
1347 for change, l in iter:
1348 cols = [fn, str(rev)]
1348 cols = [fn, str(rev)]
1349 before, match, after = None, None, None
1349 before, match, after = None, None, None
1350 if opts.get('line_number'):
1350 if opts.get('line_number'):
1351 cols.append(str(l.linenum))
1351 cols.append(str(l.linenum))
1352 if opts.get('all'):
1352 if opts.get('all'):
1353 cols.append(change)
1353 cols.append(change)
1354 if opts.get('user'):
1354 if opts.get('user'):
1355 cols.append(ui.shortuser(ctx.user()))
1355 cols.append(ui.shortuser(ctx.user()))
1356 if opts.get('date'):
1356 if opts.get('date'):
1357 cols.append(datefunc(ctx.date()))
1357 cols.append(datefunc(ctx.date()))
1358 if opts.get('files_with_matches'):
1358 if opts.get('files_with_matches'):
1359 c = (fn, rev)
1359 c = (fn, rev)
1360 if c in filerevmatches:
1360 if c in filerevmatches:
1361 continue
1361 continue
1362 filerevmatches[c] = 1
1362 filerevmatches[c] = 1
1363 else:
1363 else:
1364 before = l.line[:l.colstart]
1364 before = l.line[:l.colstart]
1365 match = l.line[l.colstart:l.colend]
1365 match = l.line[l.colstart:l.colend]
1366 after = l.line[l.colend:]
1366 after = l.line[l.colend:]
1367 ui.write(sep.join(cols))
1367 ui.write(sep.join(cols))
1368 if before is not None:
1368 if before is not None:
1369 ui.write(sep + before)
1369 ui.write(sep + before)
1370 ui.write(match, label='grep.match')
1370 ui.write(match, label='grep.match')
1371 ui.write(after)
1371 ui.write(after)
1372 ui.write(eol)
1372 ui.write(eol)
1373 found = True
1373 found = True
1374 return found
1374 return found
1375
1375
1376 skip = {}
1376 skip = {}
1377 revfiles = {}
1377 revfiles = {}
1378 matchfn = cmdutil.match(repo, pats, opts)
1378 matchfn = cmdutil.match(repo, pats, opts)
1379 found = False
1379 found = False
1380 follow = opts.get('follow')
1380 follow = opts.get('follow')
1381
1381
1382 def prep(ctx, fns):
1382 def prep(ctx, fns):
1383 rev = ctx.rev()
1383 rev = ctx.rev()
1384 pctx = ctx.parents()[0]
1384 pctx = ctx.parents()[0]
1385 parent = pctx.rev()
1385 parent = pctx.rev()
1386 matches.setdefault(rev, {})
1386 matches.setdefault(rev, {})
1387 matches.setdefault(parent, {})
1387 matches.setdefault(parent, {})
1388 files = revfiles.setdefault(rev, [])
1388 files = revfiles.setdefault(rev, [])
1389 for fn in fns:
1389 for fn in fns:
1390 flog = getfile(fn)
1390 flog = getfile(fn)
1391 try:
1391 try:
1392 fnode = ctx.filenode(fn)
1392 fnode = ctx.filenode(fn)
1393 except error.LookupError:
1393 except error.LookupError:
1394 continue
1394 continue
1395
1395
1396 copied = flog.renamed(fnode)
1396 copied = flog.renamed(fnode)
1397 copy = follow and copied and copied[0]
1397 copy = follow and copied and copied[0]
1398 if copy:
1398 if copy:
1399 copies.setdefault(rev, {})[fn] = copy
1399 copies.setdefault(rev, {})[fn] = copy
1400 if fn in skip:
1400 if fn in skip:
1401 if copy:
1401 if copy:
1402 skip[copy] = True
1402 skip[copy] = True
1403 continue
1403 continue
1404 files.append(fn)
1404 files.append(fn)
1405
1405
1406 if fn not in matches[rev]:
1406 if fn not in matches[rev]:
1407 grepbody(fn, rev, flog.read(fnode))
1407 grepbody(fn, rev, flog.read(fnode))
1408
1408
1409 pfn = copy or fn
1409 pfn = copy or fn
1410 if pfn not in matches[parent]:
1410 if pfn not in matches[parent]:
1411 try:
1411 try:
1412 fnode = pctx.filenode(pfn)
1412 fnode = pctx.filenode(pfn)
1413 grepbody(pfn, parent, flog.read(fnode))
1413 grepbody(pfn, parent, flog.read(fnode))
1414 except error.LookupError:
1414 except error.LookupError:
1415 pass
1415 pass
1416
1416
1417 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1417 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1418 rev = ctx.rev()
1418 rev = ctx.rev()
1419 parent = ctx.parents()[0].rev()
1419 parent = ctx.parents()[0].rev()
1420 for fn in sorted(revfiles.get(rev, [])):
1420 for fn in sorted(revfiles.get(rev, [])):
1421 states = matches[rev][fn]
1421 states = matches[rev][fn]
1422 copy = copies.get(rev, {}).get(fn)
1422 copy = copies.get(rev, {}).get(fn)
1423 if fn in skip:
1423 if fn in skip:
1424 if copy:
1424 if copy:
1425 skip[copy] = True
1425 skip[copy] = True
1426 continue
1426 continue
1427 pstates = matches.get(parent, {}).get(copy or fn, [])
1427 pstates = matches.get(parent, {}).get(copy or fn, [])
1428 if pstates or states:
1428 if pstates or states:
1429 r = display(fn, ctx, pstates, states)
1429 r = display(fn, ctx, pstates, states)
1430 found = found or r
1430 found = found or r
1431 if r and not opts.get('all'):
1431 if r and not opts.get('all'):
1432 skip[fn] = True
1432 skip[fn] = True
1433 if copy:
1433 if copy:
1434 skip[copy] = True
1434 skip[copy] = True
1435 del matches[rev]
1435 del matches[rev]
1436 del revfiles[rev]
1436 del revfiles[rev]
1437
1437
1438 def heads(ui, repo, *branchrevs, **opts):
1438 def heads(ui, repo, *branchrevs, **opts):
1439 """show current repository heads or show branch heads
1439 """show current repository heads or show branch heads
1440
1440
1441 With no arguments, show all repository branch heads.
1441 With no arguments, show all repository branch heads.
1442
1442
1443 Repository "heads" are changesets with no child changesets. They are
1443 Repository "heads" are changesets with no child changesets. They are
1444 where development generally takes place and are the usual targets
1444 where development generally takes place and are the usual targets
1445 for update and merge operations. Branch heads are changesets that have
1445 for update and merge operations. Branch heads are changesets that have
1446 no child changeset on the same branch.
1446 no child changeset on the same branch.
1447
1447
1448 If one or more REVs are given, only branch heads on the branches
1448 If one or more REVs are given, only branch heads on the branches
1449 associated with the specified changesets are shown.
1449 associated with the specified changesets are shown.
1450
1450
1451 If -c/--closed is specified, also show branch heads marked closed
1451 If -c/--closed is specified, also show branch heads marked closed
1452 (see hg commit --close-branch).
1452 (see hg commit --close-branch).
1453
1453
1454 If STARTREV is specified, only those heads that are descendants of
1454 If STARTREV is specified, only those heads that are descendants of
1455 STARTREV will be displayed.
1455 STARTREV will be displayed.
1456
1456
1457 If -t/--topo is specified, named branch mechanics will be ignored and only
1457 If -t/--topo is specified, named branch mechanics will be ignored and only
1458 changesets without children will be shown.
1458 changesets without children will be shown.
1459 """
1459 """
1460
1460
1461 if opts.get('rev'):
1461 if opts.get('rev'):
1462 start = repo.lookup(opts['rev'])
1462 start = repo.lookup(opts['rev'])
1463 else:
1463 else:
1464 start = None
1464 start = None
1465
1465
1466 if opts.get('topo'):
1466 if opts.get('topo'):
1467 heads = [repo[h] for h in repo.heads(start)]
1467 heads = [repo[h] for h in repo.heads(start)]
1468 else:
1468 else:
1469 heads = []
1469 heads = []
1470 for b, ls in repo.branchmap().iteritems():
1470 for b, ls in repo.branchmap().iteritems():
1471 if start is None:
1471 if start is None:
1472 heads += [repo[h] for h in ls]
1472 heads += [repo[h] for h in ls]
1473 continue
1473 continue
1474 startrev = repo.changelog.rev(start)
1474 startrev = repo.changelog.rev(start)
1475 descendants = set(repo.changelog.descendants(startrev))
1475 descendants = set(repo.changelog.descendants(startrev))
1476 descendants.add(startrev)
1476 descendants.add(startrev)
1477 rev = repo.changelog.rev
1477 rev = repo.changelog.rev
1478 heads += [repo[h] for h in ls if rev(h) in descendants]
1478 heads += [repo[h] for h in ls if rev(h) in descendants]
1479
1479
1480 if branchrevs:
1480 if branchrevs:
1481 decode, encode = encoding.fromlocal, encoding.tolocal
1481 decode, encode = encoding.fromlocal, encoding.tolocal
1482 branches = set(repo[decode(br)].branch() for br in branchrevs)
1482 branches = set(repo[decode(br)].branch() for br in branchrevs)
1483 heads = [h for h in heads if h.branch() in branches]
1483 heads = [h for h in heads if h.branch() in branches]
1484
1484
1485 if not opts.get('closed'):
1485 if not opts.get('closed'):
1486 heads = [h for h in heads if not h.extra().get('close')]
1486 heads = [h for h in heads if not h.extra().get('close')]
1487
1487
1488 if opts.get('active') and branchrevs:
1488 if opts.get('active') and branchrevs:
1489 dagheads = repo.heads(start)
1489 dagheads = repo.heads(start)
1490 heads = [h for h in heads if h.node() in dagheads]
1490 heads = [h for h in heads if h.node() in dagheads]
1491
1491
1492 if branchrevs:
1492 if branchrevs:
1493 haveheads = set(h.branch() for h in heads)
1493 haveheads = set(h.branch() for h in heads)
1494 if branches - haveheads:
1494 if branches - haveheads:
1495 headless = ', '.join(encode(b) for b in branches - haveheads)
1495 headless = ', '.join(encode(b) for b in branches - haveheads)
1496 msg = _('no open branch heads found on branches %s')
1496 msg = _('no open branch heads found on branches %s')
1497 if opts.get('rev'):
1497 if opts.get('rev'):
1498 msg += _(' (started at %s)' % opts['rev'])
1498 msg += _(' (started at %s)' % opts['rev'])
1499 ui.warn((msg + '\n') % headless)
1499 ui.warn((msg + '\n') % headless)
1500
1500
1501 if not heads:
1501 if not heads:
1502 return 1
1502 return 1
1503
1503
1504 heads = sorted(heads, key=lambda x: -x.rev())
1504 heads = sorted(heads, key=lambda x: -x.rev())
1505 displayer = cmdutil.show_changeset(ui, repo, opts)
1505 displayer = cmdutil.show_changeset(ui, repo, opts)
1506 for ctx in heads:
1506 for ctx in heads:
1507 displayer.show(ctx)
1507 displayer.show(ctx)
1508 displayer.close()
1508 displayer.close()
1509
1509
1510 def help_(ui, name=None, with_version=False, unknowncmd=False):
1510 def help_(ui, name=None, with_version=False, unknowncmd=False):
1511 """show help for a given topic or a help overview
1511 """show help for a given topic or a help overview
1512
1512
1513 With no arguments, print a list of commands with short help messages.
1513 With no arguments, print a list of commands with short help messages.
1514
1514
1515 Given a topic, extension, or command name, print help for that
1515 Given a topic, extension, or command name, print help for that
1516 topic."""
1516 topic."""
1517 option_lists = []
1517 option_lists = []
1518 textwidth = util.termwidth() - 2
1518 textwidth = util.termwidth() - 2
1519
1519
1520 def addglobalopts(aliases):
1520 def addglobalopts(aliases):
1521 if ui.verbose:
1521 if ui.verbose:
1522 option_lists.append((_("global options:"), globalopts))
1522 option_lists.append((_("global options:"), globalopts))
1523 if name == 'shortlist':
1523 if name == 'shortlist':
1524 option_lists.append((_('use "hg help" for the full list '
1524 option_lists.append((_('use "hg help" for the full list '
1525 'of commands'), ()))
1525 'of commands'), ()))
1526 else:
1526 else:
1527 if name == 'shortlist':
1527 if name == 'shortlist':
1528 msg = _('use "hg help" for the full list of commands '
1528 msg = _('use "hg help" for the full list of commands '
1529 'or "hg -v" for details')
1529 'or "hg -v" for details')
1530 elif aliases:
1530 elif aliases:
1531 msg = _('use "hg -v help%s" to show aliases and '
1531 msg = _('use "hg -v help%s" to show aliases and '
1532 'global options') % (name and " " + name or "")
1532 'global options') % (name and " " + name or "")
1533 else:
1533 else:
1534 msg = _('use "hg -v help %s" to show global options') % name
1534 msg = _('use "hg -v help %s" to show global options') % name
1535 option_lists.append((msg, ()))
1535 option_lists.append((msg, ()))
1536
1536
1537 def helpcmd(name):
1537 def helpcmd(name):
1538 if with_version:
1538 if with_version:
1539 version_(ui)
1539 version_(ui)
1540 ui.write('\n')
1540 ui.write('\n')
1541
1541
1542 try:
1542 try:
1543 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1543 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1544 except error.AmbiguousCommand, inst:
1544 except error.AmbiguousCommand, inst:
1545 # py3k fix: except vars can't be used outside the scope of the
1545 # py3k fix: except vars can't be used outside the scope of the
1546 # except block, nor can be used inside a lambda. python issue4617
1546 # except block, nor can be used inside a lambda. python issue4617
1547 prefix = inst.args[0]
1547 prefix = inst.args[0]
1548 select = lambda c: c.lstrip('^').startswith(prefix)
1548 select = lambda c: c.lstrip('^').startswith(prefix)
1549 helplist(_('list of commands:\n\n'), select)
1549 helplist(_('list of commands:\n\n'), select)
1550 return
1550 return
1551
1551
1552 # check if it's an invalid alias and display its error if it is
1552 # check if it's an invalid alias and display its error if it is
1553 if getattr(entry[0], 'badalias', False):
1553 if getattr(entry[0], 'badalias', False):
1554 if not unknowncmd:
1554 if not unknowncmd:
1555 entry[0](ui)
1555 entry[0](ui)
1556 return
1556 return
1557
1557
1558 # synopsis
1558 # synopsis
1559 if len(entry) > 2:
1559 if len(entry) > 2:
1560 if entry[2].startswith('hg'):
1560 if entry[2].startswith('hg'):
1561 ui.write("%s\n" % entry[2])
1561 ui.write("%s\n" % entry[2])
1562 else:
1562 else:
1563 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1563 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1564 else:
1564 else:
1565 ui.write('hg %s\n' % aliases[0])
1565 ui.write('hg %s\n' % aliases[0])
1566
1566
1567 # aliases
1567 # aliases
1568 if not ui.quiet and len(aliases) > 1:
1568 if not ui.quiet and len(aliases) > 1:
1569 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1569 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1570
1570
1571 # description
1571 # description
1572 doc = gettext(entry[0].__doc__)
1572 doc = gettext(entry[0].__doc__)
1573 if not doc:
1573 if not doc:
1574 doc = _("(no help text available)")
1574 doc = _("(no help text available)")
1575 if hasattr(entry[0], 'definition'): # aliased command
1575 if hasattr(entry[0], 'definition'): # aliased command
1576 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1576 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1577 if ui.quiet:
1577 if ui.quiet:
1578 doc = doc.splitlines()[0]
1578 doc = doc.splitlines()[0]
1579 keep = ui.verbose and ['verbose'] or []
1579 keep = ui.verbose and ['verbose'] or []
1580 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1580 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1581 ui.write("\n%s\n" % formatted)
1581 ui.write("\n%s\n" % formatted)
1582 if pruned:
1582 if pruned:
1583 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1583 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1584
1584
1585 if not ui.quiet:
1585 if not ui.quiet:
1586 # options
1586 # options
1587 if entry[1]:
1587 if entry[1]:
1588 option_lists.append((_("options:\n"), entry[1]))
1588 option_lists.append((_("options:\n"), entry[1]))
1589
1589
1590 addglobalopts(False)
1590 addglobalopts(False)
1591
1591
1592 def helplist(header, select=None):
1592 def helplist(header, select=None):
1593 h = {}
1593 h = {}
1594 cmds = {}
1594 cmds = {}
1595 for c, e in table.iteritems():
1595 for c, e in table.iteritems():
1596 f = c.split("|", 1)[0]
1596 f = c.split("|", 1)[0]
1597 if select and not select(f):
1597 if select and not select(f):
1598 continue
1598 continue
1599 if (not select and name != 'shortlist' and
1599 if (not select and name != 'shortlist' and
1600 e[0].__module__ != __name__):
1600 e[0].__module__ != __name__):
1601 continue
1601 continue
1602 if name == "shortlist" and not f.startswith("^"):
1602 if name == "shortlist" and not f.startswith("^"):
1603 continue
1603 continue
1604 f = f.lstrip("^")
1604 f = f.lstrip("^")
1605 if not ui.debugflag and f.startswith("debug"):
1605 if not ui.debugflag and f.startswith("debug"):
1606 continue
1606 continue
1607 doc = e[0].__doc__
1607 doc = e[0].__doc__
1608 if doc and 'DEPRECATED' in doc and not ui.verbose:
1608 if doc and 'DEPRECATED' in doc and not ui.verbose:
1609 continue
1609 continue
1610 doc = gettext(doc)
1610 doc = gettext(doc)
1611 if not doc:
1611 if not doc:
1612 doc = _("(no help text available)")
1612 doc = _("(no help text available)")
1613 h[f] = doc.splitlines()[0].rstrip()
1613 h[f] = doc.splitlines()[0].rstrip()
1614 cmds[f] = c.lstrip("^")
1614 cmds[f] = c.lstrip("^")
1615
1615
1616 if not h:
1616 if not h:
1617 ui.status(_('no commands defined\n'))
1617 ui.status(_('no commands defined\n'))
1618 return
1618 return
1619
1619
1620 ui.status(header)
1620 ui.status(header)
1621 fns = sorted(h)
1621 fns = sorted(h)
1622 m = max(map(len, fns))
1622 m = max(map(len, fns))
1623 for f in fns:
1623 for f in fns:
1624 if ui.verbose:
1624 if ui.verbose:
1625 commands = cmds[f].replace("|",", ")
1625 commands = cmds[f].replace("|",", ")
1626 ui.write(" %s:\n %s\n"%(commands, h[f]))
1626 ui.write(" %s:\n %s\n"%(commands, h[f]))
1627 else:
1627 else:
1628 ui.write(' %-*s %s\n' % (m, f, util.wrap(h[f], m + 4)))
1628 ui.write(' %-*s %s\n' % (m, f, util.wrap(h[f], m + 4)))
1629
1629
1630 if not ui.quiet:
1630 if not ui.quiet:
1631 addglobalopts(True)
1631 addglobalopts(True)
1632
1632
1633 def helptopic(name):
1633 def helptopic(name):
1634 for names, header, doc in help.helptable:
1634 for names, header, doc in help.helptable:
1635 if name in names:
1635 if name in names:
1636 break
1636 break
1637 else:
1637 else:
1638 raise error.UnknownCommand(name)
1638 raise error.UnknownCommand(name)
1639
1639
1640 # description
1640 # description
1641 if not doc:
1641 if not doc:
1642 doc = _("(no help text available)")
1642 doc = _("(no help text available)")
1643 if hasattr(doc, '__call__'):
1643 if hasattr(doc, '__call__'):
1644 doc = doc()
1644 doc = doc()
1645
1645
1646 ui.write("%s\n\n" % header)
1646 ui.write("%s\n\n" % header)
1647 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1647 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1648
1648
1649 def helpext(name):
1649 def helpext(name):
1650 try:
1650 try:
1651 mod = extensions.find(name)
1651 mod = extensions.find(name)
1652 doc = gettext(mod.__doc__) or _('no help text available')
1652 doc = gettext(mod.__doc__) or _('no help text available')
1653 except KeyError:
1653 except KeyError:
1654 mod = None
1654 mod = None
1655 doc = extensions.disabledext(name)
1655 doc = extensions.disabledext(name)
1656 if not doc:
1656 if not doc:
1657 raise error.UnknownCommand(name)
1657 raise error.UnknownCommand(name)
1658
1658
1659 if '\n' not in doc:
1659 if '\n' not in doc:
1660 head, tail = doc, ""
1660 head, tail = doc, ""
1661 else:
1661 else:
1662 head, tail = doc.split('\n', 1)
1662 head, tail = doc.split('\n', 1)
1663 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1663 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1664 if tail:
1664 if tail:
1665 ui.write(minirst.format(tail, textwidth))
1665 ui.write(minirst.format(tail, textwidth))
1666 ui.status('\n\n')
1666 ui.status('\n\n')
1667
1667
1668 if mod:
1668 if mod:
1669 try:
1669 try:
1670 ct = mod.cmdtable
1670 ct = mod.cmdtable
1671 except AttributeError:
1671 except AttributeError:
1672 ct = {}
1672 ct = {}
1673 modcmds = set([c.split('|', 1)[0] for c in ct])
1673 modcmds = set([c.split('|', 1)[0] for c in ct])
1674 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1674 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1675 else:
1675 else:
1676 ui.write(_('use "hg help extensions" for information on enabling '
1676 ui.write(_('use "hg help extensions" for information on enabling '
1677 'extensions\n'))
1677 'extensions\n'))
1678
1678
1679 def helpextcmd(name):
1679 def helpextcmd(name):
1680 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1680 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1681 doc = gettext(mod.__doc__).splitlines()[0]
1681 doc = gettext(mod.__doc__).splitlines()[0]
1682
1682
1683 msg = help.listexts(_("'%s' is provided by the following "
1683 msg = help.listexts(_("'%s' is provided by the following "
1684 "extension:") % cmd, {ext: doc}, len(ext),
1684 "extension:") % cmd, {ext: doc}, len(ext),
1685 indent=4)
1685 indent=4)
1686 ui.write(minirst.format(msg, textwidth))
1686 ui.write(minirst.format(msg, textwidth))
1687 ui.write('\n\n')
1687 ui.write('\n\n')
1688 ui.write(_('use "hg help extensions" for information on enabling '
1688 ui.write(_('use "hg help extensions" for information on enabling '
1689 'extensions\n'))
1689 'extensions\n'))
1690
1690
1691 if name and name != 'shortlist':
1691 if name and name != 'shortlist':
1692 i = None
1692 i = None
1693 if unknowncmd:
1693 if unknowncmd:
1694 queries = (helpextcmd,)
1694 queries = (helpextcmd,)
1695 else:
1695 else:
1696 queries = (helptopic, helpcmd, helpext, helpextcmd)
1696 queries = (helptopic, helpcmd, helpext, helpextcmd)
1697 for f in queries:
1697 for f in queries:
1698 try:
1698 try:
1699 f(name)
1699 f(name)
1700 i = None
1700 i = None
1701 break
1701 break
1702 except error.UnknownCommand, inst:
1702 except error.UnknownCommand, inst:
1703 i = inst
1703 i = inst
1704 if i:
1704 if i:
1705 raise i
1705 raise i
1706
1706
1707 else:
1707 else:
1708 # program name
1708 # program name
1709 if ui.verbose or with_version:
1709 if ui.verbose or with_version:
1710 version_(ui)
1710 version_(ui)
1711 else:
1711 else:
1712 ui.status(_("Mercurial Distributed SCM\n"))
1712 ui.status(_("Mercurial Distributed SCM\n"))
1713 ui.status('\n')
1713 ui.status('\n')
1714
1714
1715 # list of commands
1715 # list of commands
1716 if name == "shortlist":
1716 if name == "shortlist":
1717 header = _('basic commands:\n\n')
1717 header = _('basic commands:\n\n')
1718 else:
1718 else:
1719 header = _('list of commands:\n\n')
1719 header = _('list of commands:\n\n')
1720
1720
1721 helplist(header)
1721 helplist(header)
1722 if name != 'shortlist':
1722 if name != 'shortlist':
1723 exts, maxlength = extensions.enabled()
1723 exts, maxlength = extensions.enabled()
1724 text = help.listexts(_('enabled extensions:'), exts, maxlength)
1724 text = help.listexts(_('enabled extensions:'), exts, maxlength)
1725 if text:
1725 if text:
1726 ui.write("\n%s\n" % minirst.format(text, textwidth))
1726 ui.write("\n%s\n" % minirst.format(text, textwidth))
1727
1727
1728 # list all option lists
1728 # list all option lists
1729 opt_output = []
1729 opt_output = []
1730 for title, options in option_lists:
1730 for title, options in option_lists:
1731 opt_output.append(("\n%s" % title, None))
1731 opt_output.append(("\n%s" % title, None))
1732 for shortopt, longopt, default, desc in options:
1732 for shortopt, longopt, default, desc in options:
1733 if _("DEPRECATED") in desc and not ui.verbose:
1733 if _("DEPRECATED") in desc and not ui.verbose:
1734 continue
1734 continue
1735 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1735 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1736 longopt and " --%s" % longopt),
1736 longopt and " --%s" % longopt),
1737 "%s%s" % (desc,
1737 "%s%s" % (desc,
1738 default
1738 default
1739 and _(" (default: %s)") % default
1739 and _(" (default: %s)") % default
1740 or "")))
1740 or "")))
1741
1741
1742 if not name:
1742 if not name:
1743 ui.write(_("\nadditional help topics:\n\n"))
1743 ui.write(_("\nadditional help topics:\n\n"))
1744 topics = []
1744 topics = []
1745 for names, header, doc in help.helptable:
1745 for names, header, doc in help.helptable:
1746 topics.append((sorted(names, key=len, reverse=True)[0], header))
1746 topics.append((sorted(names, key=len, reverse=True)[0], header))
1747 topics_len = max([len(s[0]) for s in topics])
1747 topics_len = max([len(s[0]) for s in topics])
1748 for t, desc in topics:
1748 for t, desc in topics:
1749 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1749 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1750
1750
1751 if opt_output:
1751 if opt_output:
1752 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1752 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1753 for first, second in opt_output:
1753 for first, second in opt_output:
1754 if second:
1754 if second:
1755 second = util.wrap(second, opts_len + 3)
1755 second = util.wrap(second, opts_len + 3)
1756 ui.write(" %-*s %s\n" % (opts_len, first, second))
1756 ui.write(" %-*s %s\n" % (opts_len, first, second))
1757 else:
1757 else:
1758 ui.write("%s\n" % first)
1758 ui.write("%s\n" % first)
1759
1759
1760 def identify(ui, repo, source=None,
1760 def identify(ui, repo, source=None,
1761 rev=None, num=None, id=None, branch=None, tags=None):
1761 rev=None, num=None, id=None, branch=None, tags=None):
1762 """identify the working copy or specified revision
1762 """identify the working copy or specified revision
1763
1763
1764 With no revision, print a summary of the current state of the
1764 With no revision, print a summary of the current state of the
1765 repository.
1765 repository.
1766
1766
1767 Specifying a path to a repository root or Mercurial bundle will
1767 Specifying a path to a repository root or Mercurial bundle will
1768 cause lookup to operate on that repository/bundle.
1768 cause lookup to operate on that repository/bundle.
1769
1769
1770 This summary identifies the repository state using one or two
1770 This summary identifies the repository state using one or two
1771 parent hash identifiers, followed by a "+" if there are
1771 parent hash identifiers, followed by a "+" if there are
1772 uncommitted changes in the working directory, a list of tags for
1772 uncommitted changes in the working directory, a list of tags for
1773 this revision and a branch name for non-default branches.
1773 this revision and a branch name for non-default branches.
1774 """
1774 """
1775
1775
1776 if not repo and not source:
1776 if not repo and not source:
1777 raise util.Abort(_("There is no Mercurial repository here "
1777 raise util.Abort(_("There is no Mercurial repository here "
1778 "(.hg not found)"))
1778 "(.hg not found)"))
1779
1779
1780 hexfunc = ui.debugflag and hex or short
1780 hexfunc = ui.debugflag and hex or short
1781 default = not (num or id or branch or tags)
1781 default = not (num or id or branch or tags)
1782 output = []
1782 output = []
1783
1783
1784 revs = []
1784 revs = []
1785 if source:
1785 if source:
1786 source, branches = hg.parseurl(ui.expandpath(source))
1786 source, branches = hg.parseurl(ui.expandpath(source))
1787 repo = hg.repository(ui, source)
1787 repo = hg.repository(ui, source)
1788 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
1788 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
1789
1789
1790 if not repo.local():
1790 if not repo.local():
1791 if not rev and revs:
1791 if not rev and revs:
1792 rev = revs[0]
1792 rev = revs[0]
1793 if not rev:
1793 if not rev:
1794 rev = "tip"
1794 rev = "tip"
1795 if num or branch or tags:
1795 if num or branch or tags:
1796 raise util.Abort(
1796 raise util.Abort(
1797 "can't query remote revision number, branch, or tags")
1797 "can't query remote revision number, branch, or tags")
1798 output = [hexfunc(repo.lookup(rev))]
1798 output = [hexfunc(repo.lookup(rev))]
1799 elif not rev:
1799 elif not rev:
1800 ctx = repo[None]
1800 ctx = repo[None]
1801 parents = ctx.parents()
1801 parents = ctx.parents()
1802 changed = False
1802 changed = False
1803 if default or id or num:
1803 if default or id or num:
1804 changed = util.any(repo.status())
1804 changed = util.any(repo.status())
1805 if default or id:
1805 if default or id:
1806 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1806 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1807 (changed) and "+" or "")]
1807 (changed) and "+" or "")]
1808 if num:
1808 if num:
1809 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1809 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1810 (changed) and "+" or ""))
1810 (changed) and "+" or ""))
1811 else:
1811 else:
1812 ctx = repo[rev]
1812 ctx = repo[rev]
1813 if default or id:
1813 if default or id:
1814 output = [hexfunc(ctx.node())]
1814 output = [hexfunc(ctx.node())]
1815 if num:
1815 if num:
1816 output.append(str(ctx.rev()))
1816 output.append(str(ctx.rev()))
1817
1817
1818 if repo.local() and default and not ui.quiet:
1818 if repo.local() and default and not ui.quiet:
1819 b = encoding.tolocal(ctx.branch())
1819 b = encoding.tolocal(ctx.branch())
1820 if b != 'default':
1820 if b != 'default':
1821 output.append("(%s)" % b)
1821 output.append("(%s)" % b)
1822
1822
1823 # multiple tags for a single parent separated by '/'
1823 # multiple tags for a single parent separated by '/'
1824 t = "/".join(ctx.tags())
1824 t = "/".join(ctx.tags())
1825 if t:
1825 if t:
1826 output.append(t)
1826 output.append(t)
1827
1827
1828 if branch:
1828 if branch:
1829 output.append(encoding.tolocal(ctx.branch()))
1829 output.append(encoding.tolocal(ctx.branch()))
1830
1830
1831 if tags:
1831 if tags:
1832 output.extend(ctx.tags())
1832 output.extend(ctx.tags())
1833
1833
1834 ui.write("%s\n" % ' '.join(output))
1834 ui.write("%s\n" % ' '.join(output))
1835
1835
1836 def import_(ui, repo, patch1, *patches, **opts):
1836 def import_(ui, repo, patch1, *patches, **opts):
1837 """import an ordered set of patches
1837 """import an ordered set of patches
1838
1838
1839 Import a list of patches and commit them individually (unless
1839 Import a list of patches and commit them individually (unless
1840 --no-commit is specified).
1840 --no-commit is specified).
1841
1841
1842 If there are outstanding changes in the working directory, import
1842 If there are outstanding changes in the working directory, import
1843 will abort unless given the -f/--force flag.
1843 will abort unless given the -f/--force flag.
1844
1844
1845 You can import a patch straight from a mail message. Even patches
1845 You can import a patch straight from a mail message. Even patches
1846 as attachments work (to use the body part, it must have type
1846 as attachments work (to use the body part, it must have type
1847 text/plain or text/x-patch). From and Subject headers of email
1847 text/plain or text/x-patch). From and Subject headers of email
1848 message are used as default committer and commit message. All
1848 message are used as default committer and commit message. All
1849 text/plain body parts before first diff are added to commit
1849 text/plain body parts before first diff are added to commit
1850 message.
1850 message.
1851
1851
1852 If the imported patch was generated by hg export, user and
1852 If the imported patch was generated by hg export, user and
1853 description from patch override values from message headers and
1853 description from patch override values from message headers and
1854 body. Values given on command line with -m/--message and -u/--user
1854 body. Values given on command line with -m/--message and -u/--user
1855 override these.
1855 override these.
1856
1856
1857 If --exact is specified, import will set the working directory to
1857 If --exact is specified, import will set the working directory to
1858 the parent of each patch before applying it, and will abort if the
1858 the parent of each patch before applying it, and will abort if the
1859 resulting changeset has a different ID than the one recorded in
1859 resulting changeset has a different ID than the one recorded in
1860 the patch. This may happen due to character set problems or other
1860 the patch. This may happen due to character set problems or other
1861 deficiencies in the text patch format.
1861 deficiencies in the text patch format.
1862
1862
1863 With -s/--similarity, hg will attempt to discover renames and
1863 With -s/--similarity, hg will attempt to discover renames and
1864 copies in the patch in the same way as 'addremove'.
1864 copies in the patch in the same way as 'addremove'.
1865
1865
1866 To read a patch from standard input, use "-" as the patch name. If
1866 To read a patch from standard input, use "-" as the patch name. If
1867 a URL is specified, the patch will be downloaded from it.
1867 a URL is specified, the patch will be downloaded from it.
1868 See :hg:`help dates` for a list of formats valid for -d/--date.
1868 See :hg:`help dates` for a list of formats valid for -d/--date.
1869 """
1869 """
1870 patches = (patch1,) + patches
1870 patches = (patch1,) + patches
1871
1871
1872 date = opts.get('date')
1872 date = opts.get('date')
1873 if date:
1873 if date:
1874 opts['date'] = util.parsedate(date)
1874 opts['date'] = util.parsedate(date)
1875
1875
1876 try:
1876 try:
1877 sim = float(opts.get('similarity') or 0)
1877 sim = float(opts.get('similarity') or 0)
1878 except ValueError:
1878 except ValueError:
1879 raise util.Abort(_('similarity must be a number'))
1879 raise util.Abort(_('similarity must be a number'))
1880 if sim < 0 or sim > 100:
1880 if sim < 0 or sim > 100:
1881 raise util.Abort(_('similarity must be between 0 and 100'))
1881 raise util.Abort(_('similarity must be between 0 and 100'))
1882
1882
1883 if opts.get('exact') or not opts.get('force'):
1883 if opts.get('exact') or not opts.get('force'):
1884 cmdutil.bail_if_changed(repo)
1884 cmdutil.bail_if_changed(repo)
1885
1885
1886 d = opts["base"]
1886 d = opts["base"]
1887 strip = opts["strip"]
1887 strip = opts["strip"]
1888 wlock = lock = None
1888 wlock = lock = None
1889
1889
1890 def tryone(ui, hunk):
1890 def tryone(ui, hunk):
1891 tmpname, message, user, date, branch, nodeid, p1, p2 = \
1891 tmpname, message, user, date, branch, nodeid, p1, p2 = \
1892 patch.extract(ui, hunk)
1892 patch.extract(ui, hunk)
1893
1893
1894 if not tmpname:
1894 if not tmpname:
1895 return None
1895 return None
1896 commitid = _('to working directory')
1896 commitid = _('to working directory')
1897
1897
1898 try:
1898 try:
1899 cmdline_message = cmdutil.logmessage(opts)
1899 cmdline_message = cmdutil.logmessage(opts)
1900 if cmdline_message:
1900 if cmdline_message:
1901 # pickup the cmdline msg
1901 # pickup the cmdline msg
1902 message = cmdline_message
1902 message = cmdline_message
1903 elif message:
1903 elif message:
1904 # pickup the patch msg
1904 # pickup the patch msg
1905 message = message.strip()
1905 message = message.strip()
1906 else:
1906 else:
1907 # launch the editor
1907 # launch the editor
1908 message = None
1908 message = None
1909 ui.debug('message:\n%s\n' % message)
1909 ui.debug('message:\n%s\n' % message)
1910
1910
1911 wp = repo.parents()
1911 wp = repo.parents()
1912 if opts.get('exact'):
1912 if opts.get('exact'):
1913 if not nodeid or not p1:
1913 if not nodeid or not p1:
1914 raise util.Abort(_('not a Mercurial patch'))
1914 raise util.Abort(_('not a Mercurial patch'))
1915 p1 = repo.lookup(p1)
1915 p1 = repo.lookup(p1)
1916 p2 = repo.lookup(p2 or hex(nullid))
1916 p2 = repo.lookup(p2 or hex(nullid))
1917
1917
1918 if p1 != wp[0].node():
1918 if p1 != wp[0].node():
1919 hg.clean(repo, p1)
1919 hg.clean(repo, p1)
1920 repo.dirstate.setparents(p1, p2)
1920 repo.dirstate.setparents(p1, p2)
1921 elif p2:
1921 elif p2:
1922 try:
1922 try:
1923 p1 = repo.lookup(p1)
1923 p1 = repo.lookup(p1)
1924 p2 = repo.lookup(p2)
1924 p2 = repo.lookup(p2)
1925 if p1 == wp[0].node():
1925 if p1 == wp[0].node():
1926 repo.dirstate.setparents(p1, p2)
1926 repo.dirstate.setparents(p1, p2)
1927 except error.RepoError:
1927 except error.RepoError:
1928 pass
1928 pass
1929 if opts.get('exact') or opts.get('import_branch'):
1929 if opts.get('exact') or opts.get('import_branch'):
1930 repo.dirstate.setbranch(branch or 'default')
1930 repo.dirstate.setbranch(branch or 'default')
1931
1931
1932 files = {}
1932 files = {}
1933 try:
1933 try:
1934 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1934 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1935 files=files, eolmode=None)
1935 files=files, eolmode=None)
1936 finally:
1936 finally:
1937 files = patch.updatedir(ui, repo, files,
1937 files = patch.updatedir(ui, repo, files,
1938 similarity=sim / 100.0)
1938 similarity=sim / 100.0)
1939 if not opts.get('no_commit'):
1939 if not opts.get('no_commit'):
1940 if opts.get('exact'):
1940 if opts.get('exact'):
1941 m = None
1941 m = None
1942 else:
1942 else:
1943 m = cmdutil.matchfiles(repo, files or [])
1943 m = cmdutil.matchfiles(repo, files or [])
1944 n = repo.commit(message, opts.get('user') or user,
1944 n = repo.commit(message, opts.get('user') or user,
1945 opts.get('date') or date, match=m,
1945 opts.get('date') or date, match=m,
1946 editor=cmdutil.commiteditor)
1946 editor=cmdutil.commiteditor)
1947 if opts.get('exact'):
1947 if opts.get('exact'):
1948 if hex(n) != nodeid:
1948 if hex(n) != nodeid:
1949 repo.rollback()
1949 repo.rollback()
1950 raise util.Abort(_('patch is damaged'
1950 raise util.Abort(_('patch is damaged'
1951 ' or loses information'))
1951 ' or loses information'))
1952 # Force a dirstate write so that the next transaction
1952 # Force a dirstate write so that the next transaction
1953 # backups an up-do-date file.
1953 # backups an up-do-date file.
1954 repo.dirstate.write()
1954 repo.dirstate.write()
1955 if n:
1955 if n:
1956 commitid = short(n)
1956 commitid = short(n)
1957
1957
1958 return commitid
1958 return commitid
1959 finally:
1959 finally:
1960 os.unlink(tmpname)
1960 os.unlink(tmpname)
1961
1961
1962 try:
1962 try:
1963 wlock = repo.wlock()
1963 wlock = repo.wlock()
1964 lock = repo.lock()
1964 lock = repo.lock()
1965 lastcommit = None
1965 lastcommit = None
1966 for p in patches:
1966 for p in patches:
1967 pf = os.path.join(d, p)
1967 pf = os.path.join(d, p)
1968
1968
1969 if pf == '-':
1969 if pf == '-':
1970 ui.status(_("applying patch from stdin\n"))
1970 ui.status(_("applying patch from stdin\n"))
1971 pf = sys.stdin
1971 pf = sys.stdin
1972 else:
1972 else:
1973 ui.status(_("applying %s\n") % p)
1973 ui.status(_("applying %s\n") % p)
1974 pf = url.open(ui, pf)
1974 pf = url.open(ui, pf)
1975
1975
1976 haspatch = False
1976 haspatch = False
1977 for hunk in patch.split(pf):
1977 for hunk in patch.split(pf):
1978 commitid = tryone(ui, hunk)
1978 commitid = tryone(ui, hunk)
1979 if commitid:
1979 if commitid:
1980 haspatch = True
1980 haspatch = True
1981 if lastcommit:
1981 if lastcommit:
1982 ui.status(_('applied %s\n') % lastcommit)
1982 ui.status(_('applied %s\n') % lastcommit)
1983 lastcommit = commitid
1983 lastcommit = commitid
1984
1984
1985 if not haspatch:
1985 if not haspatch:
1986 raise util.Abort(_('no diffs found'))
1986 raise util.Abort(_('no diffs found'))
1987
1987
1988 finally:
1988 finally:
1989 release(lock, wlock)
1989 release(lock, wlock)
1990
1990
1991 def incoming(ui, repo, source="default", **opts):
1991 def incoming(ui, repo, source="default", **opts):
1992 """show new changesets found in source
1992 """show new changesets found in source
1993
1993
1994 Show new changesets found in the specified path/URL or the default
1994 Show new changesets found in the specified path/URL or the default
1995 pull location. These are the changesets that would have been pulled
1995 pull location. These are the changesets that would have been pulled
1996 if a pull at the time you issued this command.
1996 if a pull at the time you issued this command.
1997
1997
1998 For remote repository, using --bundle avoids downloading the
1998 For remote repository, using --bundle avoids downloading the
1999 changesets twice if the incoming is followed by a pull.
1999 changesets twice if the incoming is followed by a pull.
2000
2000
2001 See pull for valid source format details.
2001 See pull for valid source format details.
2002 """
2002 """
2003 limit = cmdutil.loglimit(opts)
2003 limit = cmdutil.loglimit(opts)
2004 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2004 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2005 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2005 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2006 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2006 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2007 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2007 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2008 if revs:
2008 if revs:
2009 revs = [other.lookup(rev) for rev in revs]
2009 revs = [other.lookup(rev) for rev in revs]
2010 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
2010 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
2011 force=opts["force"])
2011 force=opts["force"])
2012 if not incoming:
2012 if not incoming:
2013 try:
2013 try:
2014 os.unlink(opts["bundle"])
2014 os.unlink(opts["bundle"])
2015 except:
2015 except:
2016 pass
2016 pass
2017 ui.status(_("no changes found\n"))
2017 ui.status(_("no changes found\n"))
2018 return 1
2018 return 1
2019
2019
2020 cleanup = None
2020 cleanup = None
2021 try:
2021 try:
2022 fname = opts["bundle"]
2022 fname = opts["bundle"]
2023 if fname or not other.local():
2023 if fname or not other.local():
2024 # create a bundle (uncompressed if other repo is not local)
2024 # create a bundle (uncompressed if other repo is not local)
2025
2025
2026 if revs is None and other.capable('changegroupsubset'):
2026 if revs is None and other.capable('changegroupsubset'):
2027 revs = rheads
2027 revs = rheads
2028
2028
2029 if revs is None:
2029 if revs is None:
2030 cg = other.changegroup(incoming, "incoming")
2030 cg = other.changegroup(incoming, "incoming")
2031 else:
2031 else:
2032 cg = other.changegroupsubset(incoming, revs, 'incoming')
2032 cg = other.changegroupsubset(incoming, revs, 'incoming')
2033 bundletype = other.local() and "HG10BZ" or "HG10UN"
2033 bundletype = other.local() and "HG10BZ" or "HG10UN"
2034 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2034 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2035 # keep written bundle?
2035 # keep written bundle?
2036 if opts["bundle"]:
2036 if opts["bundle"]:
2037 cleanup = None
2037 cleanup = None
2038 if not other.local():
2038 if not other.local():
2039 # use the created uncompressed bundlerepo
2039 # use the created uncompressed bundlerepo
2040 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2040 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2041
2041
2042 o = other.changelog.nodesbetween(incoming, revs)[0]
2042 o = other.changelog.nodesbetween(incoming, revs)[0]
2043 if opts.get('newest_first'):
2043 if opts.get('newest_first'):
2044 o.reverse()
2044 o.reverse()
2045 displayer = cmdutil.show_changeset(ui, other, opts)
2045 displayer = cmdutil.show_changeset(ui, other, opts)
2046 count = 0
2046 count = 0
2047 for n in o:
2047 for n in o:
2048 if limit is not None and count >= limit:
2048 if limit is not None and count >= limit:
2049 break
2049 break
2050 parents = [p for p in other.changelog.parents(n) if p != nullid]
2050 parents = [p for p in other.changelog.parents(n) if p != nullid]
2051 if opts.get('no_merges') and len(parents) == 2:
2051 if opts.get('no_merges') and len(parents) == 2:
2052 continue
2052 continue
2053 count += 1
2053 count += 1
2054 displayer.show(other[n])
2054 displayer.show(other[n])
2055 displayer.close()
2055 displayer.close()
2056 finally:
2056 finally:
2057 if hasattr(other, 'close'):
2057 if hasattr(other, 'close'):
2058 other.close()
2058 other.close()
2059 if cleanup:
2059 if cleanup:
2060 os.unlink(cleanup)
2060 os.unlink(cleanup)
2061
2061
2062 def init(ui, dest=".", **opts):
2062 def init(ui, dest=".", **opts):
2063 """create a new repository in the given directory
2063 """create a new repository in the given directory
2064
2064
2065 Initialize a new repository in the given directory. If the given
2065 Initialize a new repository in the given directory. If the given
2066 directory does not exist, it will be created.
2066 directory does not exist, it will be created.
2067
2067
2068 If no directory is given, the current directory is used.
2068 If no directory is given, the current directory is used.
2069
2069
2070 It is possible to specify an ``ssh://`` URL as the destination.
2070 It is possible to specify an ``ssh://`` URL as the destination.
2071 See :hg:`help urls` for more information.
2071 See :hg:`help urls` for more information.
2072 """
2072 """
2073 hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
2073 hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
2074
2074
2075 def locate(ui, repo, *pats, **opts):
2075 def locate(ui, repo, *pats, **opts):
2076 """locate files matching specific patterns
2076 """locate files matching specific patterns
2077
2077
2078 Print files under Mercurial control in the working directory whose
2078 Print files under Mercurial control in the working directory whose
2079 names match the given patterns.
2079 names match the given patterns.
2080
2080
2081 By default, this command searches all directories in the working
2081 By default, this command searches all directories in the working
2082 directory. To search just the current directory and its
2082 directory. To search just the current directory and its
2083 subdirectories, use "--include .".
2083 subdirectories, use "--include .".
2084
2084
2085 If no patterns are given to match, this command prints the names
2085 If no patterns are given to match, this command prints the names
2086 of all files under Mercurial control in the working directory.
2086 of all files under Mercurial control in the working directory.
2087
2087
2088 If you want to feed the output of this command into the "xargs"
2088 If you want to feed the output of this command into the "xargs"
2089 command, use the -0 option to both this command and "xargs". This
2089 command, use the -0 option to both this command and "xargs". This
2090 will avoid the problem of "xargs" treating single filenames that
2090 will avoid the problem of "xargs" treating single filenames that
2091 contain whitespace as multiple filenames.
2091 contain whitespace as multiple filenames.
2092 """
2092 """
2093 end = opts.get('print0') and '\0' or '\n'
2093 end = opts.get('print0') and '\0' or '\n'
2094 rev = opts.get('rev') or None
2094 rev = opts.get('rev') or None
2095
2095
2096 ret = 1
2096 ret = 1
2097 m = cmdutil.match(repo, pats, opts, default='relglob')
2097 m = cmdutil.match(repo, pats, opts, default='relglob')
2098 m.bad = lambda x, y: False
2098 m.bad = lambda x, y: False
2099 for abs in repo[rev].walk(m):
2099 for abs in repo[rev].walk(m):
2100 if not rev and abs not in repo.dirstate:
2100 if not rev and abs not in repo.dirstate:
2101 continue
2101 continue
2102 if opts.get('fullpath'):
2102 if opts.get('fullpath'):
2103 ui.write(repo.wjoin(abs), end)
2103 ui.write(repo.wjoin(abs), end)
2104 else:
2104 else:
2105 ui.write(((pats and m.rel(abs)) or abs), end)
2105 ui.write(((pats and m.rel(abs)) or abs), end)
2106 ret = 0
2106 ret = 0
2107
2107
2108 return ret
2108 return ret
2109
2109
2110 def log(ui, repo, *pats, **opts):
2110 def log(ui, repo, *pats, **opts):
2111 """show revision history of entire repository or files
2111 """show revision history of entire repository or files
2112
2112
2113 Print the revision history of the specified files or the entire
2113 Print the revision history of the specified files or the entire
2114 project.
2114 project.
2115
2115
2116 File history is shown without following rename or copy history of
2116 File history is shown without following rename or copy history of
2117 files. Use -f/--follow with a filename to follow history across
2117 files. Use -f/--follow with a filename to follow history across
2118 renames and copies. --follow without a filename will only show
2118 renames and copies. --follow without a filename will only show
2119 ancestors or descendants of the starting revision. --follow-first
2119 ancestors or descendants of the starting revision. --follow-first
2120 only follows the first parent of merge revisions.
2120 only follows the first parent of merge revisions.
2121
2121
2122 If no revision range is specified, the default is tip:0 unless
2122 If no revision range is specified, the default is tip:0 unless
2123 --follow is set, in which case the working directory parent is
2123 --follow is set, in which case the working directory parent is
2124 used as the starting revision.
2124 used as the starting revision.
2125
2125
2126 See :hg:`help dates` for a list of formats valid for -d/--date.
2126 See :hg:`help dates` for a list of formats valid for -d/--date.
2127
2127
2128 By default this command prints revision number and changeset id,
2128 By default this command prints revision number and changeset id,
2129 tags, non-trivial parents, user, date and time, and a summary for
2129 tags, non-trivial parents, user, date and time, and a summary for
2130 each commit. When the -v/--verbose switch is used, the list of
2130 each commit. When the -v/--verbose switch is used, the list of
2131 changed files and full commit message are shown.
2131 changed files and full commit message are shown.
2132
2132
2133 NOTE: log -p/--patch may generate unexpected diff output for merge
2133 NOTE: log -p/--patch may generate unexpected diff output for merge
2134 changesets, as it will only compare the merge changeset against
2134 changesets, as it will only compare the merge changeset against
2135 its first parent. Also, only files different from BOTH parents
2135 its first parent. Also, only files different from BOTH parents
2136 will appear in files:.
2136 will appear in files:.
2137 """
2137 """
2138
2138
2139 matchfn = cmdutil.match(repo, pats, opts)
2139 matchfn = cmdutil.match(repo, pats, opts)
2140 limit = cmdutil.loglimit(opts)
2140 limit = cmdutil.loglimit(opts)
2141 count = 0
2141 count = 0
2142
2142
2143 endrev = None
2143 endrev = None
2144 if opts.get('copies') and opts.get('rev'):
2144 if opts.get('copies') and opts.get('rev'):
2145 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2145 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2146
2146
2147 df = False
2147 df = False
2148 if opts["date"]:
2148 if opts["date"]:
2149 df = util.matchdate(opts["date"])
2149 df = util.matchdate(opts["date"])
2150
2150
2151 branches = opts.get('branch', []) + opts.get('only_branch', [])
2151 branches = opts.get('branch', []) + opts.get('only_branch', [])
2152 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2152 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2153
2153
2154 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2154 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2155 def prep(ctx, fns):
2155 def prep(ctx, fns):
2156 rev = ctx.rev()
2156 rev = ctx.rev()
2157 parents = [p for p in repo.changelog.parentrevs(rev)
2157 parents = [p for p in repo.changelog.parentrevs(rev)
2158 if p != nullrev]
2158 if p != nullrev]
2159 if opts.get('no_merges') and len(parents) == 2:
2159 if opts.get('no_merges') and len(parents) == 2:
2160 return
2160 return
2161 if opts.get('only_merges') and len(parents) != 2:
2161 if opts.get('only_merges') and len(parents) != 2:
2162 return
2162 return
2163 if opts.get('branch') and ctx.branch() not in opts['branch']:
2163 if opts.get('branch') and ctx.branch() not in opts['branch']:
2164 return
2164 return
2165 if df and not df(ctx.date()[0]):
2165 if df and not df(ctx.date()[0]):
2166 return
2166 return
2167 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2167 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2168 return
2168 return
2169 if opts.get('keyword'):
2169 if opts.get('keyword'):
2170 for k in [kw.lower() for kw in opts['keyword']]:
2170 for k in [kw.lower() for kw in opts['keyword']]:
2171 if (k in ctx.user().lower() or
2171 if (k in ctx.user().lower() or
2172 k in ctx.description().lower() or
2172 k in ctx.description().lower() or
2173 k in " ".join(ctx.files()).lower()):
2173 k in " ".join(ctx.files()).lower()):
2174 break
2174 break
2175 else:
2175 else:
2176 return
2176 return
2177
2177
2178 copies = None
2178 copies = None
2179 if opts.get('copies') and rev:
2179 if opts.get('copies') and rev:
2180 copies = []
2180 copies = []
2181 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2181 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2182 for fn in ctx.files():
2182 for fn in ctx.files():
2183 rename = getrenamed(fn, rev)
2183 rename = getrenamed(fn, rev)
2184 if rename:
2184 if rename:
2185 copies.append((fn, rename[0]))
2185 copies.append((fn, rename[0]))
2186
2186
2187 displayer.show(ctx, copies=copies)
2187 displayer.show(ctx, copies=copies)
2188
2188
2189 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2189 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2190 if count == limit:
2190 if count == limit:
2191 break
2191 break
2192 if displayer.flush(ctx.rev()):
2192 if displayer.flush(ctx.rev()):
2193 count += 1
2193 count += 1
2194 displayer.close()
2194 displayer.close()
2195
2195
2196 def manifest(ui, repo, node=None, rev=None):
2196 def manifest(ui, repo, node=None, rev=None):
2197 """output the current or given revision of the project manifest
2197 """output the current or given revision of the project manifest
2198
2198
2199 Print a list of version controlled files for the given revision.
2199 Print a list of version controlled files for the given revision.
2200 If no revision is given, the first parent of the working directory
2200 If no revision is given, the first parent of the working directory
2201 is used, or the null revision if no revision is checked out.
2201 is used, or the null revision if no revision is checked out.
2202
2202
2203 With -v, print file permissions, symlink and executable bits.
2203 With -v, print file permissions, symlink and executable bits.
2204 With --debug, print file revision hashes.
2204 With --debug, print file revision hashes.
2205 """
2205 """
2206
2206
2207 if rev and node:
2207 if rev and node:
2208 raise util.Abort(_("please specify just one revision"))
2208 raise util.Abort(_("please specify just one revision"))
2209
2209
2210 if not node:
2210 if not node:
2211 node = rev
2211 node = rev
2212
2212
2213 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2213 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2214 ctx = repo[node]
2214 ctx = repo[node]
2215 for f in ctx:
2215 for f in ctx:
2216 if ui.debugflag:
2216 if ui.debugflag:
2217 ui.write("%40s " % hex(ctx.manifest()[f]))
2217 ui.write("%40s " % hex(ctx.manifest()[f]))
2218 if ui.verbose:
2218 if ui.verbose:
2219 ui.write(decor[ctx.flags(f)])
2219 ui.write(decor[ctx.flags(f)])
2220 ui.write("%s\n" % f)
2220 ui.write("%s\n" % f)
2221
2221
2222 def merge(ui, repo, node=None, **opts):
2222 def merge(ui, repo, node=None, **opts):
2223 """merge working directory with another revision
2223 """merge working directory with another revision
2224
2224
2225 The current working directory is updated with all changes made in
2225 The current working directory is updated with all changes made in
2226 the requested revision since the last common predecessor revision.
2226 the requested revision since the last common predecessor revision.
2227
2227
2228 Files that changed between either parent are marked as changed for
2228 Files that changed between either parent are marked as changed for
2229 the next commit and a commit must be performed before any further
2229 the next commit and a commit must be performed before any further
2230 updates to the repository are allowed. The next commit will have
2230 updates to the repository are allowed. The next commit will have
2231 two parents.
2231 two parents.
2232
2232
2233 If no revision is specified, the working directory's parent is a
2233 If no revision is specified, the working directory's parent is a
2234 head revision, and the current branch contains exactly one other
2234 head revision, and the current branch contains exactly one other
2235 head, the other head is merged with by default. Otherwise, an
2235 head, the other head is merged with by default. Otherwise, an
2236 explicit revision with which to merge with must be provided.
2236 explicit revision with which to merge with must be provided.
2237 """
2237 """
2238
2238
2239 if opts.get('rev') and node:
2239 if opts.get('rev') and node:
2240 raise util.Abort(_("please specify just one revision"))
2240 raise util.Abort(_("please specify just one revision"))
2241 if not node:
2241 if not node:
2242 node = opts.get('rev')
2242 node = opts.get('rev')
2243
2243
2244 if not node:
2244 if not node:
2245 branch = repo.changectx(None).branch()
2245 branch = repo.changectx(None).branch()
2246 bheads = repo.branchheads(branch)
2246 bheads = repo.branchheads(branch)
2247 if len(bheads) > 2:
2247 if len(bheads) > 2:
2248 ui.warn(_("abort: branch '%s' has %d heads - "
2248 ui.warn(_("abort: branch '%s' has %d heads - "
2249 "please merge with an explicit rev\n")
2249 "please merge with an explicit rev\n")
2250 % (branch, len(bheads)))
2250 % (branch, len(bheads)))
2251 ui.status(_("(run 'hg heads .' to see heads)\n"))
2251 ui.status(_("(run 'hg heads .' to see heads)\n"))
2252 return False
2252 return False
2253
2253
2254 parent = repo.dirstate.parents()[0]
2254 parent = repo.dirstate.parents()[0]
2255 if len(bheads) == 1:
2255 if len(bheads) == 1:
2256 if len(repo.heads()) > 1:
2256 if len(repo.heads()) > 1:
2257 ui.warn(_("abort: branch '%s' has one head - "
2257 ui.warn(_("abort: branch '%s' has one head - "
2258 "please merge with an explicit rev\n" % branch))
2258 "please merge with an explicit rev\n" % branch))
2259 ui.status(_("(run 'hg heads' to see all heads)\n"))
2259 ui.status(_("(run 'hg heads' to see all heads)\n"))
2260 return False
2260 return False
2261 msg = _('there is nothing to merge')
2261 msg = _('there is nothing to merge')
2262 if parent != repo.lookup(repo[None].branch()):
2262 if parent != repo.lookup(repo[None].branch()):
2263 msg = _('%s - use "hg update" instead') % msg
2263 msg = _('%s - use "hg update" instead') % msg
2264 raise util.Abort(msg)
2264 raise util.Abort(msg)
2265
2265
2266 if parent not in bheads:
2266 if parent not in bheads:
2267 raise util.Abort(_('working dir not at a head rev - '
2267 raise util.Abort(_('working dir not at a head rev - '
2268 'use "hg update" or merge with an explicit rev'))
2268 'use "hg update" or merge with an explicit rev'))
2269 node = parent == bheads[0] and bheads[-1] or bheads[0]
2269 node = parent == bheads[0] and bheads[-1] or bheads[0]
2270
2270
2271 if opts.get('preview'):
2271 if opts.get('preview'):
2272 # find nodes that are ancestors of p2 but not of p1
2272 # find nodes that are ancestors of p2 but not of p1
2273 p1 = repo.lookup('.')
2273 p1 = repo.lookup('.')
2274 p2 = repo.lookup(node)
2274 p2 = repo.lookup(node)
2275 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2275 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2276
2276
2277 displayer = cmdutil.show_changeset(ui, repo, opts)
2277 displayer = cmdutil.show_changeset(ui, repo, opts)
2278 for node in nodes:
2278 for node in nodes:
2279 displayer.show(repo[node])
2279 displayer.show(repo[node])
2280 displayer.close()
2280 displayer.close()
2281 return 0
2281 return 0
2282
2282
2283 return hg.merge(repo, node, force=opts.get('force'))
2283 return hg.merge(repo, node, force=opts.get('force'))
2284
2284
2285 def outgoing(ui, repo, dest=None, **opts):
2285 def outgoing(ui, repo, dest=None, **opts):
2286 """show changesets not found in the destination
2286 """show changesets not found in the destination
2287
2287
2288 Show changesets not found in the specified destination repository
2288 Show changesets not found in the specified destination repository
2289 or the default push location. These are the changesets that would
2289 or the default push location. These are the changesets that would
2290 be pushed if a push was requested.
2290 be pushed if a push was requested.
2291
2291
2292 See pull for details of valid destination formats.
2292 See pull for details of valid destination formats.
2293 """
2293 """
2294 limit = cmdutil.loglimit(opts)
2294 limit = cmdutil.loglimit(opts)
2295 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2295 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2296 dest, branches = hg.parseurl(dest, opts.get('branch'))
2296 dest, branches = hg.parseurl(dest, opts.get('branch'))
2297 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2297 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2298 if revs:
2298 if revs:
2299 revs = [repo.lookup(rev) for rev in revs]
2299 revs = [repo.lookup(rev) for rev in revs]
2300
2300
2301 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2301 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2302 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2302 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2303 o = repo.findoutgoing(other, force=opts.get('force'))
2303 o = repo.findoutgoing(other, force=opts.get('force'))
2304 if not o:
2304 if not o:
2305 ui.status(_("no changes found\n"))
2305 ui.status(_("no changes found\n"))
2306 return 1
2306 return 1
2307 o = repo.changelog.nodesbetween(o, revs)[0]
2307 o = repo.changelog.nodesbetween(o, revs)[0]
2308 if opts.get('newest_first'):
2308 if opts.get('newest_first'):
2309 o.reverse()
2309 o.reverse()
2310 displayer = cmdutil.show_changeset(ui, repo, opts)
2310 displayer = cmdutil.show_changeset(ui, repo, opts)
2311 count = 0
2311 count = 0
2312 for n in o:
2312 for n in o:
2313 if limit is not None and count >= limit:
2313 if limit is not None and count >= limit:
2314 break
2314 break
2315 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2315 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2316 if opts.get('no_merges') and len(parents) == 2:
2316 if opts.get('no_merges') and len(parents) == 2:
2317 continue
2317 continue
2318 count += 1
2318 count += 1
2319 displayer.show(repo[n])
2319 displayer.show(repo[n])
2320 displayer.close()
2320 displayer.close()
2321
2321
2322 def parents(ui, repo, file_=None, **opts):
2322 def parents(ui, repo, file_=None, **opts):
2323 """show the parents of the working directory or revision
2323 """show the parents of the working directory or revision
2324
2324
2325 Print the working directory's parent revisions. If a revision is
2325 Print the working directory's parent revisions. If a revision is
2326 given via -r/--rev, the parent of that revision will be printed.
2326 given via -r/--rev, the parent of that revision will be printed.
2327 If a file argument is given, the revision in which the file was
2327 If a file argument is given, the revision in which the file was
2328 last changed (before the working directory revision or the
2328 last changed (before the working directory revision or the
2329 argument to --rev if given) is printed.
2329 argument to --rev if given) is printed.
2330 """
2330 """
2331 rev = opts.get('rev')
2331 rev = opts.get('rev')
2332 if rev:
2332 if rev:
2333 ctx = repo[rev]
2333 ctx = repo[rev]
2334 else:
2334 else:
2335 ctx = repo[None]
2335 ctx = repo[None]
2336
2336
2337 if file_:
2337 if file_:
2338 m = cmdutil.match(repo, (file_,), opts)
2338 m = cmdutil.match(repo, (file_,), opts)
2339 if m.anypats() or len(m.files()) != 1:
2339 if m.anypats() or len(m.files()) != 1:
2340 raise util.Abort(_('can only specify an explicit filename'))
2340 raise util.Abort(_('can only specify an explicit filename'))
2341 file_ = m.files()[0]
2341 file_ = m.files()[0]
2342 filenodes = []
2342 filenodes = []
2343 for cp in ctx.parents():
2343 for cp in ctx.parents():
2344 if not cp:
2344 if not cp:
2345 continue
2345 continue
2346 try:
2346 try:
2347 filenodes.append(cp.filenode(file_))
2347 filenodes.append(cp.filenode(file_))
2348 except error.LookupError:
2348 except error.LookupError:
2349 pass
2349 pass
2350 if not filenodes:
2350 if not filenodes:
2351 raise util.Abort(_("'%s' not found in manifest!") % file_)
2351 raise util.Abort(_("'%s' not found in manifest!") % file_)
2352 fl = repo.file(file_)
2352 fl = repo.file(file_)
2353 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2353 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2354 else:
2354 else:
2355 p = [cp.node() for cp in ctx.parents()]
2355 p = [cp.node() for cp in ctx.parents()]
2356
2356
2357 displayer = cmdutil.show_changeset(ui, repo, opts)
2357 displayer = cmdutil.show_changeset(ui, repo, opts)
2358 for n in p:
2358 for n in p:
2359 if n != nullid:
2359 if n != nullid:
2360 displayer.show(repo[n])
2360 displayer.show(repo[n])
2361 displayer.close()
2361 displayer.close()
2362
2362
2363 def paths(ui, repo, search=None):
2363 def paths(ui, repo, search=None):
2364 """show aliases for remote repositories
2364 """show aliases for remote repositories
2365
2365
2366 Show definition of symbolic path name NAME. If no name is given,
2366 Show definition of symbolic path name NAME. If no name is given,
2367 show definition of all available names.
2367 show definition of all available names.
2368
2368
2369 Path names are defined in the [paths] section of
2369 Path names are defined in the [paths] section of
2370 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2370 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2371 repository, ``.hg/hgrc`` is used, too.
2371 repository, ``.hg/hgrc`` is used, too.
2372
2372
2373 The path names ``default`` and ``default-push`` have a special
2373 The path names ``default`` and ``default-push`` have a special
2374 meaning. When performing a push or pull operation, they are used
2374 meaning. When performing a push or pull operation, they are used
2375 as fallbacks if no location is specified on the command-line.
2375 as fallbacks if no location is specified on the command-line.
2376 When ``default-push`` is set, it will be used for push and
2376 When ``default-push`` is set, it will be used for push and
2377 ``default`` will be used for pull; otherwise ``default`` is used
2377 ``default`` will be used for pull; otherwise ``default`` is used
2378 as the fallback for both. When cloning a repository, the clone
2378 as the fallback for both. When cloning a repository, the clone
2379 source is written as ``default`` in ``.hg/hgrc``. Note that
2379 source is written as ``default`` in ``.hg/hgrc``. Note that
2380 ``default`` and ``default-push`` apply to all inbound (e.g.
2380 ``default`` and ``default-push`` apply to all inbound (e.g.
2381 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2381 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2382 :hg:`bundle`) operations.
2382 :hg:`bundle`) operations.
2383
2383
2384 See :hg:`help urls` for more information.
2384 See :hg:`help urls` for more information.
2385 """
2385 """
2386 if search:
2386 if search:
2387 for name, path in ui.configitems("paths"):
2387 for name, path in ui.configitems("paths"):
2388 if name == search:
2388 if name == search:
2389 ui.write("%s\n" % url.hidepassword(path))
2389 ui.write("%s\n" % url.hidepassword(path))
2390 return
2390 return
2391 ui.warn(_("not found!\n"))
2391 ui.warn(_("not found!\n"))
2392 return 1
2392 return 1
2393 else:
2393 else:
2394 for name, path in ui.configitems("paths"):
2394 for name, path in ui.configitems("paths"):
2395 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2395 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2396
2396
2397 def postincoming(ui, repo, modheads, optupdate, checkout):
2397 def postincoming(ui, repo, modheads, optupdate, checkout):
2398 if modheads == 0:
2398 if modheads == 0:
2399 return
2399 return
2400 if optupdate:
2400 if optupdate:
2401 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2401 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2402 return hg.update(repo, checkout)
2402 return hg.update(repo, checkout)
2403 else:
2403 else:
2404 ui.status(_("not updating, since new heads added\n"))
2404 ui.status(_("not updating, since new heads added\n"))
2405 if modheads > 1:
2405 if modheads > 1:
2406 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2406 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2407 else:
2407 else:
2408 ui.status(_("(run 'hg update' to get a working copy)\n"))
2408 ui.status(_("(run 'hg update' to get a working copy)\n"))
2409
2409
2410 def pull(ui, repo, source="default", **opts):
2410 def pull(ui, repo, source="default", **opts):
2411 """pull changes from the specified source
2411 """pull changes from the specified source
2412
2412
2413 Pull changes from a remote repository to a local one.
2413 Pull changes from a remote repository to a local one.
2414
2414
2415 This finds all changes from the repository at the specified path
2415 This finds all changes from the repository at the specified path
2416 or URL and adds them to a local repository (the current one unless
2416 or URL and adds them to a local repository (the current one unless
2417 -R is specified). By default, this does not update the copy of the
2417 -R is specified). By default, this does not update the copy of the
2418 project in the working directory.
2418 project in the working directory.
2419
2419
2420 Use hg incoming if you want to see what would have been added by a
2420 Use hg incoming if you want to see what would have been added by a
2421 pull at the time you issued this command. If you then decide to
2421 pull at the time you issued this command. If you then decide to
2422 added those changes to the repository, you should use pull -r X
2422 added those changes to the repository, you should use pull -r X
2423 where X is the last changeset listed by hg incoming.
2423 where X is the last changeset listed by hg incoming.
2424
2424
2425 If SOURCE is omitted, the 'default' path will be used.
2425 If SOURCE is omitted, the 'default' path will be used.
2426 See :hg:`help urls` for more information.
2426 See :hg:`help urls` for more information.
2427 """
2427 """
2428 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2428 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2429 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2429 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2430 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2430 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2431 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2431 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2432 if revs:
2432 if revs:
2433 try:
2433 try:
2434 revs = [other.lookup(rev) for rev in revs]
2434 revs = [other.lookup(rev) for rev in revs]
2435 except error.CapabilityError:
2435 except error.CapabilityError:
2436 err = _("Other repository doesn't support revision lookup, "
2436 err = _("Other repository doesn't support revision lookup, "
2437 "so a rev cannot be specified.")
2437 "so a rev cannot be specified.")
2438 raise util.Abort(err)
2438 raise util.Abort(err)
2439
2439
2440 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2440 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2441 if checkout:
2441 if checkout:
2442 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2442 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2443 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2443 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2444
2444
2445 def push(ui, repo, dest=None, **opts):
2445 def push(ui, repo, dest=None, **opts):
2446 """push changes to the specified destination
2446 """push changes to the specified destination
2447
2447
2448 Push changes from the local repository to the specified destination.
2448 Push changes from the local repository to the specified destination.
2449
2449
2450 This is the symmetrical operation for pull. It moves changes from
2450 This is the symmetrical operation for pull. It moves changes from
2451 the current repository to a different one. If the destination is
2451 the current repository to a different one. If the destination is
2452 local this is identical to a pull in that directory from the
2452 local this is identical to a pull in that directory from the
2453 current one.
2453 current one.
2454
2454
2455 By default, push will refuse to run if it detects the result would
2455 By default, push will refuse to run if it detects the result would
2456 increase the number of remote heads. This generally indicates the
2456 increase the number of remote heads. This generally indicates the
2457 user forgot to pull and merge before pushing.
2457 user forgot to pull and merge before pushing.
2458
2458
2459 If -r/--rev is used, the named revision and all its ancestors will
2459 If -r/--rev is used, the named revision and all its ancestors will
2460 be pushed to the remote repository.
2460 be pushed to the remote repository.
2461
2461
2462 Please see :hg:`help urls` for important details about ``ssh://``
2462 Please see :hg:`help urls` for important details about ``ssh://``
2463 URLs. If DESTINATION is omitted, a default path will be used.
2463 URLs. If DESTINATION is omitted, a default path will be used.
2464 """
2464 """
2465 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2465 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2466 dest, branches = hg.parseurl(dest, opts.get('branch'))
2466 dest, branches = hg.parseurl(dest, opts.get('branch'))
2467 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2467 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2468 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2468 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2469 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2469 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2470 if revs:
2470 if revs:
2471 revs = [repo.lookup(rev) for rev in revs]
2471 revs = [repo.lookup(rev) for rev in revs]
2472
2472
2473 # push subrepos depth-first for coherent ordering
2473 # push subrepos depth-first for coherent ordering
2474 c = repo['']
2474 c = repo['']
2475 subs = c.substate # only repos that are committed
2475 subs = c.substate # only repos that are committed
2476 for s in sorted(subs):
2476 for s in sorted(subs):
2477 c.sub(s).push(opts.get('force'))
2477 c.sub(s).push(opts.get('force'))
2478
2478
2479 r = repo.push(other, opts.get('force'), revs=revs)
2479 r = repo.push(other, opts.get('force'), revs=revs)
2480 return r == 0
2480 return r == 0
2481
2481
2482 def recover(ui, repo):
2482 def recover(ui, repo):
2483 """roll back an interrupted transaction
2483 """roll back an interrupted transaction
2484
2484
2485 Recover from an interrupted commit or pull.
2485 Recover from an interrupted commit or pull.
2486
2486
2487 This command tries to fix the repository status after an
2487 This command tries to fix the repository status after an
2488 interrupted operation. It should only be necessary when Mercurial
2488 interrupted operation. It should only be necessary when Mercurial
2489 suggests it.
2489 suggests it.
2490 """
2490 """
2491 if repo.recover():
2491 if repo.recover():
2492 return hg.verify(repo)
2492 return hg.verify(repo)
2493 return 1
2493 return 1
2494
2494
2495 def remove(ui, repo, *pats, **opts):
2495 def remove(ui, repo, *pats, **opts):
2496 """remove the specified files on the next commit
2496 """remove the specified files on the next commit
2497
2497
2498 Schedule the indicated files for removal from the repository.
2498 Schedule the indicated files for removal from the repository.
2499
2499
2500 This only removes files from the current branch, not from the
2500 This only removes files from the current branch, not from the
2501 entire project history. -A/--after can be used to remove only
2501 entire project history. -A/--after can be used to remove only
2502 files that have already been deleted, -f/--force can be used to
2502 files that have already been deleted, -f/--force can be used to
2503 force deletion, and -Af can be used to remove files from the next
2503 force deletion, and -Af can be used to remove files from the next
2504 revision without deleting them from the working directory.
2504 revision without deleting them from the working directory.
2505
2505
2506 The following table details the behavior of remove for different
2506 The following table details the behavior of remove for different
2507 file states (columns) and option combinations (rows). The file
2507 file states (columns) and option combinations (rows). The file
2508 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2508 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2509 reported by hg status). The actions are Warn, Remove (from branch)
2509 reported by hg status). The actions are Warn, Remove (from branch)
2510 and Delete (from disk)::
2510 and Delete (from disk)::
2511
2511
2512 A C M !
2512 A C M !
2513 none W RD W R
2513 none W RD W R
2514 -f R RD RD R
2514 -f R RD RD R
2515 -A W W W R
2515 -A W W W R
2516 -Af R R R R
2516 -Af R R R R
2517
2517
2518 This command schedules the files to be removed at the next commit.
2518 This command schedules the files to be removed at the next commit.
2519 To undo a remove before that, see hg revert.
2519 To undo a remove before that, see hg revert.
2520 """
2520 """
2521
2521
2522 after, force = opts.get('after'), opts.get('force')
2522 after, force = opts.get('after'), opts.get('force')
2523 if not pats and not after:
2523 if not pats and not after:
2524 raise util.Abort(_('no files specified'))
2524 raise util.Abort(_('no files specified'))
2525
2525
2526 m = cmdutil.match(repo, pats, opts)
2526 m = cmdutil.match(repo, pats, opts)
2527 s = repo.status(match=m, clean=True)
2527 s = repo.status(match=m, clean=True)
2528 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2528 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2529
2529
2530 for f in m.files():
2530 for f in m.files():
2531 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2531 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2532 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2532 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2533
2533
2534 def warn(files, reason):
2534 def warn(files, reason):
2535 for f in files:
2535 for f in files:
2536 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2536 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2537 % (m.rel(f), reason))
2537 % (m.rel(f), reason))
2538
2538
2539 if force:
2539 if force:
2540 remove, forget = modified + deleted + clean, added
2540 remove, forget = modified + deleted + clean, added
2541 elif after:
2541 elif after:
2542 remove, forget = deleted, []
2542 remove, forget = deleted, []
2543 warn(modified + added + clean, _('still exists'))
2543 warn(modified + added + clean, _('still exists'))
2544 else:
2544 else:
2545 remove, forget = deleted + clean, []
2545 remove, forget = deleted + clean, []
2546 warn(modified, _('is modified'))
2546 warn(modified, _('is modified'))
2547 warn(added, _('has been marked for add'))
2547 warn(added, _('has been marked for add'))
2548
2548
2549 for f in sorted(remove + forget):
2549 for f in sorted(remove + forget):
2550 if ui.verbose or not m.exact(f):
2550 if ui.verbose or not m.exact(f):
2551 ui.status(_('removing %s\n') % m.rel(f))
2551 ui.status(_('removing %s\n') % m.rel(f))
2552
2552
2553 repo.forget(forget)
2553 repo.forget(forget)
2554 repo.remove(remove, unlink=not after)
2554 repo.remove(remove, unlink=not after)
2555
2555
2556 def rename(ui, repo, *pats, **opts):
2556 def rename(ui, repo, *pats, **opts):
2557 """rename files; equivalent of copy + remove
2557 """rename files; equivalent of copy + remove
2558
2558
2559 Mark dest as copies of sources; mark sources for deletion. If dest
2559 Mark dest as copies of sources; mark sources for deletion. If dest
2560 is a directory, copies are put in that directory. If dest is a
2560 is a directory, copies are put in that directory. If dest is a
2561 file, there can only be one source.
2561 file, there can only be one source.
2562
2562
2563 By default, this command copies the contents of files as they
2563 By default, this command copies the contents of files as they
2564 exist in the working directory. If invoked with -A/--after, the
2564 exist in the working directory. If invoked with -A/--after, the
2565 operation is recorded, but no copying is performed.
2565 operation is recorded, but no copying is performed.
2566
2566
2567 This command takes effect at the next commit. To undo a rename
2567 This command takes effect at the next commit. To undo a rename
2568 before that, see hg revert.
2568 before that, see hg revert.
2569 """
2569 """
2570 wlock = repo.wlock(False)
2570 wlock = repo.wlock(False)
2571 try:
2571 try:
2572 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2572 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2573 finally:
2573 finally:
2574 wlock.release()
2574 wlock.release()
2575
2575
2576 def resolve(ui, repo, *pats, **opts):
2576 def resolve(ui, repo, *pats, **opts):
2577 """various operations to help finish a merge
2577 """various operations to help finish a merge
2578
2578
2579 This command includes several actions that are often useful while
2579 This command includes several actions that are often useful while
2580 performing a merge, after running ``merge`` but before running
2580 performing a merge, after running ``merge`` but before running
2581 ``commit``. (It is only meaningful if your working directory has
2581 ``commit``. (It is only meaningful if your working directory has
2582 two parents.) It is most relevant for merges with unresolved
2582 two parents.) It is most relevant for merges with unresolved
2583 conflicts, which are typically a result of non-interactive merging with
2583 conflicts, which are typically a result of non-interactive merging with
2584 ``internal:merge`` or a command-line merge tool like ``diff3``.
2584 ``internal:merge`` or a command-line merge tool like ``diff3``.
2585
2585
2586 The available actions are:
2586 The available actions are:
2587
2587
2588 1) list files that were merged with conflicts (U, for unresolved)
2588 1) list files that were merged with conflicts (U, for unresolved)
2589 and without conflicts (R, for resolved): ``hg resolve -l``
2589 and without conflicts (R, for resolved): ``hg resolve -l``
2590 (this is like ``status`` for merges)
2590 (this is like ``status`` for merges)
2591 2) record that you have resolved conflicts in certain files:
2591 2) record that you have resolved conflicts in certain files:
2592 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2592 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2593 3) forget that you have resolved conflicts in certain files:
2593 3) forget that you have resolved conflicts in certain files:
2594 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2594 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2595 4) discard your current attempt(s) at resolving conflicts and
2595 4) discard your current attempt(s) at resolving conflicts and
2596 restart the merge from scratch: ``hg resolve file...``
2596 restart the merge from scratch: ``hg resolve file...``
2597 (or ``-a`` for all unresolved files)
2597 (or ``-a`` for all unresolved files)
2598
2598
2599 Note that Mercurial will not let you commit files with unresolved merge
2599 Note that Mercurial will not let you commit files with unresolved merge
2600 conflicts. You must use ``hg resolve -m ...`` before you can commit
2600 conflicts. You must use ``hg resolve -m ...`` before you can commit
2601 after a conflicting merge.
2601 after a conflicting merge.
2602 """
2602 """
2603
2603
2604 all, mark, unmark, show, nostatus = \
2604 all, mark, unmark, show, nostatus = \
2605 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2605 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2606
2606
2607 if (show and (mark or unmark)) or (mark and unmark):
2607 if (show and (mark or unmark)) or (mark and unmark):
2608 raise util.Abort(_("too many options specified"))
2608 raise util.Abort(_("too many options specified"))
2609 if pats and all:
2609 if pats and all:
2610 raise util.Abort(_("can't specify --all and patterns"))
2610 raise util.Abort(_("can't specify --all and patterns"))
2611 if not (all or pats or show or mark or unmark):
2611 if not (all or pats or show or mark or unmark):
2612 raise util.Abort(_('no files or directories specified; '
2612 raise util.Abort(_('no files or directories specified; '
2613 'use --all to remerge all files'))
2613 'use --all to remerge all files'))
2614
2614
2615 ms = mergemod.mergestate(repo)
2615 ms = mergemod.mergestate(repo)
2616 m = cmdutil.match(repo, pats, opts)
2616 m = cmdutil.match(repo, pats, opts)
2617
2617
2618 for f in ms:
2618 for f in ms:
2619 if m(f):
2619 if m(f):
2620 if show:
2620 if show:
2621 if nostatus:
2621 if nostatus:
2622 ui.write("%s\n" % f)
2622 ui.write("%s\n" % f)
2623 else:
2623 else:
2624 ui.write("%s %s\n" % (ms[f].upper(), f),
2624 ui.write("%s %s\n" % (ms[f].upper(), f),
2625 label='resolve.' +
2625 label='resolve.' +
2626 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2626 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2627 elif mark:
2627 elif mark:
2628 ms.mark(f, "r")
2628 ms.mark(f, "r")
2629 elif unmark:
2629 elif unmark:
2630 ms.mark(f, "u")
2630 ms.mark(f, "u")
2631 else:
2631 else:
2632 wctx = repo[None]
2632 wctx = repo[None]
2633 mctx = wctx.parents()[-1]
2633 mctx = wctx.parents()[-1]
2634
2634
2635 # backup pre-resolve (merge uses .orig for its own purposes)
2635 # backup pre-resolve (merge uses .orig for its own purposes)
2636 a = repo.wjoin(f)
2636 a = repo.wjoin(f)
2637 util.copyfile(a, a + ".resolve")
2637 util.copyfile(a, a + ".resolve")
2638
2638
2639 # resolve file
2639 # resolve file
2640 ms.resolve(f, wctx, mctx)
2640 ms.resolve(f, wctx, mctx)
2641
2641
2642 # replace filemerge's .orig file with our resolve file
2642 # replace filemerge's .orig file with our resolve file
2643 util.rename(a + ".resolve", a + ".orig")
2643 util.rename(a + ".resolve", a + ".orig")
2644
2644
2645 def revert(ui, repo, *pats, **opts):
2645 def revert(ui, repo, *pats, **opts):
2646 """restore individual files or directories to an earlier state
2646 """restore individual files or directories to an earlier state
2647
2647
2648 (Use update -r to check out earlier revisions, revert does not
2648 (Use update -r to check out earlier revisions, revert does not
2649 change the working directory parents.)
2649 change the working directory parents.)
2650
2650
2651 With no revision specified, revert the named files or directories
2651 With no revision specified, revert the named files or directories
2652 to the contents they had in the parent of the working directory.
2652 to the contents they had in the parent of the working directory.
2653 This restores the contents of the affected files to an unmodified
2653 This restores the contents of the affected files to an unmodified
2654 state and unschedules adds, removes, copies, and renames. If the
2654 state and unschedules adds, removes, copies, and renames. If the
2655 working directory has two parents, you must explicitly specify a
2655 working directory has two parents, you must explicitly specify a
2656 revision.
2656 revision.
2657
2657
2658 Using the -r/--rev option, revert the given files or directories
2658 Using the -r/--rev option, revert the given files or directories
2659 to their contents as of a specific revision. This can be helpful
2659 to their contents as of a specific revision. This can be helpful
2660 to "roll back" some or all of an earlier change. See :hg:`help
2660 to "roll back" some or all of an earlier change. See :hg:`help
2661 dates` for a list of formats valid for -d/--date.
2661 dates` for a list of formats valid for -d/--date.
2662
2662
2663 Revert modifies the working directory. It does not commit any
2663 Revert modifies the working directory. It does not commit any
2664 changes, or change the parent of the working directory. If you
2664 changes, or change the parent of the working directory. If you
2665 revert to a revision other than the parent of the working
2665 revert to a revision other than the parent of the working
2666 directory, the reverted files will thus appear modified
2666 directory, the reverted files will thus appear modified
2667 afterwards.
2667 afterwards.
2668
2668
2669 If a file has been deleted, it is restored. If the executable mode
2669 If a file has been deleted, it is restored. If the executable mode
2670 of a file was changed, it is reset.
2670 of a file was changed, it is reset.
2671
2671
2672 If names are given, all files matching the names are reverted.
2672 If names are given, all files matching the names are reverted.
2673 If no arguments are given, no files are reverted.
2673 If no arguments are given, no files are reverted.
2674
2674
2675 Modified files are saved with a .orig suffix before reverting.
2675 Modified files are saved with a .orig suffix before reverting.
2676 To disable these backups, use --no-backup.
2676 To disable these backups, use --no-backup.
2677 """
2677 """
2678
2678
2679 if opts["date"]:
2679 if opts["date"]:
2680 if opts["rev"]:
2680 if opts["rev"]:
2681 raise util.Abort(_("you can't specify a revision and a date"))
2681 raise util.Abort(_("you can't specify a revision and a date"))
2682 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2682 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2683
2683
2684 if not pats and not opts.get('all'):
2684 if not pats and not opts.get('all'):
2685 raise util.Abort(_('no files or directories specified; '
2685 raise util.Abort(_('no files or directories specified; '
2686 'use --all to revert the whole repo'))
2686 'use --all to revert the whole repo'))
2687
2687
2688 parent, p2 = repo.dirstate.parents()
2688 parent, p2 = repo.dirstate.parents()
2689 if not opts.get('rev') and p2 != nullid:
2689 if not opts.get('rev') and p2 != nullid:
2690 raise util.Abort(_('uncommitted merge - please provide a '
2690 raise util.Abort(_('uncommitted merge - please provide a '
2691 'specific revision'))
2691 'specific revision'))
2692 ctx = repo[opts.get('rev')]
2692 ctx = repo[opts.get('rev')]
2693 node = ctx.node()
2693 node = ctx.node()
2694 mf = ctx.manifest()
2694 mf = ctx.manifest()
2695 if node == parent:
2695 if node == parent:
2696 pmf = mf
2696 pmf = mf
2697 else:
2697 else:
2698 pmf = None
2698 pmf = None
2699
2699
2700 # need all matching names in dirstate and manifest of target rev,
2700 # need all matching names in dirstate and manifest of target rev,
2701 # so have to walk both. do not print errors if files exist in one
2701 # so have to walk both. do not print errors if files exist in one
2702 # but not other.
2702 # but not other.
2703
2703
2704 names = {}
2704 names = {}
2705
2705
2706 wlock = repo.wlock()
2706 wlock = repo.wlock()
2707 try:
2707 try:
2708 # walk dirstate.
2708 # walk dirstate.
2709
2709
2710 m = cmdutil.match(repo, pats, opts)
2710 m = cmdutil.match(repo, pats, opts)
2711 m.bad = lambda x, y: False
2711 m.bad = lambda x, y: False
2712 for abs in repo.walk(m):
2712 for abs in repo.walk(m):
2713 names[abs] = m.rel(abs), m.exact(abs)
2713 names[abs] = m.rel(abs), m.exact(abs)
2714
2714
2715 # walk target manifest.
2715 # walk target manifest.
2716
2716
2717 def badfn(path, msg):
2717 def badfn(path, msg):
2718 if path in names:
2718 if path in names:
2719 return
2719 return
2720 path_ = path + '/'
2720 path_ = path + '/'
2721 for f in names:
2721 for f in names:
2722 if f.startswith(path_):
2722 if f.startswith(path_):
2723 return
2723 return
2724 ui.warn("%s: %s\n" % (m.rel(path), msg))
2724 ui.warn("%s: %s\n" % (m.rel(path), msg))
2725
2725
2726 m = cmdutil.match(repo, pats, opts)
2726 m = cmdutil.match(repo, pats, opts)
2727 m.bad = badfn
2727 m.bad = badfn
2728 for abs in repo[node].walk(m):
2728 for abs in repo[node].walk(m):
2729 if abs not in names:
2729 if abs not in names:
2730 names[abs] = m.rel(abs), m.exact(abs)
2730 names[abs] = m.rel(abs), m.exact(abs)
2731
2731
2732 m = cmdutil.matchfiles(repo, names)
2732 m = cmdutil.matchfiles(repo, names)
2733 changes = repo.status(match=m)[:4]
2733 changes = repo.status(match=m)[:4]
2734 modified, added, removed, deleted = map(set, changes)
2734 modified, added, removed, deleted = map(set, changes)
2735
2735
2736 # if f is a rename, also revert the source
2736 # if f is a rename, also revert the source
2737 cwd = repo.getcwd()
2737 cwd = repo.getcwd()
2738 for f in added:
2738 for f in added:
2739 src = repo.dirstate.copied(f)
2739 src = repo.dirstate.copied(f)
2740 if src and src not in names and repo.dirstate[src] == 'r':
2740 if src and src not in names and repo.dirstate[src] == 'r':
2741 removed.add(src)
2741 removed.add(src)
2742 names[src] = (repo.pathto(src, cwd), True)
2742 names[src] = (repo.pathto(src, cwd), True)
2743
2743
2744 def removeforget(abs):
2744 def removeforget(abs):
2745 if repo.dirstate[abs] == 'a':
2745 if repo.dirstate[abs] == 'a':
2746 return _('forgetting %s\n')
2746 return _('forgetting %s\n')
2747 return _('removing %s\n')
2747 return _('removing %s\n')
2748
2748
2749 revert = ([], _('reverting %s\n'))
2749 revert = ([], _('reverting %s\n'))
2750 add = ([], _('adding %s\n'))
2750 add = ([], _('adding %s\n'))
2751 remove = ([], removeforget)
2751 remove = ([], removeforget)
2752 undelete = ([], _('undeleting %s\n'))
2752 undelete = ([], _('undeleting %s\n'))
2753
2753
2754 disptable = (
2754 disptable = (
2755 # dispatch table:
2755 # dispatch table:
2756 # file state
2756 # file state
2757 # action if in target manifest
2757 # action if in target manifest
2758 # action if not in target manifest
2758 # action if not in target manifest
2759 # make backup if in target manifest
2759 # make backup if in target manifest
2760 # make backup if not in target manifest
2760 # make backup if not in target manifest
2761 (modified, revert, remove, True, True),
2761 (modified, revert, remove, True, True),
2762 (added, revert, remove, True, False),
2762 (added, revert, remove, True, False),
2763 (removed, undelete, None, False, False),
2763 (removed, undelete, None, False, False),
2764 (deleted, revert, remove, False, False),
2764 (deleted, revert, remove, False, False),
2765 )
2765 )
2766
2766
2767 for abs, (rel, exact) in sorted(names.items()):
2767 for abs, (rel, exact) in sorted(names.items()):
2768 mfentry = mf.get(abs)
2768 mfentry = mf.get(abs)
2769 target = repo.wjoin(abs)
2769 target = repo.wjoin(abs)
2770 def handle(xlist, dobackup):
2770 def handle(xlist, dobackup):
2771 xlist[0].append(abs)
2771 xlist[0].append(abs)
2772 if dobackup and not opts.get('no_backup') and util.lexists(target):
2772 if dobackup and not opts.get('no_backup') and util.lexists(target):
2773 bakname = "%s.orig" % rel
2773 bakname = "%s.orig" % rel
2774 ui.note(_('saving current version of %s as %s\n') %
2774 ui.note(_('saving current version of %s as %s\n') %
2775 (rel, bakname))
2775 (rel, bakname))
2776 if not opts.get('dry_run'):
2776 if not opts.get('dry_run'):
2777 util.copyfile(target, bakname)
2777 util.copyfile(target, bakname)
2778 if ui.verbose or not exact:
2778 if ui.verbose or not exact:
2779 msg = xlist[1]
2779 msg = xlist[1]
2780 if not isinstance(msg, basestring):
2780 if not isinstance(msg, basestring):
2781 msg = msg(abs)
2781 msg = msg(abs)
2782 ui.status(msg % rel)
2782 ui.status(msg % rel)
2783 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2783 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2784 if abs not in table:
2784 if abs not in table:
2785 continue
2785 continue
2786 # file has changed in dirstate
2786 # file has changed in dirstate
2787 if mfentry:
2787 if mfentry:
2788 handle(hitlist, backuphit)
2788 handle(hitlist, backuphit)
2789 elif misslist is not None:
2789 elif misslist is not None:
2790 handle(misslist, backupmiss)
2790 handle(misslist, backupmiss)
2791 break
2791 break
2792 else:
2792 else:
2793 if abs not in repo.dirstate:
2793 if abs not in repo.dirstate:
2794 if mfentry:
2794 if mfentry:
2795 handle(add, True)
2795 handle(add, True)
2796 elif exact:
2796 elif exact:
2797 ui.warn(_('file not managed: %s\n') % rel)
2797 ui.warn(_('file not managed: %s\n') % rel)
2798 continue
2798 continue
2799 # file has not changed in dirstate
2799 # file has not changed in dirstate
2800 if node == parent:
2800 if node == parent:
2801 if exact:
2801 if exact:
2802 ui.warn(_('no changes needed to %s\n') % rel)
2802 ui.warn(_('no changes needed to %s\n') % rel)
2803 continue
2803 continue
2804 if pmf is None:
2804 if pmf is None:
2805 # only need parent manifest in this unlikely case,
2805 # only need parent manifest in this unlikely case,
2806 # so do not read by default
2806 # so do not read by default
2807 pmf = repo[parent].manifest()
2807 pmf = repo[parent].manifest()
2808 if abs in pmf:
2808 if abs in pmf:
2809 if mfentry:
2809 if mfentry:
2810 # if version of file is same in parent and target
2810 # if version of file is same in parent and target
2811 # manifests, do nothing
2811 # manifests, do nothing
2812 if (pmf[abs] != mfentry or
2812 if (pmf[abs] != mfentry or
2813 pmf.flags(abs) != mf.flags(abs)):
2813 pmf.flags(abs) != mf.flags(abs)):
2814 handle(revert, False)
2814 handle(revert, False)
2815 else:
2815 else:
2816 handle(remove, False)
2816 handle(remove, False)
2817
2817
2818 if not opts.get('dry_run'):
2818 if not opts.get('dry_run'):
2819 def checkout(f):
2819 def checkout(f):
2820 fc = ctx[f]
2820 fc = ctx[f]
2821 repo.wwrite(f, fc.data(), fc.flags())
2821 repo.wwrite(f, fc.data(), fc.flags())
2822
2822
2823 audit_path = util.path_auditor(repo.root)
2823 audit_path = util.path_auditor(repo.root)
2824 for f in remove[0]:
2824 for f in remove[0]:
2825 if repo.dirstate[f] == 'a':
2825 if repo.dirstate[f] == 'a':
2826 repo.dirstate.forget(f)
2826 repo.dirstate.forget(f)
2827 continue
2827 continue
2828 audit_path(f)
2828 audit_path(f)
2829 try:
2829 try:
2830 util.unlink(repo.wjoin(f))
2830 util.unlink(repo.wjoin(f))
2831 except OSError:
2831 except OSError:
2832 pass
2832 pass
2833 repo.dirstate.remove(f)
2833 repo.dirstate.remove(f)
2834
2834
2835 normal = None
2835 normal = None
2836 if node == parent:
2836 if node == parent:
2837 # We're reverting to our parent. If possible, we'd like status
2837 # We're reverting to our parent. If possible, we'd like status
2838 # to report the file as clean. We have to use normallookup for
2838 # to report the file as clean. We have to use normallookup for
2839 # merges to avoid losing information about merged/dirty files.
2839 # merges to avoid losing information about merged/dirty files.
2840 if p2 != nullid:
2840 if p2 != nullid:
2841 normal = repo.dirstate.normallookup
2841 normal = repo.dirstate.normallookup
2842 else:
2842 else:
2843 normal = repo.dirstate.normal
2843 normal = repo.dirstate.normal
2844 for f in revert[0]:
2844 for f in revert[0]:
2845 checkout(f)
2845 checkout(f)
2846 if normal:
2846 if normal:
2847 normal(f)
2847 normal(f)
2848
2848
2849 for f in add[0]:
2849 for f in add[0]:
2850 checkout(f)
2850 checkout(f)
2851 repo.dirstate.add(f)
2851 repo.dirstate.add(f)
2852
2852
2853 normal = repo.dirstate.normallookup
2853 normal = repo.dirstate.normallookup
2854 if node == parent and p2 == nullid:
2854 if node == parent and p2 == nullid:
2855 normal = repo.dirstate.normal
2855 normal = repo.dirstate.normal
2856 for f in undelete[0]:
2856 for f in undelete[0]:
2857 checkout(f)
2857 checkout(f)
2858 normal(f)
2858 normal(f)
2859
2859
2860 finally:
2860 finally:
2861 wlock.release()
2861 wlock.release()
2862
2862
2863 def rollback(ui, repo, **opts):
2863 def rollback(ui, repo, **opts):
2864 """roll back the last transaction (dangerous)
2864 """roll back the last transaction (dangerous)
2865
2865
2866 This command should be used with care. There is only one level of
2866 This command should be used with care. There is only one level of
2867 rollback, and there is no way to undo a rollback. It will also
2867 rollback, and there is no way to undo a rollback. It will also
2868 restore the dirstate at the time of the last transaction, losing
2868 restore the dirstate at the time of the last transaction, losing
2869 any dirstate changes since that time. This command does not alter
2869 any dirstate changes since that time. This command does not alter
2870 the working directory.
2870 the working directory.
2871
2871
2872 Transactions are used to encapsulate the effects of all commands
2872 Transactions are used to encapsulate the effects of all commands
2873 that create new changesets or propagate existing changesets into a
2873 that create new changesets or propagate existing changesets into a
2874 repository. For example, the following commands are transactional,
2874 repository. For example, the following commands are transactional,
2875 and their effects can be rolled back:
2875 and their effects can be rolled back:
2876
2876
2877 - commit
2877 - commit
2878 - import
2878 - import
2879 - pull
2879 - pull
2880 - push (with this repository as the destination)
2880 - push (with this repository as the destination)
2881 - unbundle
2881 - unbundle
2882
2882
2883 This command is not intended for use on public repositories. Once
2883 This command is not intended for use on public repositories. Once
2884 changes are visible for pull by other users, rolling a transaction
2884 changes are visible for pull by other users, rolling a transaction
2885 back locally is ineffective (someone else may already have pulled
2885 back locally is ineffective (someone else may already have pulled
2886 the changes). Furthermore, a race is possible with readers of the
2886 the changes). Furthermore, a race is possible with readers of the
2887 repository; for example an in-progress pull from the repository
2887 repository; for example an in-progress pull from the repository
2888 may fail if a rollback is performed.
2888 may fail if a rollback is performed.
2889 """
2889 """
2890 repo.rollback(opts.get('dry_run'))
2890 repo.rollback(opts.get('dry_run'))
2891
2891
2892 def root(ui, repo):
2892 def root(ui, repo):
2893 """print the root (top) of the current working directory
2893 """print the root (top) of the current working directory
2894
2894
2895 Print the root directory of the current repository.
2895 Print the root directory of the current repository.
2896 """
2896 """
2897 ui.write(repo.root + "\n")
2897 ui.write(repo.root + "\n")
2898
2898
2899 def serve(ui, repo, **opts):
2899 def serve(ui, repo, **opts):
2900 """start stand-alone webserver
2900 """start stand-alone webserver
2901
2901
2902 Start a local HTTP repository browser and pull server.
2902 Start a local HTTP repository browser and pull server.
2903
2903
2904 By default, the server logs accesses to stdout and errors to
2904 By default, the server logs accesses to stdout and errors to
2905 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
2905 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
2906 files.
2906 files.
2907
2907
2908 To have the server choose a free port number to listen on, specify
2908 To have the server choose a free port number to listen on, specify
2909 a port number of 0; in this case, the server will print the port
2909 a port number of 0; in this case, the server will print the port
2910 number it uses.
2910 number it uses.
2911 """
2911 """
2912
2912
2913 if opts["stdio"]:
2913 if opts["stdio"]:
2914 if repo is None:
2914 if repo is None:
2915 raise error.RepoError(_("There is no Mercurial repository here"
2915 raise error.RepoError(_("There is no Mercurial repository here"
2916 " (.hg not found)"))
2916 " (.hg not found)"))
2917 s = sshserver.sshserver(ui, repo)
2917 s = sshserver.sshserver(ui, repo)
2918 s.serve_forever()
2918 s.serve_forever()
2919
2919
2920 # this way we can check if something was given in the command-line
2920 # this way we can check if something was given in the command-line
2921 if opts.get('port'):
2921 if opts.get('port'):
2922 opts['port'] = int(opts.get('port'))
2922 opts['port'] = int(opts.get('port'))
2923
2923
2924 baseui = repo and repo.baseui or ui
2924 baseui = repo and repo.baseui or ui
2925 optlist = ("name templates style address port prefix ipv6"
2925 optlist = ("name templates style address port prefix ipv6"
2926 " accesslog errorlog certificate encoding")
2926 " accesslog errorlog certificate encoding")
2927 for o in optlist.split():
2927 for o in optlist.split():
2928 val = opts.get(o, '')
2928 val = opts.get(o, '')
2929 if val in (None, ''): # should check against default options instead
2929 if val in (None, ''): # should check against default options instead
2930 continue
2930 continue
2931 baseui.setconfig("web", o, val)
2931 baseui.setconfig("web", o, val)
2932 if repo and repo.ui != baseui:
2932 if repo and repo.ui != baseui:
2933 repo.ui.setconfig("web", o, val)
2933 repo.ui.setconfig("web", o, val)
2934
2934
2935 o = opts.get('web_conf') or opts.get('webdir_conf')
2935 o = opts.get('web_conf') or opts.get('webdir_conf')
2936 if not o:
2936 if not o:
2937 if not repo:
2937 if not repo:
2938 raise error.RepoError(_("There is no Mercurial repository"
2938 raise error.RepoError(_("There is no Mercurial repository"
2939 " here (.hg not found)"))
2939 " here (.hg not found)"))
2940 o = repo.root
2940 o = repo.root
2941
2941
2942 app = hgweb.hgweb(o, baseui=ui)
2942 app = hgweb.hgweb(o, baseui=ui)
2943
2943
2944 class service(object):
2944 class service(object):
2945 def init(self):
2945 def init(self):
2946 util.set_signal_handler()
2946 util.set_signal_handler()
2947 self.httpd = hgweb.server.create_server(ui, app)
2947 self.httpd = hgweb.server.create_server(ui, app)
2948
2948
2949 if opts['port'] and not ui.verbose:
2949 if opts['port'] and not ui.verbose:
2950 return
2950 return
2951
2951
2952 if self.httpd.prefix:
2952 if self.httpd.prefix:
2953 prefix = self.httpd.prefix.strip('/') + '/'
2953 prefix = self.httpd.prefix.strip('/') + '/'
2954 else:
2954 else:
2955 prefix = ''
2955 prefix = ''
2956
2956
2957 port = ':%d' % self.httpd.port
2957 port = ':%d' % self.httpd.port
2958 if port == ':80':
2958 if port == ':80':
2959 port = ''
2959 port = ''
2960
2960
2961 bindaddr = self.httpd.addr
2961 bindaddr = self.httpd.addr
2962 if bindaddr == '0.0.0.0':
2962 if bindaddr == '0.0.0.0':
2963 bindaddr = '*'
2963 bindaddr = '*'
2964 elif ':' in bindaddr: # IPv6
2964 elif ':' in bindaddr: # IPv6
2965 bindaddr = '[%s]' % bindaddr
2965 bindaddr = '[%s]' % bindaddr
2966
2966
2967 fqaddr = self.httpd.fqaddr
2967 fqaddr = self.httpd.fqaddr
2968 if ':' in fqaddr:
2968 if ':' in fqaddr:
2969 fqaddr = '[%s]' % fqaddr
2969 fqaddr = '[%s]' % fqaddr
2970 if opts['port']:
2970 if opts['port']:
2971 write = ui.status
2971 write = ui.status
2972 else:
2972 else:
2973 write = ui.write
2973 write = ui.write
2974 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2974 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2975 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2975 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2976
2976
2977 def run(self):
2977 def run(self):
2978 self.httpd.serve_forever()
2978 self.httpd.serve_forever()
2979
2979
2980 service = service()
2980 service = service()
2981
2981
2982 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2982 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2983
2983
2984 def status(ui, repo, *pats, **opts):
2984 def status(ui, repo, *pats, **opts):
2985 """show changed files in the working directory
2985 """show changed files in the working directory
2986
2986
2987 Show status of files in the repository. If names are given, only
2987 Show status of files in the repository. If names are given, only
2988 files that match are shown. Files that are clean or ignored or
2988 files that match are shown. Files that are clean or ignored or
2989 the source of a copy/move operation, are not listed unless
2989 the source of a copy/move operation, are not listed unless
2990 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
2990 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
2991 Unless options described with "show only ..." are given, the
2991 Unless options described with "show only ..." are given, the
2992 options -mardu are used.
2992 options -mardu are used.
2993
2993
2994 Option -q/--quiet hides untracked (unknown and ignored) files
2994 Option -q/--quiet hides untracked (unknown and ignored) files
2995 unless explicitly requested with -u/--unknown or -i/--ignored.
2995 unless explicitly requested with -u/--unknown or -i/--ignored.
2996
2996
2997 NOTE: status may appear to disagree with diff if permissions have
2997 NOTE: status may appear to disagree with diff if permissions have
2998 changed or a merge has occurred. The standard diff format does not
2998 changed or a merge has occurred. The standard diff format does not
2999 report permission changes and diff only reports changes relative
2999 report permission changes and diff only reports changes relative
3000 to one merge parent.
3000 to one merge parent.
3001
3001
3002 If one revision is given, it is used as the base revision.
3002 If one revision is given, it is used as the base revision.
3003 If two revisions are given, the differences between them are
3003 If two revisions are given, the differences between them are
3004 shown. The --change option can also be used as a shortcut to list
3004 shown. The --change option can also be used as a shortcut to list
3005 the changed files of a revision from its first parent.
3005 the changed files of a revision from its first parent.
3006
3006
3007 The codes used to show the status of files are::
3007 The codes used to show the status of files are::
3008
3008
3009 M = modified
3009 M = modified
3010 A = added
3010 A = added
3011 R = removed
3011 R = removed
3012 C = clean
3012 C = clean
3013 ! = missing (deleted by non-hg command, but still tracked)
3013 ! = missing (deleted by non-hg command, but still tracked)
3014 ? = not tracked
3014 ? = not tracked
3015 I = ignored
3015 I = ignored
3016 = origin of the previous file listed as A (added)
3016 = origin of the previous file listed as A (added)
3017 """
3017 """
3018
3018
3019 revs = opts.get('rev')
3019 revs = opts.get('rev')
3020 change = opts.get('change')
3020 change = opts.get('change')
3021
3021
3022 if revs and change:
3022 if revs and change:
3023 msg = _('cannot specify --rev and --change at the same time')
3023 msg = _('cannot specify --rev and --change at the same time')
3024 raise util.Abort(msg)
3024 raise util.Abort(msg)
3025 elif change:
3025 elif change:
3026 node2 = repo.lookup(change)
3026 node2 = repo.lookup(change)
3027 node1 = repo[node2].parents()[0].node()
3027 node1 = repo[node2].parents()[0].node()
3028 else:
3028 else:
3029 node1, node2 = cmdutil.revpair(repo, revs)
3029 node1, node2 = cmdutil.revpair(repo, revs)
3030
3030
3031 cwd = (pats and repo.getcwd()) or ''
3031 cwd = (pats and repo.getcwd()) or ''
3032 end = opts.get('print0') and '\0' or '\n'
3032 end = opts.get('print0') and '\0' or '\n'
3033 copy = {}
3033 copy = {}
3034 states = 'modified added removed deleted unknown ignored clean'.split()
3034 states = 'modified added removed deleted unknown ignored clean'.split()
3035 show = [k for k in states if opts.get(k)]
3035 show = [k for k in states if opts.get(k)]
3036 if opts.get('all'):
3036 if opts.get('all'):
3037 show += ui.quiet and (states[:4] + ['clean']) or states
3037 show += ui.quiet and (states[:4] + ['clean']) or states
3038 if not show:
3038 if not show:
3039 show = ui.quiet and states[:4] or states[:5]
3039 show = ui.quiet and states[:4] or states[:5]
3040
3040
3041 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3041 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3042 'ignored' in show, 'clean' in show, 'unknown' in show)
3042 'ignored' in show, 'clean' in show, 'unknown' in show)
3043 changestates = zip(states, 'MAR!?IC', stat)
3043 changestates = zip(states, 'MAR!?IC', stat)
3044
3044
3045 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3045 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3046 ctxn = repo[nullid]
3046 ctxn = repo[nullid]
3047 ctx1 = repo[node1]
3047 ctx1 = repo[node1]
3048 ctx2 = repo[node2]
3048 ctx2 = repo[node2]
3049 added = stat[1]
3049 added = stat[1]
3050 if node2 is None:
3050 if node2 is None:
3051 added = stat[0] + stat[1] # merged?
3051 added = stat[0] + stat[1] # merged?
3052
3052
3053 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3053 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3054 if k in added:
3054 if k in added:
3055 copy[k] = v
3055 copy[k] = v
3056 elif v in added:
3056 elif v in added:
3057 copy[v] = k
3057 copy[v] = k
3058
3058
3059 for state, char, files in changestates:
3059 for state, char, files in changestates:
3060 if state in show:
3060 if state in show:
3061 format = "%s %%s%s" % (char, end)
3061 format = "%s %%s%s" % (char, end)
3062 if opts.get('no_status'):
3062 if opts.get('no_status'):
3063 format = "%%s%s" % end
3063 format = "%%s%s" % end
3064
3064
3065 for f in files:
3065 for f in files:
3066 ui.write(format % repo.pathto(f, cwd),
3066 ui.write(format % repo.pathto(f, cwd),
3067 label='status.' + state)
3067 label='status.' + state)
3068 if f in copy:
3068 if f in copy:
3069 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3069 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3070 label='status.copied')
3070 label='status.copied')
3071
3071
3072 def summary(ui, repo, **opts):
3072 def summary(ui, repo, **opts):
3073 """summarize working directory state
3073 """summarize working directory state
3074
3074
3075 This generates a brief summary of the working directory state,
3075 This generates a brief summary of the working directory state,
3076 including parents, branch, commit status, and available updates.
3076 including parents, branch, commit status, and available updates.
3077
3077
3078 With the --remote option, this will check the default paths for
3078 With the --remote option, this will check the default paths for
3079 incoming and outgoing changes. This can be time-consuming.
3079 incoming and outgoing changes. This can be time-consuming.
3080 """
3080 """
3081
3081
3082 ctx = repo[None]
3082 ctx = repo[None]
3083 parents = ctx.parents()
3083 parents = ctx.parents()
3084 pnode = parents[0].node()
3084 pnode = parents[0].node()
3085
3085
3086 for p in parents:
3086 for p in parents:
3087 # label with log.changeset (instead of log.parent) since this
3087 # label with log.changeset (instead of log.parent) since this
3088 # shows a working directory parent *changeset*:
3088 # shows a working directory parent *changeset*:
3089 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3089 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3090 label='log.changeset')
3090 label='log.changeset')
3091 ui.write(' '.join(p.tags()), label='log.tag')
3091 ui.write(' '.join(p.tags()), label='log.tag')
3092 if p.rev() == -1:
3092 if p.rev() == -1:
3093 if not len(repo):
3093 if not len(repo):
3094 ui.write(_(' (empty repository)'))
3094 ui.write(_(' (empty repository)'))
3095 else:
3095 else:
3096 ui.write(_(' (no revision checked out)'))
3096 ui.write(_(' (no revision checked out)'))
3097 ui.write('\n')
3097 ui.write('\n')
3098 if p.description():
3098 if p.description():
3099 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3099 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3100 label='log.summary')
3100 label='log.summary')
3101
3101
3102 branch = ctx.branch()
3102 branch = ctx.branch()
3103 bheads = repo.branchheads(branch)
3103 bheads = repo.branchheads(branch)
3104 m = _('branch: %s\n') % branch
3104 m = _('branch: %s\n') % branch
3105 if branch != 'default':
3105 if branch != 'default':
3106 ui.write(m, label='log.branch')
3106 ui.write(m, label='log.branch')
3107 else:
3107 else:
3108 ui.status(m, label='log.branch')
3108 ui.status(m, label='log.branch')
3109
3109
3110 st = list(repo.status(unknown=True))[:6]
3110 st = list(repo.status(unknown=True))[:6]
3111 ms = mergemod.mergestate(repo)
3111 ms = mergemod.mergestate(repo)
3112 st.append([f for f in ms if ms[f] == 'u'])
3112 st.append([f for f in ms if ms[f] == 'u'])
3113 labels = [ui.label(_('%d modified'), 'status.modified'),
3113 labels = [ui.label(_('%d modified'), 'status.modified'),
3114 ui.label(_('%d added'), 'status.added'),
3114 ui.label(_('%d added'), 'status.added'),
3115 ui.label(_('%d removed'), 'status.removed'),
3115 ui.label(_('%d removed'), 'status.removed'),
3116 ui.label(_('%d deleted'), 'status.deleted'),
3116 ui.label(_('%d deleted'), 'status.deleted'),
3117 ui.label(_('%d unknown'), 'status.unknown'),
3117 ui.label(_('%d unknown'), 'status.unknown'),
3118 ui.label(_('%d ignored'), 'status.ignored'),
3118 ui.label(_('%d ignored'), 'status.ignored'),
3119 ui.label(_('%d unresolved'), 'resolve.unresolved')]
3119 ui.label(_('%d unresolved'), 'resolve.unresolved')]
3120 t = []
3120 t = []
3121 for s, l in zip(st, labels):
3121 for s, l in zip(st, labels):
3122 if s:
3122 if s:
3123 t.append(l % len(s))
3123 t.append(l % len(s))
3124
3124
3125 t = ', '.join(t)
3125 t = ', '.join(t)
3126 cleanworkdir = False
3126 cleanworkdir = False
3127
3127
3128 if len(parents) > 1:
3128 if len(parents) > 1:
3129 t += _(' (merge)')
3129 t += _(' (merge)')
3130 elif branch != parents[0].branch():
3130 elif branch != parents[0].branch():
3131 t += _(' (new branch)')
3131 t += _(' (new branch)')
3132 elif (not st[0] and not st[1] and not st[2]):
3132 elif (not st[0] and not st[1] and not st[2]):
3133 t += _(' (clean)')
3133 t += _(' (clean)')
3134 cleanworkdir = True
3134 cleanworkdir = True
3135 elif pnode not in bheads:
3135 elif pnode not in bheads:
3136 t += _(' (new branch head)')
3136 t += _(' (new branch head)')
3137
3137
3138 if cleanworkdir:
3138 if cleanworkdir:
3139 ui.status(_('commit: %s\n') % t.strip())
3139 ui.status(_('commit: %s\n') % t.strip())
3140 else:
3140 else:
3141 ui.write(_('commit: %s\n') % t.strip())
3141 ui.write(_('commit: %s\n') % t.strip())
3142
3142
3143 # all ancestors of branch heads - all ancestors of parent = new csets
3143 # all ancestors of branch heads - all ancestors of parent = new csets
3144 new = [0] * len(repo)
3144 new = [0] * len(repo)
3145 cl = repo.changelog
3145 cl = repo.changelog
3146 for a in [cl.rev(n) for n in bheads]:
3146 for a in [cl.rev(n) for n in bheads]:
3147 new[a] = 1
3147 new[a] = 1
3148 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3148 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3149 new[a] = 1
3149 new[a] = 1
3150 for a in [p.rev() for p in parents]:
3150 for a in [p.rev() for p in parents]:
3151 if a >= 0:
3151 if a >= 0:
3152 new[a] = 0
3152 new[a] = 0
3153 for a in cl.ancestors(*[p.rev() for p in parents]):
3153 for a in cl.ancestors(*[p.rev() for p in parents]):
3154 new[a] = 0
3154 new[a] = 0
3155 new = sum(new)
3155 new = sum(new)
3156
3156
3157 if new == 0:
3157 if new == 0:
3158 ui.status(_('update: (current)\n'))
3158 ui.status(_('update: (current)\n'))
3159 elif pnode not in bheads:
3159 elif pnode not in bheads:
3160 ui.write(_('update: %d new changesets (update)\n') % new)
3160 ui.write(_('update: %d new changesets (update)\n') % new)
3161 else:
3161 else:
3162 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3162 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3163 (new, len(bheads)))
3163 (new, len(bheads)))
3164
3164
3165 if opts.get('remote'):
3165 if opts.get('remote'):
3166 t = []
3166 t = []
3167 source, branches = hg.parseurl(ui.expandpath('default'))
3167 source, branches = hg.parseurl(ui.expandpath('default'))
3168 other = hg.repository(cmdutil.remoteui(repo, {}), source)
3168 other = hg.repository(cmdutil.remoteui(repo, {}), source)
3169 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3169 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3170 ui.debug('comparing with %s\n' % url.hidepassword(source))
3170 ui.debug('comparing with %s\n' % url.hidepassword(source))
3171 repo.ui.pushbuffer()
3171 repo.ui.pushbuffer()
3172 common, incoming, rheads = repo.findcommonincoming(other)
3172 common, incoming, rheads = repo.findcommonincoming(other)
3173 repo.ui.popbuffer()
3173 repo.ui.popbuffer()
3174 if incoming:
3174 if incoming:
3175 t.append(_('1 or more incoming'))
3175 t.append(_('1 or more incoming'))
3176
3176
3177 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3177 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3179 other = hg.repository(cmdutil.remoteui(repo, {}), dest)
3179 other = hg.repository(cmdutil.remoteui(repo, {}), dest)
3180 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3180 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3181 repo.ui.pushbuffer()
3181 repo.ui.pushbuffer()
3182 o = repo.findoutgoing(other)
3182 o = repo.findoutgoing(other)
3183 repo.ui.popbuffer()
3183 repo.ui.popbuffer()
3184 o = repo.changelog.nodesbetween(o, None)[0]
3184 o = repo.changelog.nodesbetween(o, None)[0]
3185 if o:
3185 if o:
3186 t.append(_('%d outgoing') % len(o))
3186 t.append(_('%d outgoing') % len(o))
3187
3187
3188 if t:
3188 if t:
3189 ui.write(_('remote: %s\n') % (', '.join(t)))
3189 ui.write(_('remote: %s\n') % (', '.join(t)))
3190 else:
3190 else:
3191 ui.status(_('remote: (synced)\n'))
3191 ui.status(_('remote: (synced)\n'))
3192
3192
3193 def tag(ui, repo, name1, *names, **opts):
3193 def tag(ui, repo, name1, *names, **opts):
3194 """add one or more tags for the current or given revision
3194 """add one or more tags for the current or given revision
3195
3195
3196 Name a particular revision using <name>.
3196 Name a particular revision using <name>.
3197
3197
3198 Tags are used to name particular revisions of the repository and are
3198 Tags are used to name particular revisions of the repository and are
3199 very useful to compare different revisions, to go back to significant
3199 very useful to compare different revisions, to go back to significant
3200 earlier versions or to mark branch points as releases, etc.
3200 earlier versions or to mark branch points as releases, etc.
3201
3201
3202 If no revision is given, the parent of the working directory is
3202 If no revision is given, the parent of the working directory is
3203 used, or tip if no revision is checked out.
3203 used, or tip if no revision is checked out.
3204
3204
3205 To facilitate version control, distribution, and merging of tags,
3205 To facilitate version control, distribution, and merging of tags,
3206 they are stored as a file named ".hgtags" which is managed
3206 they are stored as a file named ".hgtags" which is managed
3207 similarly to other project files and can be hand-edited if
3207 similarly to other project files and can be hand-edited if
3208 necessary. The file '.hg/localtags' is used for local tags (not
3208 necessary. The file '.hg/localtags' is used for local tags (not
3209 shared among repositories).
3209 shared among repositories).
3210
3210
3211 See :hg:`help dates` for a list of formats valid for -d/--date.
3211 See :hg:`help dates` for a list of formats valid for -d/--date.
3212 """
3212 """
3213
3213
3214 rev_ = "."
3214 rev_ = "."
3215 names = (name1,) + names
3215 names = (name1,) + names
3216 if len(names) != len(set(names)):
3216 if len(names) != len(set(names)):
3217 raise util.Abort(_('tag names must be unique'))
3217 raise util.Abort(_('tag names must be unique'))
3218 for n in names:
3218 for n in names:
3219 if n in ['tip', '.', 'null']:
3219 if n in ['tip', '.', 'null']:
3220 raise util.Abort(_('the name \'%s\' is reserved') % n)
3220 raise util.Abort(_('the name \'%s\' is reserved') % n)
3221 if opts.get('rev') and opts.get('remove'):
3221 if opts.get('rev') and opts.get('remove'):
3222 raise util.Abort(_("--rev and --remove are incompatible"))
3222 raise util.Abort(_("--rev and --remove are incompatible"))
3223 if opts.get('rev'):
3223 if opts.get('rev'):
3224 rev_ = opts['rev']
3224 rev_ = opts['rev']
3225 message = opts.get('message')
3225 message = opts.get('message')
3226 if opts.get('remove'):
3226 if opts.get('remove'):
3227 expectedtype = opts.get('local') and 'local' or 'global'
3227 expectedtype = opts.get('local') and 'local' or 'global'
3228 for n in names:
3228 for n in names:
3229 if not repo.tagtype(n):
3229 if not repo.tagtype(n):
3230 raise util.Abort(_('tag \'%s\' does not exist') % n)
3230 raise util.Abort(_('tag \'%s\' does not exist') % n)
3231 if repo.tagtype(n) != expectedtype:
3231 if repo.tagtype(n) != expectedtype:
3232 if expectedtype == 'global':
3232 if expectedtype == 'global':
3233 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3233 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3234 else:
3234 else:
3235 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3235 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3236 rev_ = nullid
3236 rev_ = nullid
3237 if not message:
3237 if not message:
3238 # we don't translate commit messages
3238 # we don't translate commit messages
3239 message = 'Removed tag %s' % ', '.join(names)
3239 message = 'Removed tag %s' % ', '.join(names)
3240 elif not opts.get('force'):
3240 elif not opts.get('force'):
3241 for n in names:
3241 for n in names:
3242 if n in repo.tags():
3242 if n in repo.tags():
3243 raise util.Abort(_('tag \'%s\' already exists '
3243 raise util.Abort(_('tag \'%s\' already exists '
3244 '(use -f to force)') % n)
3244 '(use -f to force)') % n)
3245 if not rev_ and repo.dirstate.parents()[1] != nullid:
3245 if not rev_ and repo.dirstate.parents()[1] != nullid:
3246 raise util.Abort(_('uncommitted merge - please provide a '
3246 raise util.Abort(_('uncommitted merge - please provide a '
3247 'specific revision'))
3247 'specific revision'))
3248 r = repo[rev_].node()
3248 r = repo[rev_].node()
3249
3249
3250 if not message:
3250 if not message:
3251 # we don't translate commit messages
3251 # we don't translate commit messages
3252 message = ('Added tag %s for changeset %s' %
3252 message = ('Added tag %s for changeset %s' %
3253 (', '.join(names), short(r)))
3253 (', '.join(names), short(r)))
3254
3254
3255 date = opts.get('date')
3255 date = opts.get('date')
3256 if date:
3256 if date:
3257 date = util.parsedate(date)
3257 date = util.parsedate(date)
3258
3258
3259 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3259 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3260
3260
3261 def tags(ui, repo):
3261 def tags(ui, repo):
3262 """list repository tags
3262 """list repository tags
3263
3263
3264 This lists both regular and local tags. When the -v/--verbose
3264 This lists both regular and local tags. When the -v/--verbose
3265 switch is used, a third column "local" is printed for local tags.
3265 switch is used, a third column "local" is printed for local tags.
3266 """
3266 """
3267
3267
3268 hexfunc = ui.debugflag and hex or short
3268 hexfunc = ui.debugflag and hex or short
3269 tagtype = ""
3269 tagtype = ""
3270
3270
3271 for t, n in reversed(repo.tagslist()):
3271 for t, n in reversed(repo.tagslist()):
3272 if ui.quiet:
3272 if ui.quiet:
3273 ui.write("%s\n" % t)
3273 ui.write("%s\n" % t)
3274 continue
3274 continue
3275
3275
3276 try:
3276 try:
3277 hn = hexfunc(n)
3277 hn = hexfunc(n)
3278 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3278 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3279 except error.LookupError:
3279 except error.LookupError:
3280 r = " ?:%s" % hn
3280 r = " ?:%s" % hn
3281 else:
3281 else:
3282 spaces = " " * (30 - encoding.colwidth(t))
3282 spaces = " " * (30 - encoding.colwidth(t))
3283 if ui.verbose:
3283 if ui.verbose:
3284 if repo.tagtype(t) == 'local':
3284 if repo.tagtype(t) == 'local':
3285 tagtype = " local"
3285 tagtype = " local"
3286 else:
3286 else:
3287 tagtype = ""
3287 tagtype = ""
3288 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3288 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3289
3289
3290 def tip(ui, repo, **opts):
3290 def tip(ui, repo, **opts):
3291 """show the tip revision
3291 """show the tip revision
3292
3292
3293 The tip revision (usually just called the tip) is the changeset
3293 The tip revision (usually just called the tip) is the changeset
3294 most recently added to the repository (and therefore the most
3294 most recently added to the repository (and therefore the most
3295 recently changed head).
3295 recently changed head).
3296
3296
3297 If you have just made a commit, that commit will be the tip. If
3297 If you have just made a commit, that commit will be the tip. If
3298 you have just pulled changes from another repository, the tip of
3298 you have just pulled changes from another repository, the tip of
3299 that repository becomes the current tip. The "tip" tag is special
3299 that repository becomes the current tip. The "tip" tag is special
3300 and cannot be renamed or assigned to a different changeset.
3300 and cannot be renamed or assigned to a different changeset.
3301 """
3301 """
3302 displayer = cmdutil.show_changeset(ui, repo, opts)
3302 displayer = cmdutil.show_changeset(ui, repo, opts)
3303 displayer.show(repo[len(repo) - 1])
3303 displayer.show(repo[len(repo) - 1])
3304 displayer.close()
3304 displayer.close()
3305
3305
3306 def unbundle(ui, repo, fname1, *fnames, **opts):
3306 def unbundle(ui, repo, fname1, *fnames, **opts):
3307 """apply one or more changegroup files
3307 """apply one or more changegroup files
3308
3308
3309 Apply one or more compressed changegroup files generated by the
3309 Apply one or more compressed changegroup files generated by the
3310 bundle command.
3310 bundle command.
3311 """
3311 """
3312 fnames = (fname1,) + fnames
3312 fnames = (fname1,) + fnames
3313
3313
3314 lock = repo.lock()
3314 lock = repo.lock()
3315 try:
3315 try:
3316 for fname in fnames:
3316 for fname in fnames:
3317 f = url.open(ui, fname)
3317 f = url.open(ui, fname)
3318 gen = changegroup.readbundle(f, fname)
3318 gen = changegroup.readbundle(f, fname)
3319 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
3319 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
3320 finally:
3320 finally:
3321 lock.release()
3321 lock.release()
3322
3322
3323 return postincoming(ui, repo, modheads, opts.get('update'), None)
3323 return postincoming(ui, repo, modheads, opts.get('update'), None)
3324
3324
3325 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3325 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3326 """update working directory (or switch revisions)
3326 """update working directory (or switch revisions)
3327
3327
3328 Update the repository's working directory to the specified
3328 Update the repository's working directory to the specified
3329 changeset.
3329 changeset.
3330
3330
3331 If no changeset is specified, attempt to update to the head of the
3331 If no changeset is specified, attempt to update to the head of the
3332 current branch. If this head is a descendant of the working
3332 current branch. If this head is a descendant of the working
3333 directory's parent, update to it, otherwise abort.
3333 directory's parent, update to it, otherwise abort.
3334
3334
3335 The following rules apply when the working directory contains
3335 The following rules apply when the working directory contains
3336 uncommitted changes:
3336 uncommitted changes:
3337
3337
3338 1. If neither -c/--check nor -C/--clean is specified, and if
3338 1. If neither -c/--check nor -C/--clean is specified, and if
3339 the requested changeset is an ancestor or descendant of
3339 the requested changeset is an ancestor or descendant of
3340 the working directory's parent, the uncommitted changes
3340 the working directory's parent, the uncommitted changes
3341 are merged into the requested changeset and the merged
3341 are merged into the requested changeset and the merged
3342 result is left uncommitted. If the requested changeset is
3342 result is left uncommitted. If the requested changeset is
3343 not an ancestor or descendant (that is, it is on another
3343 not an ancestor or descendant (that is, it is on another
3344 branch), the update is aborted and the uncommitted changes
3344 branch), the update is aborted and the uncommitted changes
3345 are preserved.
3345 are preserved.
3346
3346
3347 2. With the -c/--check option, the update is aborted and the
3347 2. With the -c/--check option, the update is aborted and the
3348 uncommitted changes are preserved.
3348 uncommitted changes are preserved.
3349
3349
3350 3. With the -C/--clean option, uncommitted changes are discarded and
3350 3. With the -C/--clean option, uncommitted changes are discarded and
3351 the working directory is updated to the requested changeset.
3351 the working directory is updated to the requested changeset.
3352
3352
3353 Use null as the changeset to remove the working directory (like
3353 Use null as the changeset to remove the working directory (like
3354 :hg:`clone -U`).
3354 :hg:`clone -U`).
3355
3355
3356 If you want to update just one file to an older changeset, use :hg:`revert`.
3356 If you want to update just one file to an older changeset, use :hg:`revert`.
3357
3357
3358 See :hg:`help dates` for a list of formats valid for -d/--date.
3358 See :hg:`help dates` for a list of formats valid for -d/--date.
3359 """
3359 """
3360 if rev and node:
3360 if rev and node:
3361 raise util.Abort(_("please specify just one revision"))
3361 raise util.Abort(_("please specify just one revision"))
3362
3362
3363 if not rev:
3363 if not rev:
3364 rev = node
3364 rev = node
3365
3365
3366 if check and clean:
3366 if check and clean:
3367 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3367 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3368
3368
3369 if check:
3369 if check:
3370 # we could use dirty() but we can ignore merge and branch trivia
3370 # we could use dirty() but we can ignore merge and branch trivia
3371 c = repo[None]
3371 c = repo[None]
3372 if c.modified() or c.added() or c.removed():
3372 if c.modified() or c.added() or c.removed():
3373 raise util.Abort(_("uncommitted local changes"))
3373 raise util.Abort(_("uncommitted local changes"))
3374
3374
3375 if date:
3375 if date:
3376 if rev:
3376 if rev:
3377 raise util.Abort(_("you can't specify a revision and a date"))
3377 raise util.Abort(_("you can't specify a revision and a date"))
3378 rev = cmdutil.finddate(ui, repo, date)
3378 rev = cmdutil.finddate(ui, repo, date)
3379
3379
3380 if clean or check:
3380 if clean or check:
3381 return hg.clean(repo, rev)
3381 return hg.clean(repo, rev)
3382 else:
3382 else:
3383 return hg.update(repo, rev)
3383 return hg.update(repo, rev)
3384
3384
3385 def verify(ui, repo):
3385 def verify(ui, repo):
3386 """verify the integrity of the repository
3386 """verify the integrity of the repository
3387
3387
3388 Verify the integrity of the current repository.
3388 Verify the integrity of the current repository.
3389
3389
3390 This will perform an extensive check of the repository's
3390 This will perform an extensive check of the repository's
3391 integrity, validating the hashes and checksums of each entry in
3391 integrity, validating the hashes and checksums of each entry in
3392 the changelog, manifest, and tracked files, as well as the
3392 the changelog, manifest, and tracked files, as well as the
3393 integrity of their crosslinks and indices.
3393 integrity of their crosslinks and indices.
3394 """
3394 """
3395 return hg.verify(repo)
3395 return hg.verify(repo)
3396
3396
3397 def version_(ui):
3397 def version_(ui):
3398 """output version and copyright information"""
3398 """output version and copyright information"""
3399 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3399 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3400 % util.version())
3400 % util.version())
3401 ui.status(_(
3401 ui.status(_(
3402 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3402 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3403 "This is free software; see the source for copying conditions. "
3403 "This is free software; see the source for copying conditions. "
3404 "There is NO\nwarranty; "
3404 "There is NO\nwarranty; "
3405 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3405 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3406 ))
3406 ))
3407
3407
3408 # Command options and aliases are listed here, alphabetically
3408 # Command options and aliases are listed here, alphabetically
3409
3409
3410 globalopts = [
3410 globalopts = [
3411 ('R', 'repository', '',
3411 ('R', 'repository', '',
3412 _('repository root directory or name of overlay bundle file')),
3412 _('repository root directory or name of overlay bundle file')),
3413 ('', 'cwd', '', _('change working directory')),
3413 ('', 'cwd', '', _('change working directory')),
3414 ('y', 'noninteractive', None,
3414 ('y', 'noninteractive', None,
3415 _('do not prompt, assume \'yes\' for any required answers')),
3415 _('do not prompt, assume \'yes\' for any required answers')),
3416 ('q', 'quiet', None, _('suppress output')),
3416 ('q', 'quiet', None, _('suppress output')),
3417 ('v', 'verbose', None, _('enable additional output')),
3417 ('v', 'verbose', None, _('enable additional output')),
3418 ('', 'config', [],
3418 ('', 'config', [],
3419 _('set/override config option (use \'section.name=value\')')),
3419 _('set/override config option (use \'section.name=value\')')),
3420 ('', 'debug', None, _('enable debugging output')),
3420 ('', 'debug', None, _('enable debugging output')),
3421 ('', 'debugger', None, _('start debugger')),
3421 ('', 'debugger', None, _('start debugger')),
3422 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3422 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3423 ('', 'encodingmode', encoding.encodingmode,
3423 ('', 'encodingmode', encoding.encodingmode,
3424 _('set the charset encoding mode')),
3424 _('set the charset encoding mode')),
3425 ('', 'traceback', None, _('always print a traceback on exception')),
3425 ('', 'traceback', None, _('always print a traceback on exception')),
3426 ('', 'time', None, _('time how long the command takes')),
3426 ('', 'time', None, _('time how long the command takes')),
3427 ('', 'profile', None, _('print command execution profile')),
3427 ('', 'profile', None, _('print command execution profile')),
3428 ('', 'version', None, _('output version information and exit')),
3428 ('', 'version', None, _('output version information and exit')),
3429 ('h', 'help', None, _('display help and exit')),
3429 ('h', 'help', None, _('display help and exit')),
3430 ]
3430 ]
3431
3431
3432 dryrunopts = [('n', 'dry-run', None,
3432 dryrunopts = [('n', 'dry-run', None,
3433 _('do not perform actions, just print output'))]
3433 _('do not perform actions, just print output'))]
3434
3434
3435 remoteopts = [
3435 remoteopts = [
3436 ('e', 'ssh', '', _('specify ssh command to use')),
3436 ('e', 'ssh', '', _('specify ssh command to use')),
3437 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3437 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3438 ]
3438 ]
3439
3439
3440 walkopts = [
3440 walkopts = [
3441 ('I', 'include', [], _('include names matching the given patterns')),
3441 ('I', 'include', [], _('include names matching the given patterns')),
3442 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3442 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3443 ]
3443 ]
3444
3444
3445 commitopts = [
3445 commitopts = [
3446 ('m', 'message', '', _('use <text> as commit message')),
3446 ('m', 'message', '', _('use <text> as commit message')),
3447 ('l', 'logfile', '', _('read commit message from <file>')),
3447 ('l', 'logfile', '', _('read commit message from <file>')),
3448 ]
3448 ]
3449
3449
3450 commitopts2 = [
3450 commitopts2 = [
3451 ('d', 'date', '', _('record datecode as commit date')),
3451 ('d', 'date', '', _('record datecode as commit date')),
3452 ('u', 'user', '', _('record the specified user as committer')),
3452 ('u', 'user', '', _('record the specified user as committer')),
3453 ]
3453 ]
3454
3454
3455 templateopts = [
3455 templateopts = [
3456 ('', 'style', '', _('display using template map file')),
3456 ('', 'style', '', _('display using template map file')),
3457 ('', 'template', '', _('display with template')),
3457 ('', 'template', '', _('display with template')),
3458 ]
3458 ]
3459
3459
3460 logopts = [
3460 logopts = [
3461 ('p', 'patch', None, _('show patch')),
3461 ('p', 'patch', None, _('show patch')),
3462 ('g', 'git', None, _('use git extended diff format')),
3462 ('g', 'git', None, _('use git extended diff format')),
3463 ('l', 'limit', '', _('limit number of changes displayed')),
3463 ('l', 'limit', '', _('limit number of changes displayed')),
3464 ('M', 'no-merges', None, _('do not show merges')),
3464 ('M', 'no-merges', None, _('do not show merges')),
3465 ('', 'stat', None, _('output diffstat-style summary of changes')),
3465 ] + templateopts
3466 ] + templateopts
3466
3467
3467 diffopts = [
3468 diffopts = [
3468 ('a', 'text', None, _('treat all files as text')),
3469 ('a', 'text', None, _('treat all files as text')),
3469 ('g', 'git', None, _('use git extended diff format')),
3470 ('g', 'git', None, _('use git extended diff format')),
3470 ('', 'nodates', None, _('omit dates from diff headers'))
3471 ('', 'nodates', None, _('omit dates from diff headers'))
3471 ]
3472 ]
3472
3473
3473 diffopts2 = [
3474 diffopts2 = [
3474 ('p', 'show-function', None, _('show which function each change is in')),
3475 ('p', 'show-function', None, _('show which function each change is in')),
3475 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3476 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3476 ('w', 'ignore-all-space', None,
3477 ('w', 'ignore-all-space', None,
3477 _('ignore white space when comparing lines')),
3478 _('ignore white space when comparing lines')),
3478 ('b', 'ignore-space-change', None,
3479 ('b', 'ignore-space-change', None,
3479 _('ignore changes in the amount of white space')),
3480 _('ignore changes in the amount of white space')),
3480 ('B', 'ignore-blank-lines', None,
3481 ('B', 'ignore-blank-lines', None,
3481 _('ignore changes whose lines are all blank')),
3482 _('ignore changes whose lines are all blank')),
3482 ('U', 'unified', '', _('number of lines of context to show')),
3483 ('U', 'unified', '', _('number of lines of context to show')),
3483 ('', 'stat', None, _('output diffstat-style summary of changes')),
3484 ('', 'stat', None, _('output diffstat-style summary of changes')),
3484 ]
3485 ]
3485
3486
3486 similarityopts = [
3487 similarityopts = [
3487 ('s', 'similarity', '',
3488 ('s', 'similarity', '',
3488 _('guess renamed files by similarity (0<=s<=100)'))
3489 _('guess renamed files by similarity (0<=s<=100)'))
3489 ]
3490 ]
3490
3491
3491 table = {
3492 table = {
3492 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3493 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3493 "addremove":
3494 "addremove":
3494 (addremove, similarityopts + walkopts + dryrunopts,
3495 (addremove, similarityopts + walkopts + dryrunopts,
3495 _('[OPTION]... [FILE]...')),
3496 _('[OPTION]... [FILE]...')),
3496 "^annotate|blame":
3497 "^annotate|blame":
3497 (annotate,
3498 (annotate,
3498 [('r', 'rev', '', _('annotate the specified revision')),
3499 [('r', 'rev', '', _('annotate the specified revision')),
3499 ('', 'follow', None,
3500 ('', 'follow', None,
3500 _('follow copies/renames and list the filename (DEPRECATED)')),
3501 _('follow copies/renames and list the filename (DEPRECATED)')),
3501 ('', 'no-follow', None, _("don't follow copies and renames")),
3502 ('', 'no-follow', None, _("don't follow copies and renames")),
3502 ('a', 'text', None, _('treat all files as text')),
3503 ('a', 'text', None, _('treat all files as text')),
3503 ('u', 'user', None, _('list the author (long with -v)')),
3504 ('u', 'user', None, _('list the author (long with -v)')),
3504 ('f', 'file', None, _('list the filename')),
3505 ('f', 'file', None, _('list the filename')),
3505 ('d', 'date', None, _('list the date (short with -q)')),
3506 ('d', 'date', None, _('list the date (short with -q)')),
3506 ('n', 'number', None, _('list the revision number (default)')),
3507 ('n', 'number', None, _('list the revision number (default)')),
3507 ('c', 'changeset', None, _('list the changeset')),
3508 ('c', 'changeset', None, _('list the changeset')),
3508 ('l', 'line-number', None,
3509 ('l', 'line-number', None,
3509 _('show line number at the first appearance'))
3510 _('show line number at the first appearance'))
3510 ] + walkopts,
3511 ] + walkopts,
3511 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3512 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3512 "archive":
3513 "archive":
3513 (archive,
3514 (archive,
3514 [('', 'no-decode', None, _('do not pass files through decoders')),
3515 [('', 'no-decode', None, _('do not pass files through decoders')),
3515 ('p', 'prefix', '', _('directory prefix for files in archive')),
3516 ('p', 'prefix', '', _('directory prefix for files in archive')),
3516 ('r', 'rev', '', _('revision to distribute')),
3517 ('r', 'rev', '', _('revision to distribute')),
3517 ('t', 'type', '', _('type of distribution to create')),
3518 ('t', 'type', '', _('type of distribution to create')),
3518 ] + walkopts,
3519 ] + walkopts,
3519 _('[OPTION]... DEST')),
3520 _('[OPTION]... DEST')),
3520 "backout":
3521 "backout":
3521 (backout,
3522 (backout,
3522 [('', 'merge', None,
3523 [('', 'merge', None,
3523 _('merge with old dirstate parent after backout')),
3524 _('merge with old dirstate parent after backout')),
3524 ('', 'parent', '', _('parent to choose when backing out merge')),
3525 ('', 'parent', '', _('parent to choose when backing out merge')),
3525 ('r', 'rev', '', _('revision to backout')),
3526 ('r', 'rev', '', _('revision to backout')),
3526 ] + walkopts + commitopts + commitopts2,
3527 ] + walkopts + commitopts + commitopts2,
3527 _('[OPTION]... [-r] REV')),
3528 _('[OPTION]... [-r] REV')),
3528 "bisect":
3529 "bisect":
3529 (bisect,
3530 (bisect,
3530 [('r', 'reset', False, _('reset bisect state')),
3531 [('r', 'reset', False, _('reset bisect state')),
3531 ('g', 'good', False, _('mark changeset good')),
3532 ('g', 'good', False, _('mark changeset good')),
3532 ('b', 'bad', False, _('mark changeset bad')),
3533 ('b', 'bad', False, _('mark changeset bad')),
3533 ('s', 'skip', False, _('skip testing changeset')),
3534 ('s', 'skip', False, _('skip testing changeset')),
3534 ('c', 'command', '', _('use command to check changeset state')),
3535 ('c', 'command', '', _('use command to check changeset state')),
3535 ('U', 'noupdate', False, _('do not update to target'))],
3536 ('U', 'noupdate', False, _('do not update to target'))],
3536 _("[-gbsr] [-U] [-c CMD] [REV]")),
3537 _("[-gbsr] [-U] [-c CMD] [REV]")),
3537 "branch":
3538 "branch":
3538 (branch,
3539 (branch,
3539 [('f', 'force', None,
3540 [('f', 'force', None,
3540 _('set branch name even if it shadows an existing branch')),
3541 _('set branch name even if it shadows an existing branch')),
3541 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3542 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3542 _('[-fC] [NAME]')),
3543 _('[-fC] [NAME]')),
3543 "branches":
3544 "branches":
3544 (branches,
3545 (branches,
3545 [('a', 'active', False,
3546 [('a', 'active', False,
3546 _('show only branches that have unmerged heads')),
3547 _('show only branches that have unmerged heads')),
3547 ('c', 'closed', False,
3548 ('c', 'closed', False,
3548 _('show normal and closed branches'))],
3549 _('show normal and closed branches'))],
3549 _('[-ac]')),
3550 _('[-ac]')),
3550 "bundle":
3551 "bundle":
3551 (bundle,
3552 (bundle,
3552 [('f', 'force', None,
3553 [('f', 'force', None,
3553 _('run even when the destination is unrelated')),
3554 _('run even when the destination is unrelated')),
3554 ('r', 'rev', [],
3555 ('r', 'rev', [],
3555 _('a changeset intended to be added to the destination')),
3556 _('a changeset intended to be added to the destination')),
3556 ('b', 'branch', [],
3557 ('b', 'branch', [],
3557 _('a specific branch you would like to bundle')),
3558 _('a specific branch you would like to bundle')),
3558 ('', 'base', [],
3559 ('', 'base', [],
3559 _('a base changeset assumed to be available at the destination')),
3560 _('a base changeset assumed to be available at the destination')),
3560 ('a', 'all', None, _('bundle all changesets in the repository')),
3561 ('a', 'all', None, _('bundle all changesets in the repository')),
3561 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3562 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3562 ] + remoteopts,
3563 ] + remoteopts,
3563 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3564 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3564 "cat":
3565 "cat":
3565 (cat,
3566 (cat,
3566 [('o', 'output', '', _('print output to file with formatted name')),
3567 [('o', 'output', '', _('print output to file with formatted name')),
3567 ('r', 'rev', '', _('print the given revision')),
3568 ('r', 'rev', '', _('print the given revision')),
3568 ('', 'decode', None, _('apply any matching decode filter')),
3569 ('', 'decode', None, _('apply any matching decode filter')),
3569 ] + walkopts,
3570 ] + walkopts,
3570 _('[OPTION]... FILE...')),
3571 _('[OPTION]... FILE...')),
3571 "^clone":
3572 "^clone":
3572 (clone,
3573 (clone,
3573 [('U', 'noupdate', None,
3574 [('U', 'noupdate', None,
3574 _('the clone will include an empty working copy (only a repository)')),
3575 _('the clone will include an empty working copy (only a repository)')),
3575 ('u', 'updaterev', '',
3576 ('u', 'updaterev', '',
3576 _('revision, tag or branch to check out')),
3577 _('revision, tag or branch to check out')),
3577 ('r', 'rev', [],
3578 ('r', 'rev', [],
3578 _('include the specified changeset')),
3579 _('include the specified changeset')),
3579 ('b', 'branch', [],
3580 ('b', 'branch', [],
3580 _('clone only the specified branch')),
3581 _('clone only the specified branch')),
3581 ('', 'pull', None, _('use pull protocol to copy metadata')),
3582 ('', 'pull', None, _('use pull protocol to copy metadata')),
3582 ('', 'uncompressed', None,
3583 ('', 'uncompressed', None,
3583 _('use uncompressed transfer (fast over LAN)')),
3584 _('use uncompressed transfer (fast over LAN)')),
3584 ] + remoteopts,
3585 ] + remoteopts,
3585 _('[OPTION]... SOURCE [DEST]')),
3586 _('[OPTION]... SOURCE [DEST]')),
3586 "^commit|ci":
3587 "^commit|ci":
3587 (commit,
3588 (commit,
3588 [('A', 'addremove', None,
3589 [('A', 'addremove', None,
3589 _('mark new/missing files as added/removed before committing')),
3590 _('mark new/missing files as added/removed before committing')),
3590 ('', 'close-branch', None,
3591 ('', 'close-branch', None,
3591 _('mark a branch as closed, hiding it from the branch list')),
3592 _('mark a branch as closed, hiding it from the branch list')),
3592 ] + walkopts + commitopts + commitopts2,
3593 ] + walkopts + commitopts + commitopts2,
3593 _('[OPTION]... [FILE]...')),
3594 _('[OPTION]... [FILE]...')),
3594 "copy|cp":
3595 "copy|cp":
3595 (copy,
3596 (copy,
3596 [('A', 'after', None, _('record a copy that has already occurred')),
3597 [('A', 'after', None, _('record a copy that has already occurred')),
3597 ('f', 'force', None,
3598 ('f', 'force', None,
3598 _('forcibly copy over an existing managed file')),
3599 _('forcibly copy over an existing managed file')),
3599 ] + walkopts + dryrunopts,
3600 ] + walkopts + dryrunopts,
3600 _('[OPTION]... [SOURCE]... DEST')),
3601 _('[OPTION]... [SOURCE]... DEST')),
3601 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3602 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3602 "debugcheckstate": (debugcheckstate, [], ''),
3603 "debugcheckstate": (debugcheckstate, [], ''),
3603 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3604 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3604 "debugcomplete":
3605 "debugcomplete":
3605 (debugcomplete,
3606 (debugcomplete,
3606 [('o', 'options', None, _('show the command options'))],
3607 [('o', 'options', None, _('show the command options'))],
3607 _('[-o] CMD')),
3608 _('[-o] CMD')),
3608 "debugdate":
3609 "debugdate":
3609 (debugdate,
3610 (debugdate,
3610 [('e', 'extended', None, _('try extended date formats'))],
3611 [('e', 'extended', None, _('try extended date formats'))],
3611 _('[-e] DATE [RANGE]')),
3612 _('[-e] DATE [RANGE]')),
3612 "debugdata": (debugdata, [], _('FILE REV')),
3613 "debugdata": (debugdata, [], _('FILE REV')),
3613 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3614 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3614 "debugindex": (debugindex, [], _('FILE')),
3615 "debugindex": (debugindex, [], _('FILE')),
3615 "debugindexdot": (debugindexdot, [], _('FILE')),
3616 "debugindexdot": (debugindexdot, [], _('FILE')),
3616 "debuginstall": (debuginstall, [], ''),
3617 "debuginstall": (debuginstall, [], ''),
3617 "debugrebuildstate":
3618 "debugrebuildstate":
3618 (debugrebuildstate,
3619 (debugrebuildstate,
3619 [('r', 'rev', '', _('revision to rebuild to'))],
3620 [('r', 'rev', '', _('revision to rebuild to'))],
3620 _('[-r REV] [REV]')),
3621 _('[-r REV] [REV]')),
3621 "debugrename":
3622 "debugrename":
3622 (debugrename,
3623 (debugrename,
3623 [('r', 'rev', '', _('revision to debug'))],
3624 [('r', 'rev', '', _('revision to debug'))],
3624 _('[-r REV] FILE')),
3625 _('[-r REV] FILE')),
3625 "debugsetparents":
3626 "debugsetparents":
3626 (debugsetparents, [], _('REV1 [REV2]')),
3627 (debugsetparents, [], _('REV1 [REV2]')),
3627 "debugstate":
3628 "debugstate":
3628 (debugstate,
3629 (debugstate,
3629 [('', 'nodates', None, _('do not display the saved mtime'))],
3630 [('', 'nodates', None, _('do not display the saved mtime'))],
3630 _('[OPTION]...')),
3631 _('[OPTION]...')),
3631 "debugsub":
3632 "debugsub":
3632 (debugsub,
3633 (debugsub,
3633 [('r', 'rev', '', _('revision to check'))],
3634 [('r', 'rev', '', _('revision to check'))],
3634 _('[-r REV] [REV]')),
3635 _('[-r REV] [REV]')),
3635 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3636 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3636 "^diff":
3637 "^diff":
3637 (diff,
3638 (diff,
3638 [('r', 'rev', [], _('revision')),
3639 [('r', 'rev', [], _('revision')),
3639 ('c', 'change', '', _('change made by revision'))
3640 ('c', 'change', '', _('change made by revision'))
3640 ] + diffopts + diffopts2 + walkopts,
3641 ] + diffopts + diffopts2 + walkopts,
3641 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
3642 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
3642 "^export":
3643 "^export":
3643 (export,
3644 (export,
3644 [('o', 'output', '', _('print output to file with formatted name')),
3645 [('o', 'output', '', _('print output to file with formatted name')),
3645 ('', 'switch-parent', None, _('diff against the second parent')),
3646 ('', 'switch-parent', None, _('diff against the second parent')),
3646 ('r', 'rev', [], _('revisions to export')),
3647 ('r', 'rev', [], _('revisions to export')),
3647 ] + diffopts,
3648 ] + diffopts,
3648 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3649 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3649 "^forget":
3650 "^forget":
3650 (forget,
3651 (forget,
3651 [] + walkopts,
3652 [] + walkopts,
3652 _('[OPTION]... FILE...')),
3653 _('[OPTION]... FILE...')),
3653 "grep":
3654 "grep":
3654 (grep,
3655 (grep,
3655 [('0', 'print0', None, _('end fields with NUL')),
3656 [('0', 'print0', None, _('end fields with NUL')),
3656 ('', 'all', None, _('print all revisions that match')),
3657 ('', 'all', None, _('print all revisions that match')),
3657 ('f', 'follow', None,
3658 ('f', 'follow', None,
3658 _('follow changeset history,'
3659 _('follow changeset history,'
3659 ' or file history across copies and renames')),
3660 ' or file history across copies and renames')),
3660 ('i', 'ignore-case', None, _('ignore case when matching')),
3661 ('i', 'ignore-case', None, _('ignore case when matching')),
3661 ('l', 'files-with-matches', None,
3662 ('l', 'files-with-matches', None,
3662 _('print only filenames and revisions that match')),
3663 _('print only filenames and revisions that match')),
3663 ('n', 'line-number', None, _('print matching line numbers')),
3664 ('n', 'line-number', None, _('print matching line numbers')),
3664 ('r', 'rev', [], _('search in given revision range')),
3665 ('r', 'rev', [], _('search in given revision range')),
3665 ('u', 'user', None, _('list the author (long with -v)')),
3666 ('u', 'user', None, _('list the author (long with -v)')),
3666 ('d', 'date', None, _('list the date (short with -q)')),
3667 ('d', 'date', None, _('list the date (short with -q)')),
3667 ] + walkopts,
3668 ] + walkopts,
3668 _('[OPTION]... PATTERN [FILE]...')),
3669 _('[OPTION]... PATTERN [FILE]...')),
3669 "heads":
3670 "heads":
3670 (heads,
3671 (heads,
3671 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3672 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3672 ('t', 'topo', False, _('show topological heads only')),
3673 ('t', 'topo', False, _('show topological heads only')),
3673 ('a', 'active', False,
3674 ('a', 'active', False,
3674 _('show active branchheads only [DEPRECATED]')),
3675 _('show active branchheads only [DEPRECATED]')),
3675 ('c', 'closed', False,
3676 ('c', 'closed', False,
3676 _('show normal and closed branch heads')),
3677 _('show normal and closed branch heads')),
3677 ] + templateopts,
3678 ] + templateopts,
3678 _('[-ac] [-r STARTREV] [REV]...')),
3679 _('[-ac] [-r STARTREV] [REV]...')),
3679 "help": (help_, [], _('[TOPIC]')),
3680 "help": (help_, [], _('[TOPIC]')),
3680 "identify|id":
3681 "identify|id":
3681 (identify,
3682 (identify,
3682 [('r', 'rev', '', _('identify the specified revision')),
3683 [('r', 'rev', '', _('identify the specified revision')),
3683 ('n', 'num', None, _('show local revision number')),
3684 ('n', 'num', None, _('show local revision number')),
3684 ('i', 'id', None, _('show global revision id')),
3685 ('i', 'id', None, _('show global revision id')),
3685 ('b', 'branch', None, _('show branch')),
3686 ('b', 'branch', None, _('show branch')),
3686 ('t', 'tags', None, _('show tags'))],
3687 ('t', 'tags', None, _('show tags'))],
3687 _('[-nibt] [-r REV] [SOURCE]')),
3688 _('[-nibt] [-r REV] [SOURCE]')),
3688 "import|patch":
3689 "import|patch":
3689 (import_,
3690 (import_,
3690 [('p', 'strip', 1,
3691 [('p', 'strip', 1,
3691 _('directory strip option for patch. This has the same '
3692 _('directory strip option for patch. This has the same '
3692 'meaning as the corresponding patch option')),
3693 'meaning as the corresponding patch option')),
3693 ('b', 'base', '', _('base path')),
3694 ('b', 'base', '', _('base path')),
3694 ('f', 'force', None,
3695 ('f', 'force', None,
3695 _('skip check for outstanding uncommitted changes')),
3696 _('skip check for outstanding uncommitted changes')),
3696 ('', 'no-commit', None,
3697 ('', 'no-commit', None,
3697 _("don't commit, just update the working directory")),
3698 _("don't commit, just update the working directory")),
3698 ('', 'exact', None,
3699 ('', 'exact', None,
3699 _('apply patch to the nodes from which it was generated')),
3700 _('apply patch to the nodes from which it was generated')),
3700 ('', 'import-branch', None,
3701 ('', 'import-branch', None,
3701 _('use any branch information in patch (implied by --exact)'))] +
3702 _('use any branch information in patch (implied by --exact)'))] +
3702 commitopts + commitopts2 + similarityopts,
3703 commitopts + commitopts2 + similarityopts,
3703 _('[OPTION]... PATCH...')),
3704 _('[OPTION]... PATCH...')),
3704 "incoming|in":
3705 "incoming|in":
3705 (incoming,
3706 (incoming,
3706 [('f', 'force', None,
3707 [('f', 'force', None,
3707 _('run even if remote repository is unrelated')),
3708 _('run even if remote repository is unrelated')),
3708 ('n', 'newest-first', None, _('show newest record first')),
3709 ('n', 'newest-first', None, _('show newest record first')),
3709 ('', 'bundle', '', _('file to store the bundles into')),
3710 ('', 'bundle', '', _('file to store the bundles into')),
3710 ('r', 'rev', [],
3711 ('r', 'rev', [],
3711 _('a remote changeset intended to be added')),
3712 _('a remote changeset intended to be added')),
3712 ('b', 'branch', [],
3713 ('b', 'branch', [],
3713 _('a specific branch you would like to pull')),
3714 _('a specific branch you would like to pull')),
3714 ] + logopts + remoteopts,
3715 ] + logopts + remoteopts,
3715 _('[-p] [-n] [-M] [-f] [-r REV]...'
3716 _('[-p] [-n] [-M] [-f] [-r REV]...'
3716 ' [--bundle FILENAME] [SOURCE]')),
3717 ' [--bundle FILENAME] [SOURCE]')),
3717 "^init":
3718 "^init":
3718 (init,
3719 (init,
3719 remoteopts,
3720 remoteopts,
3720 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3721 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3721 "locate":
3722 "locate":
3722 (locate,
3723 (locate,
3723 [('r', 'rev', '', _('search the repository as it is in REV')),
3724 [('r', 'rev', '', _('search the repository as it is in REV')),
3724 ('0', 'print0', None,
3725 ('0', 'print0', None,
3725 _('end filenames with NUL, for use with xargs')),
3726 _('end filenames with NUL, for use with xargs')),
3726 ('f', 'fullpath', None,
3727 ('f', 'fullpath', None,
3727 _('print complete paths from the filesystem root')),
3728 _('print complete paths from the filesystem root')),
3728 ] + walkopts,
3729 ] + walkopts,
3729 _('[OPTION]... [PATTERN]...')),
3730 _('[OPTION]... [PATTERN]...')),
3730 "^log|history":
3731 "^log|history":
3731 (log,
3732 (log,
3732 [('f', 'follow', None,
3733 [('f', 'follow', None,
3733 _('follow changeset history,'
3734 _('follow changeset history,'
3734 ' or file history across copies and renames')),
3735 ' or file history across copies and renames')),
3735 ('', 'follow-first', None,
3736 ('', 'follow-first', None,
3736 _('only follow the first parent of merge changesets')),
3737 _('only follow the first parent of merge changesets')),
3737 ('d', 'date', '', _('show revisions matching date spec')),
3738 ('d', 'date', '', _('show revisions matching date spec')),
3738 ('C', 'copies', None, _('show copied files')),
3739 ('C', 'copies', None, _('show copied files')),
3739 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3740 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3740 ('r', 'rev', [], _('show the specified revision or range')),
3741 ('r', 'rev', [], _('show the specified revision or range')),
3741 ('', 'removed', None, _('include revisions where files were removed')),
3742 ('', 'removed', None, _('include revisions where files were removed')),
3742 ('m', 'only-merges', None, _('show only merges')),
3743 ('m', 'only-merges', None, _('show only merges')),
3743 ('u', 'user', [], _('revisions committed by user')),
3744 ('u', 'user', [], _('revisions committed by user')),
3744 ('', 'only-branch', [],
3745 ('', 'only-branch', [],
3745 _('show only changesets within the given named branch (DEPRECATED)')),
3746 _('show only changesets within the given named branch (DEPRECATED)')),
3746 ('b', 'branch', [],
3747 ('b', 'branch', [],
3747 _('show changesets within the given named branch')),
3748 _('show changesets within the given named branch')),
3748 ('P', 'prune', [],
3749 ('P', 'prune', [],
3749 _('do not display revision or any of its ancestors')),
3750 _('do not display revision or any of its ancestors')),
3750 ] + logopts + walkopts,
3751 ] + logopts + walkopts,
3751 _('[OPTION]... [FILE]')),
3752 _('[OPTION]... [FILE]')),
3752 "manifest":
3753 "manifest":
3753 (manifest,
3754 (manifest,
3754 [('r', 'rev', '', _('revision to display'))],
3755 [('r', 'rev', '', _('revision to display'))],
3755 _('[-r REV]')),
3756 _('[-r REV]')),
3756 "^merge":
3757 "^merge":
3757 (merge,
3758 (merge,
3758 [('f', 'force', None, _('force a merge with outstanding changes')),
3759 [('f', 'force', None, _('force a merge with outstanding changes')),
3759 ('r', 'rev', '', _('revision to merge')),
3760 ('r', 'rev', '', _('revision to merge')),
3760 ('P', 'preview', None,
3761 ('P', 'preview', None,
3761 _('review revisions to merge (no merge is performed)'))],
3762 _('review revisions to merge (no merge is performed)'))],
3762 _('[-P] [-f] [[-r] REV]')),
3763 _('[-P] [-f] [[-r] REV]')),
3763 "outgoing|out":
3764 "outgoing|out":
3764 (outgoing,
3765 (outgoing,
3765 [('f', 'force', None,
3766 [('f', 'force', None,
3766 _('run even when the destination is unrelated')),
3767 _('run even when the destination is unrelated')),
3767 ('r', 'rev', [],
3768 ('r', 'rev', [],
3768 _('a changeset intended to be included in the destination')),
3769 _('a changeset intended to be included in the destination')),
3769 ('n', 'newest-first', None, _('show newest record first')),
3770 ('n', 'newest-first', None, _('show newest record first')),
3770 ('b', 'branch', [],
3771 ('b', 'branch', [],
3771 _('a specific branch you would like to push')),
3772 _('a specific branch you would like to push')),
3772 ] + logopts + remoteopts,
3773 ] + logopts + remoteopts,
3773 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3774 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3774 "parents":
3775 "parents":
3775 (parents,
3776 (parents,
3776 [('r', 'rev', '', _('show parents of the specified revision')),
3777 [('r', 'rev', '', _('show parents of the specified revision')),
3777 ] + templateopts,
3778 ] + templateopts,
3778 _('[-r REV] [FILE]')),
3779 _('[-r REV] [FILE]')),
3779 "paths": (paths, [], _('[NAME]')),
3780 "paths": (paths, [], _('[NAME]')),
3780 "^pull":
3781 "^pull":
3781 (pull,
3782 (pull,
3782 [('u', 'update', None,
3783 [('u', 'update', None,
3783 _('update to new branch head if changesets were pulled')),
3784 _('update to new branch head if changesets were pulled')),
3784 ('f', 'force', None,
3785 ('f', 'force', None,
3785 _('run even when remote repository is unrelated')),
3786 _('run even when remote repository is unrelated')),
3786 ('r', 'rev', [],
3787 ('r', 'rev', [],
3787 _('a remote changeset intended to be added')),
3788 _('a remote changeset intended to be added')),
3788 ('b', 'branch', [],
3789 ('b', 'branch', [],
3789 _('a specific branch you would like to pull')),
3790 _('a specific branch you would like to pull')),
3790 ] + remoteopts,
3791 ] + remoteopts,
3791 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3792 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3792 "^push":
3793 "^push":
3793 (push,
3794 (push,
3794 [('f', 'force', None, _('force push')),
3795 [('f', 'force', None, _('force push')),
3795 ('r', 'rev', [],
3796 ('r', 'rev', [],
3796 _('a changeset intended to be included in the destination')),
3797 _('a changeset intended to be included in the destination')),
3797 ('b', 'branch', [],
3798 ('b', 'branch', [],
3798 _('a specific branch you would like to push')),
3799 _('a specific branch you would like to push')),
3799 ] + remoteopts,
3800 ] + remoteopts,
3800 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3801 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3801 "recover": (recover, []),
3802 "recover": (recover, []),
3802 "^remove|rm":
3803 "^remove|rm":
3803 (remove,
3804 (remove,
3804 [('A', 'after', None, _('record delete for missing files')),
3805 [('A', 'after', None, _('record delete for missing files')),
3805 ('f', 'force', None,
3806 ('f', 'force', None,
3806 _('remove (and delete) file even if added or modified')),
3807 _('remove (and delete) file even if added or modified')),
3807 ] + walkopts,
3808 ] + walkopts,
3808 _('[OPTION]... FILE...')),
3809 _('[OPTION]... FILE...')),
3809 "rename|mv":
3810 "rename|mv":
3810 (rename,
3811 (rename,
3811 [('A', 'after', None, _('record a rename that has already occurred')),
3812 [('A', 'after', None, _('record a rename that has already occurred')),
3812 ('f', 'force', None,
3813 ('f', 'force', None,
3813 _('forcibly copy over an existing managed file')),
3814 _('forcibly copy over an existing managed file')),
3814 ] + walkopts + dryrunopts,
3815 ] + walkopts + dryrunopts,
3815 _('[OPTION]... SOURCE... DEST')),
3816 _('[OPTION]... SOURCE... DEST')),
3816 "resolve":
3817 "resolve":
3817 (resolve,
3818 (resolve,
3818 [('a', 'all', None, _('select all unresolved files')),
3819 [('a', 'all', None, _('select all unresolved files')),
3819 ('l', 'list', None, _('list state of files needing merge')),
3820 ('l', 'list', None, _('list state of files needing merge')),
3820 ('m', 'mark', None, _('mark files as resolved')),
3821 ('m', 'mark', None, _('mark files as resolved')),
3821 ('u', 'unmark', None, _('unmark files as resolved')),
3822 ('u', 'unmark', None, _('unmark files as resolved')),
3822 ('n', 'no-status', None, _('hide status prefix'))]
3823 ('n', 'no-status', None, _('hide status prefix'))]
3823 + walkopts,
3824 + walkopts,
3824 _('[OPTION]... [FILE]...')),
3825 _('[OPTION]... [FILE]...')),
3825 "revert":
3826 "revert":
3826 (revert,
3827 (revert,
3827 [('a', 'all', None, _('revert all changes when no arguments given')),
3828 [('a', 'all', None, _('revert all changes when no arguments given')),
3828 ('d', 'date', '', _('tipmost revision matching date')),
3829 ('d', 'date', '', _('tipmost revision matching date')),
3829 ('r', 'rev', '', _('revert to the specified revision')),
3830 ('r', 'rev', '', _('revert to the specified revision')),
3830 ('', 'no-backup', None, _('do not save backup copies of files')),
3831 ('', 'no-backup', None, _('do not save backup copies of files')),
3831 ] + walkopts + dryrunopts,
3832 ] + walkopts + dryrunopts,
3832 _('[OPTION]... [-r REV] [NAME]...')),
3833 _('[OPTION]... [-r REV] [NAME]...')),
3833 "rollback": (rollback, dryrunopts),
3834 "rollback": (rollback, dryrunopts),
3834 "root": (root, []),
3835 "root": (root, []),
3835 "^serve":
3836 "^serve":
3836 (serve,
3837 (serve,
3837 [('A', 'accesslog', '', _('name of access log file to write to')),
3838 [('A', 'accesslog', '', _('name of access log file to write to')),
3838 ('d', 'daemon', None, _('run server in background')),
3839 ('d', 'daemon', None, _('run server in background')),
3839 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3840 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3840 ('E', 'errorlog', '', _('name of error log file to write to')),
3841 ('E', 'errorlog', '', _('name of error log file to write to')),
3841 # use string type, then we can check if something was passed
3842 # use string type, then we can check if something was passed
3842 ('p', 'port', '', _('port to listen on (default: 8000)')),
3843 ('p', 'port', '', _('port to listen on (default: 8000)')),
3843 ('a', 'address', '',
3844 ('a', 'address', '',
3844 _('address to listen on (default: all interfaces)')),
3845 _('address to listen on (default: all interfaces)')),
3845 ('', 'prefix', '',
3846 ('', 'prefix', '',
3846 _('prefix path to serve from (default: server root)')),
3847 _('prefix path to serve from (default: server root)')),
3847 ('n', 'name', '',
3848 ('n', 'name', '',
3848 _('name to show in web pages (default: working directory)')),
3849 _('name to show in web pages (default: working directory)')),
3849 ('', 'web-conf', '', _('name of the hgweb config file'
3850 ('', 'web-conf', '', _('name of the hgweb config file'
3850 ' (serve more than one repository)')),
3851 ' (serve more than one repository)')),
3851 ('', 'webdir-conf', '', _('name of the hgweb config file'
3852 ('', 'webdir-conf', '', _('name of the hgweb config file'
3852 ' (DEPRECATED)')),
3853 ' (DEPRECATED)')),
3853 ('', 'pid-file', '', _('name of file to write process ID to')),
3854 ('', 'pid-file', '', _('name of file to write process ID to')),
3854 ('', 'stdio', None, _('for remote clients')),
3855 ('', 'stdio', None, _('for remote clients')),
3855 ('t', 'templates', '', _('web templates to use')),
3856 ('t', 'templates', '', _('web templates to use')),
3856 ('', 'style', '', _('template style to use')),
3857 ('', 'style', '', _('template style to use')),
3857 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3858 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3858 ('', 'certificate', '', _('SSL certificate file'))],
3859 ('', 'certificate', '', _('SSL certificate file'))],
3859 _('[OPTION]...')),
3860 _('[OPTION]...')),
3860 "showconfig|debugconfig":
3861 "showconfig|debugconfig":
3861 (showconfig,
3862 (showconfig,
3862 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3863 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3863 _('[-u] [NAME]...')),
3864 _('[-u] [NAME]...')),
3864 "^summary|sum":
3865 "^summary|sum":
3865 (summary,
3866 (summary,
3866 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
3867 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
3867 "^status|st":
3868 "^status|st":
3868 (status,
3869 (status,
3869 [('A', 'all', None, _('show status of all files')),
3870 [('A', 'all', None, _('show status of all files')),
3870 ('m', 'modified', None, _('show only modified files')),
3871 ('m', 'modified', None, _('show only modified files')),
3871 ('a', 'added', None, _('show only added files')),
3872 ('a', 'added', None, _('show only added files')),
3872 ('r', 'removed', None, _('show only removed files')),
3873 ('r', 'removed', None, _('show only removed files')),
3873 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3874 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3874 ('c', 'clean', None, _('show only files without changes')),
3875 ('c', 'clean', None, _('show only files without changes')),
3875 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3876 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3876 ('i', 'ignored', None, _('show only ignored files')),
3877 ('i', 'ignored', None, _('show only ignored files')),
3877 ('n', 'no-status', None, _('hide status prefix')),
3878 ('n', 'no-status', None, _('hide status prefix')),
3878 ('C', 'copies', None, _('show source of copied files')),
3879 ('C', 'copies', None, _('show source of copied files')),
3879 ('0', 'print0', None,
3880 ('0', 'print0', None,
3880 _('end filenames with NUL, for use with xargs')),
3881 _('end filenames with NUL, for use with xargs')),
3881 ('', 'rev', [], _('show difference from revision')),
3882 ('', 'rev', [], _('show difference from revision')),
3882 ('', 'change', '', _('list the changed files of a revision')),
3883 ('', 'change', '', _('list the changed files of a revision')),
3883 ] + walkopts,
3884 ] + walkopts,
3884 _('[OPTION]... [FILE]...')),
3885 _('[OPTION]... [FILE]...')),
3885 "tag":
3886 "tag":
3886 (tag,
3887 (tag,
3887 [('f', 'force', None, _('replace existing tag')),
3888 [('f', 'force', None, _('replace existing tag')),
3888 ('l', 'local', None, _('make the tag local')),
3889 ('l', 'local', None, _('make the tag local')),
3889 ('r', 'rev', '', _('revision to tag')),
3890 ('r', 'rev', '', _('revision to tag')),
3890 ('', 'remove', None, _('remove a tag')),
3891 ('', 'remove', None, _('remove a tag')),
3891 # -l/--local is already there, commitopts cannot be used
3892 # -l/--local is already there, commitopts cannot be used
3892 ('m', 'message', '', _('use <text> as commit message')),
3893 ('m', 'message', '', _('use <text> as commit message')),
3893 ] + commitopts2,
3894 ] + commitopts2,
3894 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3895 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3895 "tags": (tags, [], ''),
3896 "tags": (tags, [], ''),
3896 "tip":
3897 "tip":
3897 (tip,
3898 (tip,
3898 [('p', 'patch', None, _('show patch')),
3899 [('p', 'patch', None, _('show patch')),
3899 ('g', 'git', None, _('use git extended diff format')),
3900 ('g', 'git', None, _('use git extended diff format')),
3900 ] + templateopts,
3901 ] + templateopts,
3901 _('[-p] [-g]')),
3902 _('[-p] [-g]')),
3902 "unbundle":
3903 "unbundle":
3903 (unbundle,
3904 (unbundle,
3904 [('u', 'update', None,
3905 [('u', 'update', None,
3905 _('update to new branch head if changesets were unbundled'))],
3906 _('update to new branch head if changesets were unbundled'))],
3906 _('[-u] FILE...')),
3907 _('[-u] FILE...')),
3907 "^update|up|checkout|co":
3908 "^update|up|checkout|co":
3908 (update,
3909 (update,
3909 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
3910 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
3910 ('c', 'check', None, _('check for uncommitted changes')),
3911 ('c', 'check', None, _('check for uncommitted changes')),
3911 ('d', 'date', '', _('tipmost revision matching date')),
3912 ('d', 'date', '', _('tipmost revision matching date')),
3912 ('r', 'rev', '', _('revision'))],
3913 ('r', 'rev', '', _('revision'))],
3913 _('[-c] [-C] [-d DATE] [[-r] REV]')),
3914 _('[-c] [-C] [-d DATE] [[-r] REV]')),
3914 "verify": (verify, []),
3915 "verify": (verify, []),
3915 "version": (version_, []),
3916 "version": (version_, []),
3916 }
3917 }
3917
3918
3918 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3919 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3919 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3920 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3920 optionalrepo = ("identify paths serve showconfig debugancestor")
3921 optionalrepo = ("identify paths serve showconfig debugancestor")
@@ -1,231 +1,231 b''
1 % Show all commands except debug commands
1 % Show all commands except debug commands
2 add
2 add
3 addremove
3 addremove
4 annotate
4 annotate
5 archive
5 archive
6 backout
6 backout
7 bisect
7 bisect
8 branch
8 branch
9 branches
9 branches
10 bundle
10 bundle
11 cat
11 cat
12 clone
12 clone
13 commit
13 commit
14 copy
14 copy
15 diff
15 diff
16 export
16 export
17 forget
17 forget
18 grep
18 grep
19 heads
19 heads
20 help
20 help
21 identify
21 identify
22 import
22 import
23 incoming
23 incoming
24 init
24 init
25 locate
25 locate
26 log
26 log
27 manifest
27 manifest
28 merge
28 merge
29 outgoing
29 outgoing
30 parents
30 parents
31 paths
31 paths
32 pull
32 pull
33 push
33 push
34 recover
34 recover
35 remove
35 remove
36 rename
36 rename
37 resolve
37 resolve
38 revert
38 revert
39 rollback
39 rollback
40 root
40 root
41 serve
41 serve
42 showconfig
42 showconfig
43 status
43 status
44 summary
44 summary
45 tag
45 tag
46 tags
46 tags
47 tip
47 tip
48 unbundle
48 unbundle
49 update
49 update
50 verify
50 verify
51 version
51 version
52
52
53 % Show all commands that start with "a"
53 % Show all commands that start with "a"
54 add
54 add
55 addremove
55 addremove
56 annotate
56 annotate
57 archive
57 archive
58
58
59 % Do not show debug commands if there are other candidates
59 % Do not show debug commands if there are other candidates
60 diff
60 diff
61
61
62 % Show debug commands if there are no other candidates
62 % Show debug commands if there are no other candidates
63 debugancestor
63 debugancestor
64 debugcheckstate
64 debugcheckstate
65 debugcommands
65 debugcommands
66 debugcomplete
66 debugcomplete
67 debugconfig
67 debugconfig
68 debugdata
68 debugdata
69 debugdate
69 debugdate
70 debugfsinfo
70 debugfsinfo
71 debugindex
71 debugindex
72 debugindexdot
72 debugindexdot
73 debuginstall
73 debuginstall
74 debugrebuildstate
74 debugrebuildstate
75 debugrename
75 debugrename
76 debugsetparents
76 debugsetparents
77 debugstate
77 debugstate
78 debugsub
78 debugsub
79 debugwalk
79 debugwalk
80
80
81 % Do not show the alias of a debug command if there are other candidates
81 % Do not show the alias of a debug command if there are other candidates
82 % (this should hide rawcommit)
82 % (this should hide rawcommit)
83 recover
83 recover
84 remove
84 remove
85 rename
85 rename
86 resolve
86 resolve
87 revert
87 revert
88 rollback
88 rollback
89 root
89 root
90
90
91 % Show the alias of a debug command if there are no other candidates
91 % Show the alias of a debug command if there are no other candidates
92
92
93
93
94 % Show the global options
94 % Show the global options
95 --config
95 --config
96 --cwd
96 --cwd
97 --debug
97 --debug
98 --debugger
98 --debugger
99 --encoding
99 --encoding
100 --encodingmode
100 --encodingmode
101 --help
101 --help
102 --noninteractive
102 --noninteractive
103 --profile
103 --profile
104 --quiet
104 --quiet
105 --repository
105 --repository
106 --time
106 --time
107 --traceback
107 --traceback
108 --verbose
108 --verbose
109 --version
109 --version
110 -R
110 -R
111 -h
111 -h
112 -q
112 -q
113 -v
113 -v
114 -y
114 -y
115
115
116 % Show the options for the "serve" command
116 % Show the options for the "serve" command
117 --accesslog
117 --accesslog
118 --address
118 --address
119 --certificate
119 --certificate
120 --config
120 --config
121 --cwd
121 --cwd
122 --daemon
122 --daemon
123 --daemon-pipefds
123 --daemon-pipefds
124 --debug
124 --debug
125 --debugger
125 --debugger
126 --encoding
126 --encoding
127 --encodingmode
127 --encodingmode
128 --errorlog
128 --errorlog
129 --help
129 --help
130 --ipv6
130 --ipv6
131 --name
131 --name
132 --noninteractive
132 --noninteractive
133 --pid-file
133 --pid-file
134 --port
134 --port
135 --prefix
135 --prefix
136 --profile
136 --profile
137 --quiet
137 --quiet
138 --repository
138 --repository
139 --stdio
139 --stdio
140 --style
140 --style
141 --templates
141 --templates
142 --time
142 --time
143 --traceback
143 --traceback
144 --verbose
144 --verbose
145 --version
145 --version
146 --web-conf
146 --web-conf
147 -6
147 -6
148 -A
148 -A
149 -E
149 -E
150 -R
150 -R
151 -a
151 -a
152 -d
152 -d
153 -h
153 -h
154 -n
154 -n
155 -p
155 -p
156 -q
156 -q
157 -t
157 -t
158 -v
158 -v
159 -y
159 -y
160
160
161 % Show an error if we use --options with an ambiguous abbreviation
161 % Show an error if we use --options with an ambiguous abbreviation
162 hg: command 's' is ambiguous:
162 hg: command 's' is ambiguous:
163 serve showconfig status summary
163 serve showconfig status summary
164
164
165 % Show all commands + options
165 % Show all commands + options
166 add: include, exclude, dry-run
166 add: include, exclude, dry-run
167 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
167 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
168 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
168 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
169 commit: addremove, close-branch, include, exclude, message, logfile, date, user
169 commit: addremove, close-branch, include, exclude, message, logfile, date, user
170 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
170 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
171 export: output, switch-parent, rev, text, git, nodates
171 export: output, switch-parent, rev, text, git, nodates
172 forget: include, exclude
172 forget: include, exclude
173 init: ssh, remotecmd
173 init: ssh, remotecmd
174 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, style, template, include, exclude
174 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
175 merge: force, rev, preview
175 merge: force, rev, preview
176 pull: update, force, rev, branch, ssh, remotecmd
176 pull: update, force, rev, branch, ssh, remotecmd
177 push: force, rev, branch, ssh, remotecmd
177 push: force, rev, branch, ssh, remotecmd
178 remove: after, force, include, exclude
178 remove: after, force, include, exclude
179 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
179 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
180 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
180 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
181 summary: remote
181 summary: remote
182 update: clean, check, date, rev
182 update: clean, check, date, rev
183 addremove: similarity, include, exclude, dry-run
183 addremove: similarity, include, exclude, dry-run
184 archive: no-decode, prefix, rev, type, include, exclude
184 archive: no-decode, prefix, rev, type, include, exclude
185 backout: merge, parent, rev, include, exclude, message, logfile, date, user
185 backout: merge, parent, rev, include, exclude, message, logfile, date, user
186 bisect: reset, good, bad, skip, command, noupdate
186 bisect: reset, good, bad, skip, command, noupdate
187 branch: force, clean
187 branch: force, clean
188 branches: active, closed
188 branches: active, closed
189 bundle: force, rev, branch, base, all, type, ssh, remotecmd
189 bundle: force, rev, branch, base, all, type, ssh, remotecmd
190 cat: output, rev, decode, include, exclude
190 cat: output, rev, decode, include, exclude
191 copy: after, force, include, exclude, dry-run
191 copy: after, force, include, exclude, dry-run
192 debugancestor:
192 debugancestor:
193 debugcheckstate:
193 debugcheckstate:
194 debugcommands:
194 debugcommands:
195 debugcomplete: options
195 debugcomplete: options
196 debugdata:
196 debugdata:
197 debugdate: extended
197 debugdate: extended
198 debugfsinfo:
198 debugfsinfo:
199 debugindex:
199 debugindex:
200 debugindexdot:
200 debugindexdot:
201 debuginstall:
201 debuginstall:
202 debugrebuildstate: rev
202 debugrebuildstate: rev
203 debugrename: rev
203 debugrename: rev
204 debugsetparents:
204 debugsetparents:
205 debugstate: nodates
205 debugstate: nodates
206 debugsub: rev
206 debugsub: rev
207 debugwalk: include, exclude
207 debugwalk: include, exclude
208 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
208 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
209 heads: rev, topo, active, closed, style, template
209 heads: rev, topo, active, closed, style, template
210 help:
210 help:
211 identify: rev, num, id, branch, tags
211 identify: rev, num, id, branch, tags
212 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
212 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
213 incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
213 incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
214 locate: rev, print0, fullpath, include, exclude
214 locate: rev, print0, fullpath, include, exclude
215 manifest: rev
215 manifest: rev
216 outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
216 outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
217 parents: rev, style, template
217 parents: rev, style, template
218 paths:
218 paths:
219 recover:
219 recover:
220 rename: after, force, include, exclude, dry-run
220 rename: after, force, include, exclude, dry-run
221 resolve: all, list, mark, unmark, no-status, include, exclude
221 resolve: all, list, mark, unmark, no-status, include, exclude
222 revert: all, date, rev, no-backup, include, exclude, dry-run
222 revert: all, date, rev, no-backup, include, exclude, dry-run
223 rollback: dry-run
223 rollback: dry-run
224 root:
224 root:
225 showconfig: untrusted
225 showconfig: untrusted
226 tag: force, local, rev, remove, message, date, user
226 tag: force, local, rev, remove, message, date, user
227 tags:
227 tags:
228 tip: patch, git, style, template
228 tip: patch, git, style, template
229 unbundle: update
229 unbundle: update
230 verify:
230 verify:
231 version:
231 version:
@@ -1,180 +1,183 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init a
3 hg init a
4
4
5 cd a
5 cd a
6 echo a > a
6 echo a > a
7 hg ci -Ama -d '1 0'
7 hg ci -Ama -d '1 0'
8
8
9 hg cp a b
9 hg cp a b
10 hg ci -mb -d '2 0'
10 hg ci -mb -d '2 0'
11
11
12 mkdir dir
12 mkdir dir
13 hg mv b dir
13 hg mv b dir
14 hg ci -mc -d '3 0'
14 hg ci -mc -d '3 0'
15
15
16 hg mv a b
16 hg mv a b
17 echo a > d
17 echo a > d
18 hg add d
18 hg add d
19 hg ci -md -d '4 0'
19 hg ci -md -d '4 0'
20
20
21 hg mv dir/b e
21 hg mv dir/b e
22 hg ci -me -d '5 0'
22 hg ci -me -d '5 0'
23
23
24 hg log a
24 hg log a
25 echo % -f, directory
25 echo % -f, directory
26 hg log -f dir
26 hg log -f dir
27 echo % -f, but no args
27 echo % -f, but no args
28 hg log -f
28 hg log -f
29 echo % one rename
29 echo % one rename
30 hg log -vf a
30 hg log -vf a
31 echo % many renames
31 echo % many renames
32 hg log -vf e
32 hg log -vf e
33
33
34 echo '% log copies with --copies'
34 echo '% log copies with --copies'
35 hg log -vC --template '{rev} {file_copies}\n'
35 hg log -vC --template '{rev} {file_copies}\n'
36 echo '% log copies switch without --copies, with old filecopy template'
36 echo '% log copies switch without --copies, with old filecopy template'
37 hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
37 hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
38 echo '% log copies switch with --copies'
38 echo '% log copies switch with --copies'
39 hg log -vC --template '{rev} {file_copies_switch}\n'
39 hg log -vC --template '{rev} {file_copies_switch}\n'
40
40
41 echo '% log copies with hardcoded style and with --style=default'
41 echo '% log copies with hardcoded style and with --style=default'
42 hg log -vC -r4
42 hg log -vC -r4
43 hg log -vC -r4 --style=default
43 hg log -vC -r4 --style=default
44
44
45 echo % log copies, non-linear manifest
45 echo % log copies, non-linear manifest
46 hg up -C 3
46 hg up -C 3
47 hg mv dir/b e
47 hg mv dir/b e
48 echo foo > foo
48 echo foo > foo
49 hg ci -Ame2 -d '6 0'
49 hg ci -Ame2 -d '6 0'
50 hg log -v --template '{rev} {file_copies}\n' -r 5
50 hg log -v --template '{rev} {file_copies}\n' -r 5
51
51
52 echo % log copies, execute bit set
52 echo % log copies, execute bit set
53 chmod +x e
53 chmod +x e
54 hg ci -me3 -d '7 0'
54 hg ci -me3 -d '7 0'
55 hg log -v --template '{rev} {file_copies}\n' -r 6
55 hg log -v --template '{rev} {file_copies}\n' -r 6
56
56
57 echo '% log -p d'
57 echo '% log -p d'
58 hg log -pv d
58 hg log -pv d
59
59
60 # log --follow tests
60 # log --follow tests
61 hg init ../follow
61 hg init ../follow
62 cd ../follow
62 cd ../follow
63
63
64 echo base > base
64 echo base > base
65 hg ci -Ambase -d '1 0'
65 hg ci -Ambase -d '1 0'
66
66
67 echo r1 >> base
67 echo r1 >> base
68 hg ci -Amr1 -d '1 0'
68 hg ci -Amr1 -d '1 0'
69 echo r2 >> base
69 echo r2 >> base
70 hg ci -Amr2 -d '1 0'
70 hg ci -Amr2 -d '1 0'
71
71
72 hg up -C 1
72 hg up -C 1
73 echo b1 > b1
73 echo b1 > b1
74 hg ci -Amb1 -d '1 0'
74 hg ci -Amb1 -d '1 0'
75
75
76 echo % log -f
76 echo % log -f
77 hg log -f
77 hg log -f
78
78
79 hg up -C 0
79 hg up -C 0
80 echo b2 > b2
80 echo b2 > b2
81 hg ci -Amb2 -d '1 0'
81 hg ci -Amb2 -d '1 0'
82
82
83 echo % log -f -r 1:tip
83 echo % log -f -r 1:tip
84 hg log -f -r 1:tip
84 hg log -f -r 1:tip
85
85
86 hg up -C 3
86 hg up -C 3
87 hg merge tip
87 hg merge tip
88
88
89 echo % log -r . with two parents
89 echo % log -r . with two parents
90 hg log -r .
90 hg log -r .
91
91
92 hg ci -mm12 -d '1 0'
92 hg ci -mm12 -d '1 0'
93
93
94 echo % log -r . with one parent
94 echo % log -r . with one parent
95 hg log -r .
95 hg log -r .
96
96
97 echo postm >> b1
97 echo postm >> b1
98 hg ci -Amb1.1 -d'1 0'
98 hg ci -Amb1.1 -d'1 0'
99
99
100 echo % log --follow-first
100 echo % log --follow-first
101 hg log --follow-first
101 hg log --follow-first
102
102
103 echo % log -P 2
103 echo % log -P 2
104 hg log -P 2
104 hg log -P 2
105
105
106 echo '% log -r tip -p --git'
106 echo '% log -r tip -p --git'
107 hg log -r tip -p --git
107 hg log -r tip -p --git
108
108
109 echo '% log -r ""'
109 echo '% log -r ""'
110 hg log -r ''
110 hg log -r ''
111
111
112 echo '% log -r <some unknown node id>'
112 echo '% log -r <some unknown node id>'
113 hg log -r 1000000000000000000000000000000000000000
113 hg log -r 1000000000000000000000000000000000000000
114
114
115 echo '% log -k r1'
115 echo '% log -k r1'
116 hg log -k r1
116 hg log -k r1
117
117
118 echo '% log -d -1'
118 echo '% log -d -1'
119 hg log -d -1
119 hg log -d -1
120
120
121 echo '% log -p -l2 --color=always'
121 echo '% log -p -l2 --color=always'
122 hg --config extensions.color= log -p -l2 --color=always
122 hg --config extensions.color= log -p -l2 --color=always
123
123
124 echo '% log -r tip --stat'
125 hg log -r tip --stat
126
124 cd ..
127 cd ..
125
128
126 hg init usertest
129 hg init usertest
127 cd usertest
130 cd usertest
128
131
129 echo a > a
132 echo a > a
130 hg ci -A -m "a" -u "User One <user1@example.org>"
133 hg ci -A -m "a" -u "User One <user1@example.org>"
131 echo b > b
134 echo b > b
132 hg ci -A -m "b" -u "User Two <user2@example.org>"
135 hg ci -A -m "b" -u "User Two <user2@example.org>"
133
136
134 hg log -u "User One <user1@example.org>"
137 hg log -u "User One <user1@example.org>"
135 hg log -u "user1" -u "user2"
138 hg log -u "user1" -u "user2"
136 hg log -u "user3"
139 hg log -u "user3"
137
140
138 cd ..
141 cd ..
139
142
140 hg init branches
143 hg init branches
141 cd branches
144 cd branches
142
145
143 echo a > a
146 echo a > a
144 hg ci -A -m "commit on default"
147 hg ci -A -m "commit on default"
145 hg branch test
148 hg branch test
146 echo b > b
149 echo b > b
147 hg ci -A -m "commit on test"
150 hg ci -A -m "commit on test"
148
151
149 hg up default
152 hg up default
150 echo c > c
153 echo c > c
151 hg ci -A -m "commit on default"
154 hg ci -A -m "commit on default"
152 hg up test
155 hg up test
153 echo c > c
156 echo c > c
154 hg ci -A -m "commit on test"
157 hg ci -A -m "commit on test"
155
158
156 echo '% log -b default'
159 echo '% log -b default'
157 hg log -b default
160 hg log -b default
158
161
159 echo '% log -b test'
162 echo '% log -b test'
160 hg log -b test
163 hg log -b test
161
164
162 echo '% log -b dummy'
165 echo '% log -b dummy'
163 hg log -b dummy
166 hg log -b dummy
164
167
165 echo '% log -b .'
168 echo '% log -b .'
166 hg log -b .
169 hg log -b .
167
170
168 echo '% log -b default -b test'
171 echo '% log -b default -b test'
169 hg log -b default -b test
172 hg log -b default -b test
170
173
171 echo '% log -b default -b .'
174 echo '% log -b default -b .'
172 hg log -b default -b .
175 hg log -b default -b .
173
176
174 echo '% log -b . -b test'
177 echo '% log -b . -b test'
175 hg log -b . -b test
178 hg log -b . -b test
176
179
177 echo '% log -b 2'
180 echo '% log -b 2'
178 hg log -b 2
181 hg log -b 2
179
182
180 exit 0
183 exit 0
@@ -1,457 +1,467 b''
1 adding a
1 adding a
2 changeset: 0:8580ff50825a
2 changeset: 0:8580ff50825a
3 user: test
3 user: test
4 date: Thu Jan 01 00:00:01 1970 +0000
4 date: Thu Jan 01 00:00:01 1970 +0000
5 summary: a
5 summary: a
6
6
7 % -f, directory
7 % -f, directory
8 abort: cannot follow nonexistent file: "dir"
8 abort: cannot follow nonexistent file: "dir"
9 % -f, but no args
9 % -f, but no args
10 changeset: 4:66c1345dc4f9
10 changeset: 4:66c1345dc4f9
11 tag: tip
11 tag: tip
12 user: test
12 user: test
13 date: Thu Jan 01 00:00:05 1970 +0000
13 date: Thu Jan 01 00:00:05 1970 +0000
14 summary: e
14 summary: e
15
15
16 changeset: 3:7c6c671bb7cc
16 changeset: 3:7c6c671bb7cc
17 user: test
17 user: test
18 date: Thu Jan 01 00:00:04 1970 +0000
18 date: Thu Jan 01 00:00:04 1970 +0000
19 summary: d
19 summary: d
20
20
21 changeset: 2:41dd4284081e
21 changeset: 2:41dd4284081e
22 user: test
22 user: test
23 date: Thu Jan 01 00:00:03 1970 +0000
23 date: Thu Jan 01 00:00:03 1970 +0000
24 summary: c
24 summary: c
25
25
26 changeset: 1:784de7cef101
26 changeset: 1:784de7cef101
27 user: test
27 user: test
28 date: Thu Jan 01 00:00:02 1970 +0000
28 date: Thu Jan 01 00:00:02 1970 +0000
29 summary: b
29 summary: b
30
30
31 changeset: 0:8580ff50825a
31 changeset: 0:8580ff50825a
32 user: test
32 user: test
33 date: Thu Jan 01 00:00:01 1970 +0000
33 date: Thu Jan 01 00:00:01 1970 +0000
34 summary: a
34 summary: a
35
35
36 % one rename
36 % one rename
37 changeset: 0:8580ff50825a
37 changeset: 0:8580ff50825a
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:01 1970 +0000
39 date: Thu Jan 01 00:00:01 1970 +0000
40 files: a
40 files: a
41 description:
41 description:
42 a
42 a
43
43
44
44
45 % many renames
45 % many renames
46 changeset: 4:66c1345dc4f9
46 changeset: 4:66c1345dc4f9
47 tag: tip
47 tag: tip
48 user: test
48 user: test
49 date: Thu Jan 01 00:00:05 1970 +0000
49 date: Thu Jan 01 00:00:05 1970 +0000
50 files: dir/b e
50 files: dir/b e
51 description:
51 description:
52 e
52 e
53
53
54
54
55 changeset: 2:41dd4284081e
55 changeset: 2:41dd4284081e
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:03 1970 +0000
57 date: Thu Jan 01 00:00:03 1970 +0000
58 files: b dir/b
58 files: b dir/b
59 description:
59 description:
60 c
60 c
61
61
62
62
63 changeset: 1:784de7cef101
63 changeset: 1:784de7cef101
64 user: test
64 user: test
65 date: Thu Jan 01 00:00:02 1970 +0000
65 date: Thu Jan 01 00:00:02 1970 +0000
66 files: b
66 files: b
67 description:
67 description:
68 b
68 b
69
69
70
70
71 changeset: 0:8580ff50825a
71 changeset: 0:8580ff50825a
72 user: test
72 user: test
73 date: Thu Jan 01 00:00:01 1970 +0000
73 date: Thu Jan 01 00:00:01 1970 +0000
74 files: a
74 files: a
75 description:
75 description:
76 a
76 a
77
77
78
78
79 % log copies with --copies
79 % log copies with --copies
80 4 e (dir/b)
80 4 e (dir/b)
81 3 b (a)
81 3 b (a)
82 2 dir/b (b)
82 2 dir/b (b)
83 1 b (a)
83 1 b (a)
84 0
84 0
85 % log copies switch without --copies, with old filecopy template
85 % log copies switch without --copies, with old filecopy template
86 4
86 4
87 3
87 3
88 2
88 2
89 1
89 1
90 0
90 0
91 % log copies switch with --copies
91 % log copies switch with --copies
92 4 e (dir/b)
92 4 e (dir/b)
93 3 b (a)
93 3 b (a)
94 2 dir/b (b)
94 2 dir/b (b)
95 1 b (a)
95 1 b (a)
96 0
96 0
97 % log copies with hardcoded style and with --style=default
97 % log copies with hardcoded style and with --style=default
98 changeset: 4:66c1345dc4f9
98 changeset: 4:66c1345dc4f9
99 tag: tip
99 tag: tip
100 user: test
100 user: test
101 date: Thu Jan 01 00:00:05 1970 +0000
101 date: Thu Jan 01 00:00:05 1970 +0000
102 files: dir/b e
102 files: dir/b e
103 copies: e (dir/b)
103 copies: e (dir/b)
104 description:
104 description:
105 e
105 e
106
106
107
107
108 changeset: 4:66c1345dc4f9
108 changeset: 4:66c1345dc4f9
109 tag: tip
109 tag: tip
110 user: test
110 user: test
111 date: Thu Jan 01 00:00:05 1970 +0000
111 date: Thu Jan 01 00:00:05 1970 +0000
112 files: dir/b e
112 files: dir/b e
113 copies: e (dir/b)
113 copies: e (dir/b)
114 description:
114 description:
115 e
115 e
116
116
117
117
118 % log copies, non-linear manifest
118 % log copies, non-linear manifest
119 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
119 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 adding foo
120 adding foo
121 created new head
121 created new head
122 5 e (dir/b)
122 5 e (dir/b)
123 % log copies, execute bit set
123 % log copies, execute bit set
124 6
124 6
125 % log -p d
125 % log -p d
126 changeset: 3:7c6c671bb7cc
126 changeset: 3:7c6c671bb7cc
127 user: test
127 user: test
128 date: Thu Jan 01 00:00:04 1970 +0000
128 date: Thu Jan 01 00:00:04 1970 +0000
129 files: a b d
129 files: a b d
130 description:
130 description:
131 d
131 d
132
132
133
133
134 diff -r 41dd4284081e -r 7c6c671bb7cc d
134 diff -r 41dd4284081e -r 7c6c671bb7cc d
135 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
135 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
136 +++ b/d Thu Jan 01 00:00:04 1970 +0000
136 +++ b/d Thu Jan 01 00:00:04 1970 +0000
137 @@ -0,0 +1,1 @@
137 @@ -0,0 +1,1 @@
138 +a
138 +a
139
139
140 adding base
140 adding base
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 adding b1
142 adding b1
143 created new head
143 created new head
144 % log -f
144 % log -f
145 changeset: 3:e62f78d544b4
145 changeset: 3:e62f78d544b4
146 tag: tip
146 tag: tip
147 parent: 1:3d5bf5654eda
147 parent: 1:3d5bf5654eda
148 user: test
148 user: test
149 date: Thu Jan 01 00:00:01 1970 +0000
149 date: Thu Jan 01 00:00:01 1970 +0000
150 summary: b1
150 summary: b1
151
151
152 changeset: 1:3d5bf5654eda
152 changeset: 1:3d5bf5654eda
153 user: test
153 user: test
154 date: Thu Jan 01 00:00:01 1970 +0000
154 date: Thu Jan 01 00:00:01 1970 +0000
155 summary: r1
155 summary: r1
156
156
157 changeset: 0:67e992f2c4f3
157 changeset: 0:67e992f2c4f3
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:01 1970 +0000
159 date: Thu Jan 01 00:00:01 1970 +0000
160 summary: base
160 summary: base
161
161
162 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
162 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
163 adding b2
163 adding b2
164 created new head
164 created new head
165 % log -f -r 1:tip
165 % log -f -r 1:tip
166 changeset: 1:3d5bf5654eda
166 changeset: 1:3d5bf5654eda
167 user: test
167 user: test
168 date: Thu Jan 01 00:00:01 1970 +0000
168 date: Thu Jan 01 00:00:01 1970 +0000
169 summary: r1
169 summary: r1
170
170
171 changeset: 2:60c670bf5b30
171 changeset: 2:60c670bf5b30
172 user: test
172 user: test
173 date: Thu Jan 01 00:00:01 1970 +0000
173 date: Thu Jan 01 00:00:01 1970 +0000
174 summary: r2
174 summary: r2
175
175
176 changeset: 3:e62f78d544b4
176 changeset: 3:e62f78d544b4
177 parent: 1:3d5bf5654eda
177 parent: 1:3d5bf5654eda
178 user: test
178 user: test
179 date: Thu Jan 01 00:00:01 1970 +0000
179 date: Thu Jan 01 00:00:01 1970 +0000
180 summary: b1
180 summary: b1
181
181
182 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
182 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 (branch merge, don't forget to commit)
184 (branch merge, don't forget to commit)
185 % log -r . with two parents
185 % log -r . with two parents
186 changeset: 3:e62f78d544b4
186 changeset: 3:e62f78d544b4
187 parent: 1:3d5bf5654eda
187 parent: 1:3d5bf5654eda
188 user: test
188 user: test
189 date: Thu Jan 01 00:00:01 1970 +0000
189 date: Thu Jan 01 00:00:01 1970 +0000
190 summary: b1
190 summary: b1
191
191
192 % log -r . with one parent
192 % log -r . with one parent
193 changeset: 5:302e9dd6890d
193 changeset: 5:302e9dd6890d
194 tag: tip
194 tag: tip
195 parent: 3:e62f78d544b4
195 parent: 3:e62f78d544b4
196 parent: 4:ddb82e70d1a1
196 parent: 4:ddb82e70d1a1
197 user: test
197 user: test
198 date: Thu Jan 01 00:00:01 1970 +0000
198 date: Thu Jan 01 00:00:01 1970 +0000
199 summary: m12
199 summary: m12
200
200
201 % log --follow-first
201 % log --follow-first
202 changeset: 6:2404bbcab562
202 changeset: 6:2404bbcab562
203 tag: tip
203 tag: tip
204 user: test
204 user: test
205 date: Thu Jan 01 00:00:01 1970 +0000
205 date: Thu Jan 01 00:00:01 1970 +0000
206 summary: b1.1
206 summary: b1.1
207
207
208 changeset: 5:302e9dd6890d
208 changeset: 5:302e9dd6890d
209 parent: 3:e62f78d544b4
209 parent: 3:e62f78d544b4
210 parent: 4:ddb82e70d1a1
210 parent: 4:ddb82e70d1a1
211 user: test
211 user: test
212 date: Thu Jan 01 00:00:01 1970 +0000
212 date: Thu Jan 01 00:00:01 1970 +0000
213 summary: m12
213 summary: m12
214
214
215 changeset: 3:e62f78d544b4
215 changeset: 3:e62f78d544b4
216 parent: 1:3d5bf5654eda
216 parent: 1:3d5bf5654eda
217 user: test
217 user: test
218 date: Thu Jan 01 00:00:01 1970 +0000
218 date: Thu Jan 01 00:00:01 1970 +0000
219 summary: b1
219 summary: b1
220
220
221 changeset: 1:3d5bf5654eda
221 changeset: 1:3d5bf5654eda
222 user: test
222 user: test
223 date: Thu Jan 01 00:00:01 1970 +0000
223 date: Thu Jan 01 00:00:01 1970 +0000
224 summary: r1
224 summary: r1
225
225
226 changeset: 0:67e992f2c4f3
226 changeset: 0:67e992f2c4f3
227 user: test
227 user: test
228 date: Thu Jan 01 00:00:01 1970 +0000
228 date: Thu Jan 01 00:00:01 1970 +0000
229 summary: base
229 summary: base
230
230
231 % log -P 2
231 % log -P 2
232 changeset: 6:2404bbcab562
232 changeset: 6:2404bbcab562
233 tag: tip
233 tag: tip
234 user: test
234 user: test
235 date: Thu Jan 01 00:00:01 1970 +0000
235 date: Thu Jan 01 00:00:01 1970 +0000
236 summary: b1.1
236 summary: b1.1
237
237
238 changeset: 5:302e9dd6890d
238 changeset: 5:302e9dd6890d
239 parent: 3:e62f78d544b4
239 parent: 3:e62f78d544b4
240 parent: 4:ddb82e70d1a1
240 parent: 4:ddb82e70d1a1
241 user: test
241 user: test
242 date: Thu Jan 01 00:00:01 1970 +0000
242 date: Thu Jan 01 00:00:01 1970 +0000
243 summary: m12
243 summary: m12
244
244
245 changeset: 4:ddb82e70d1a1
245 changeset: 4:ddb82e70d1a1
246 parent: 0:67e992f2c4f3
246 parent: 0:67e992f2c4f3
247 user: test
247 user: test
248 date: Thu Jan 01 00:00:01 1970 +0000
248 date: Thu Jan 01 00:00:01 1970 +0000
249 summary: b2
249 summary: b2
250
250
251 changeset: 3:e62f78d544b4
251 changeset: 3:e62f78d544b4
252 parent: 1:3d5bf5654eda
252 parent: 1:3d5bf5654eda
253 user: test
253 user: test
254 date: Thu Jan 01 00:00:01 1970 +0000
254 date: Thu Jan 01 00:00:01 1970 +0000
255 summary: b1
255 summary: b1
256
256
257 % log -r tip -p --git
257 % log -r tip -p --git
258 changeset: 6:2404bbcab562
258 changeset: 6:2404bbcab562
259 tag: tip
259 tag: tip
260 user: test
260 user: test
261 date: Thu Jan 01 00:00:01 1970 +0000
261 date: Thu Jan 01 00:00:01 1970 +0000
262 summary: b1.1
262 summary: b1.1
263
263
264 diff --git a/b1 b/b1
264 diff --git a/b1 b/b1
265 --- a/b1
265 --- a/b1
266 +++ b/b1
266 +++ b/b1
267 @@ -1,1 +1,2 @@
267 @@ -1,1 +1,2 @@
268 b1
268 b1
269 +postm
269 +postm
270
270
271 % log -r ""
271 % log -r ""
272 abort: 00changelog.i@: ambiguous identifier!
272 abort: 00changelog.i@: ambiguous identifier!
273 % log -r <some unknown node id>
273 % log -r <some unknown node id>
274 abort: unknown revision '1000000000000000000000000000000000000000'!
274 abort: unknown revision '1000000000000000000000000000000000000000'!
275 % log -k r1
275 % log -k r1
276 changeset: 1:3d5bf5654eda
276 changeset: 1:3d5bf5654eda
277 user: test
277 user: test
278 date: Thu Jan 01 00:00:01 1970 +0000
278 date: Thu Jan 01 00:00:01 1970 +0000
279 summary: r1
279 summary: r1
280
280
281 % log -d -1
281 % log -d -1
282 % log -p -l2 --color=always
282 % log -p -l2 --color=always
283 changeset: 6:2404bbcab562
283 changeset: 6:2404bbcab562
284 tag: tip
284 tag: tip
285 user: test
285 user: test
286 date: Thu Jan 01 00:00:01 1970 +0000
286 date: Thu Jan 01 00:00:01 1970 +0000
287 summary: b1.1
287 summary: b1.1
288
288
289 diff -r 302e9dd6890d -r 2404bbcab562 b1
289 diff -r 302e9dd6890d -r 2404bbcab562 b1
290 --- a/b1 Thu Jan 01 00:00:01 1970 +0000
290 --- a/b1 Thu Jan 01 00:00:01 1970 +0000
291 +++ b/b1 Thu Jan 01 00:00:01 1970 +0000
291 +++ b/b1 Thu Jan 01 00:00:01 1970 +0000
292 @@ -1,1 +1,2 @@
292 @@ -1,1 +1,2 @@
293 b1
293 b1
294 +postm
294 +postm
295
295
296 changeset: 5:302e9dd6890d
296 changeset: 5:302e9dd6890d
297 parent: 3:e62f78d544b4
297 parent: 3:e62f78d544b4
298 parent: 4:ddb82e70d1a1
298 parent: 4:ddb82e70d1a1
299 user: test
299 user: test
300 date: Thu Jan 01 00:00:01 1970 +0000
300 date: Thu Jan 01 00:00:01 1970 +0000
301 summary: m12
301 summary: m12
302
302
303 diff -r e62f78d544b4 -r 302e9dd6890d b2
303 diff -r e62f78d544b4 -r 302e9dd6890d b2
304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
305 +++ b/b2 Thu Jan 01 00:00:01 1970 +0000
305 +++ b/b2 Thu Jan 01 00:00:01 1970 +0000
306 @@ -0,0 +1,1 @@
306 @@ -0,0 +1,1 @@
307 +b2
307 +b2
308
308
309 % log -r tip --stat
310 changeset: 6:2404bbcab562
311 tag: tip
312 user: test
313 date: Thu Jan 01 00:00:01 1970 +0000
314 summary: b1.1
315
316 b1 | 1 +
317 1 files changed, 1 insertions(+), 0 deletions(-)
318
309 adding a
319 adding a
310 adding b
320 adding b
311 changeset: 0:29a4c94f1924
321 changeset: 0:29a4c94f1924
312 user: User One <user1@example.org>
322 user: User One <user1@example.org>
313 date: Thu Jan 01 00:00:00 1970 +0000
323 date: Thu Jan 01 00:00:00 1970 +0000
314 summary: a
324 summary: a
315
325
316 changeset: 1:e834b5e69c0e
326 changeset: 1:e834b5e69c0e
317 tag: tip
327 tag: tip
318 user: User Two <user2@example.org>
328 user: User Two <user2@example.org>
319 date: Thu Jan 01 00:00:00 1970 +0000
329 date: Thu Jan 01 00:00:00 1970 +0000
320 summary: b
330 summary: b
321
331
322 changeset: 0:29a4c94f1924
332 changeset: 0:29a4c94f1924
323 user: User One <user1@example.org>
333 user: User One <user1@example.org>
324 date: Thu Jan 01 00:00:00 1970 +0000
334 date: Thu Jan 01 00:00:00 1970 +0000
325 summary: a
335 summary: a
326
336
327 adding a
337 adding a
328 marked working directory as branch test
338 marked working directory as branch test
329 adding b
339 adding b
330 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
340 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
331 adding c
341 adding c
332 created new head
342 created new head
333 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
343 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
334 adding c
344 adding c
335 % log -b default
345 % log -b default
336 changeset: 2:c3a4f03cc9a7
346 changeset: 2:c3a4f03cc9a7
337 parent: 0:24427303d56f
347 parent: 0:24427303d56f
338 user: test
348 user: test
339 date: Thu Jan 01 00:00:00 1970 +0000
349 date: Thu Jan 01 00:00:00 1970 +0000
340 summary: commit on default
350 summary: commit on default
341
351
342 changeset: 0:24427303d56f
352 changeset: 0:24427303d56f
343 user: test
353 user: test
344 date: Thu Jan 01 00:00:00 1970 +0000
354 date: Thu Jan 01 00:00:00 1970 +0000
345 summary: commit on default
355 summary: commit on default
346
356
347 % log -b test
357 % log -b test
348 changeset: 3:f5d8de11c2e2
358 changeset: 3:f5d8de11c2e2
349 branch: test
359 branch: test
350 tag: tip
360 tag: tip
351 parent: 1:d32277701ccb
361 parent: 1:d32277701ccb
352 user: test
362 user: test
353 date: Thu Jan 01 00:00:00 1970 +0000
363 date: Thu Jan 01 00:00:00 1970 +0000
354 summary: commit on test
364 summary: commit on test
355
365
356 changeset: 1:d32277701ccb
366 changeset: 1:d32277701ccb
357 branch: test
367 branch: test
358 user: test
368 user: test
359 date: Thu Jan 01 00:00:00 1970 +0000
369 date: Thu Jan 01 00:00:00 1970 +0000
360 summary: commit on test
370 summary: commit on test
361
371
362 % log -b dummy
372 % log -b dummy
363 abort: unknown revision 'dummy'!
373 abort: unknown revision 'dummy'!
364 % log -b .
374 % log -b .
365 changeset: 3:f5d8de11c2e2
375 changeset: 3:f5d8de11c2e2
366 branch: test
376 branch: test
367 tag: tip
377 tag: tip
368 parent: 1:d32277701ccb
378 parent: 1:d32277701ccb
369 user: test
379 user: test
370 date: Thu Jan 01 00:00:00 1970 +0000
380 date: Thu Jan 01 00:00:00 1970 +0000
371 summary: commit on test
381 summary: commit on test
372
382
373 changeset: 1:d32277701ccb
383 changeset: 1:d32277701ccb
374 branch: test
384 branch: test
375 user: test
385 user: test
376 date: Thu Jan 01 00:00:00 1970 +0000
386 date: Thu Jan 01 00:00:00 1970 +0000
377 summary: commit on test
387 summary: commit on test
378
388
379 % log -b default -b test
389 % log -b default -b test
380 changeset: 3:f5d8de11c2e2
390 changeset: 3:f5d8de11c2e2
381 branch: test
391 branch: test
382 tag: tip
392 tag: tip
383 parent: 1:d32277701ccb
393 parent: 1:d32277701ccb
384 user: test
394 user: test
385 date: Thu Jan 01 00:00:00 1970 +0000
395 date: Thu Jan 01 00:00:00 1970 +0000
386 summary: commit on test
396 summary: commit on test
387
397
388 changeset: 2:c3a4f03cc9a7
398 changeset: 2:c3a4f03cc9a7
389 parent: 0:24427303d56f
399 parent: 0:24427303d56f
390 user: test
400 user: test
391 date: Thu Jan 01 00:00:00 1970 +0000
401 date: Thu Jan 01 00:00:00 1970 +0000
392 summary: commit on default
402 summary: commit on default
393
403
394 changeset: 1:d32277701ccb
404 changeset: 1:d32277701ccb
395 branch: test
405 branch: test
396 user: test
406 user: test
397 date: Thu Jan 01 00:00:00 1970 +0000
407 date: Thu Jan 01 00:00:00 1970 +0000
398 summary: commit on test
408 summary: commit on test
399
409
400 changeset: 0:24427303d56f
410 changeset: 0:24427303d56f
401 user: test
411 user: test
402 date: Thu Jan 01 00:00:00 1970 +0000
412 date: Thu Jan 01 00:00:00 1970 +0000
403 summary: commit on default
413 summary: commit on default
404
414
405 % log -b default -b .
415 % log -b default -b .
406 changeset: 3:f5d8de11c2e2
416 changeset: 3:f5d8de11c2e2
407 branch: test
417 branch: test
408 tag: tip
418 tag: tip
409 parent: 1:d32277701ccb
419 parent: 1:d32277701ccb
410 user: test
420 user: test
411 date: Thu Jan 01 00:00:00 1970 +0000
421 date: Thu Jan 01 00:00:00 1970 +0000
412 summary: commit on test
422 summary: commit on test
413
423
414 changeset: 2:c3a4f03cc9a7
424 changeset: 2:c3a4f03cc9a7
415 parent: 0:24427303d56f
425 parent: 0:24427303d56f
416 user: test
426 user: test
417 date: Thu Jan 01 00:00:00 1970 +0000
427 date: Thu Jan 01 00:00:00 1970 +0000
418 summary: commit on default
428 summary: commit on default
419
429
420 changeset: 1:d32277701ccb
430 changeset: 1:d32277701ccb
421 branch: test
431 branch: test
422 user: test
432 user: test
423 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
424 summary: commit on test
434 summary: commit on test
425
435
426 changeset: 0:24427303d56f
436 changeset: 0:24427303d56f
427 user: test
437 user: test
428 date: Thu Jan 01 00:00:00 1970 +0000
438 date: Thu Jan 01 00:00:00 1970 +0000
429 summary: commit on default
439 summary: commit on default
430
440
431 % log -b . -b test
441 % log -b . -b test
432 changeset: 3:f5d8de11c2e2
442 changeset: 3:f5d8de11c2e2
433 branch: test
443 branch: test
434 tag: tip
444 tag: tip
435 parent: 1:d32277701ccb
445 parent: 1:d32277701ccb
436 user: test
446 user: test
437 date: Thu Jan 01 00:00:00 1970 +0000
447 date: Thu Jan 01 00:00:00 1970 +0000
438 summary: commit on test
448 summary: commit on test
439
449
440 changeset: 1:d32277701ccb
450 changeset: 1:d32277701ccb
441 branch: test
451 branch: test
442 user: test
452 user: test
443 date: Thu Jan 01 00:00:00 1970 +0000
453 date: Thu Jan 01 00:00:00 1970 +0000
444 summary: commit on test
454 summary: commit on test
445
455
446 % log -b 2
456 % log -b 2
447 changeset: 2:c3a4f03cc9a7
457 changeset: 2:c3a4f03cc9a7
448 parent: 0:24427303d56f
458 parent: 0:24427303d56f
449 user: test
459 user: test
450 date: Thu Jan 01 00:00:00 1970 +0000
460 date: Thu Jan 01 00:00:00 1970 +0000
451 summary: commit on default
461 summary: commit on default
452
462
453 changeset: 0:24427303d56f
463 changeset: 0:24427303d56f
454 user: test
464 user: test
455 date: Thu Jan 01 00:00:00 1970 +0000
465 date: Thu Jan 01 00:00:00 1970 +0000
456 summary: commit on default
466 summary: commit on default
457
467
General Comments 0
You need to be logged in to leave comments. Login now