##// END OF EJS Templates
add: move main part to cmdutil to make it easier to reuse
Martin Geisler -
r12269:877236cd default
parent child Browse files
Show More
@@ -1,1336 +1,1352 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 util, templater, patch, error, encoding, templatekw
11 import util, templater, patch, error, encoding, templatekw
12 import match as matchmod
12 import match as matchmod
13 import similar, revset, subrepo
13 import similar, revset, subrepo
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 revpair(repo, revs):
114 def revpair(repo, revs):
115 '''return pair of nodes, given list of revisions. second item can
115 '''return pair of nodes, given list of revisions. second item can
116 be None, meaning use working dir.'''
116 be None, meaning use working dir.'''
117
117
118 def revfix(repo, val, defval):
118 def revfix(repo, val, defval):
119 if not val and val != 0 and defval is not None:
119 if not val and val != 0 and defval is not None:
120 val = defval
120 val = defval
121 return repo.lookup(val)
121 return repo.lookup(val)
122
122
123 if not revs:
123 if not revs:
124 return repo.dirstate.parents()[0], None
124 return repo.dirstate.parents()[0], None
125 end = None
125 end = None
126 if len(revs) == 1:
126 if len(revs) == 1:
127 if revrangesep in revs[0]:
127 if revrangesep in revs[0]:
128 start, end = revs[0].split(revrangesep, 1)
128 start, end = revs[0].split(revrangesep, 1)
129 start = revfix(repo, start, 0)
129 start = revfix(repo, start, 0)
130 end = revfix(repo, end, len(repo) - 1)
130 end = revfix(repo, end, len(repo) - 1)
131 else:
131 else:
132 start = revfix(repo, revs[0], None)
132 start = revfix(repo, revs[0], None)
133 elif len(revs) == 2:
133 elif len(revs) == 2:
134 if revrangesep in revs[0] or revrangesep in revs[1]:
134 if revrangesep in revs[0] or revrangesep in revs[1]:
135 raise util.Abort(_('too many revisions specified'))
135 raise util.Abort(_('too many revisions specified'))
136 start = revfix(repo, revs[0], None)
136 start = revfix(repo, revs[0], None)
137 end = revfix(repo, revs[1], None)
137 end = revfix(repo, revs[1], None)
138 else:
138 else:
139 raise util.Abort(_('too many revisions specified'))
139 raise util.Abort(_('too many revisions specified'))
140 return start, end
140 return start, end
141
141
142 def revrange(repo, revs):
142 def revrange(repo, revs):
143 """Yield revision as strings from a list of revision specifications."""
143 """Yield revision as strings from a list of revision specifications."""
144
144
145 def revfix(repo, val, defval):
145 def revfix(repo, val, defval):
146 if not val and val != 0 and defval is not None:
146 if not val and val != 0 and defval is not None:
147 return defval
147 return defval
148 return repo.changelog.rev(repo.lookup(val))
148 return repo.changelog.rev(repo.lookup(val))
149
149
150 seen, l = set(), []
150 seen, l = set(), []
151 for spec in revs:
151 for spec in revs:
152 # attempt to parse old-style ranges first to deal with
152 # attempt to parse old-style ranges first to deal with
153 # things like old-tag which contain query metacharacters
153 # things like old-tag which contain query metacharacters
154 try:
154 try:
155 if revrangesep in spec:
155 if revrangesep in spec:
156 start, end = spec.split(revrangesep, 1)
156 start, end = spec.split(revrangesep, 1)
157 start = revfix(repo, start, 0)
157 start = revfix(repo, start, 0)
158 end = revfix(repo, end, len(repo) - 1)
158 end = revfix(repo, end, len(repo) - 1)
159 step = start > end and -1 or 1
159 step = start > end and -1 or 1
160 for rev in xrange(start, end + step, step):
160 for rev in xrange(start, end + step, step):
161 if rev in seen:
161 if rev in seen:
162 continue
162 continue
163 seen.add(rev)
163 seen.add(rev)
164 l.append(rev)
164 l.append(rev)
165 continue
165 continue
166 elif spec and spec in repo: # single unquoted rev
166 elif spec and spec in repo: # single unquoted rev
167 rev = revfix(repo, spec, None)
167 rev = revfix(repo, spec, None)
168 if rev in seen:
168 if rev in seen:
169 continue
169 continue
170 seen.add(rev)
170 seen.add(rev)
171 l.append(rev)
171 l.append(rev)
172 continue
172 continue
173 except error.RepoLookupError:
173 except error.RepoLookupError:
174 pass
174 pass
175
175
176 # fall through to new-style queries if old-style fails
176 # fall through to new-style queries if old-style fails
177 m = revset.match(spec)
177 m = revset.match(spec)
178 for r in m(repo, range(len(repo))):
178 for r in m(repo, range(len(repo))):
179 if r not in seen:
179 if r not in seen:
180 l.append(r)
180 l.append(r)
181 seen.update(l)
181 seen.update(l)
182
182
183 return l
183 return l
184
184
185 def make_filename(repo, pat, node,
185 def make_filename(repo, pat, node,
186 total=None, seqno=None, revwidth=None, pathname=None):
186 total=None, seqno=None, revwidth=None, pathname=None):
187 node_expander = {
187 node_expander = {
188 'H': lambda: hex(node),
188 'H': lambda: hex(node),
189 'R': lambda: str(repo.changelog.rev(node)),
189 'R': lambda: str(repo.changelog.rev(node)),
190 'h': lambda: short(node),
190 'h': lambda: short(node),
191 }
191 }
192 expander = {
192 expander = {
193 '%': lambda: '%',
193 '%': lambda: '%',
194 'b': lambda: os.path.basename(repo.root),
194 'b': lambda: os.path.basename(repo.root),
195 }
195 }
196
196
197 try:
197 try:
198 if node:
198 if node:
199 expander.update(node_expander)
199 expander.update(node_expander)
200 if node:
200 if node:
201 expander['r'] = (lambda:
201 expander['r'] = (lambda:
202 str(repo.changelog.rev(node)).zfill(revwidth or 0))
202 str(repo.changelog.rev(node)).zfill(revwidth or 0))
203 if total is not None:
203 if total is not None:
204 expander['N'] = lambda: str(total)
204 expander['N'] = lambda: str(total)
205 if seqno is not None:
205 if seqno is not None:
206 expander['n'] = lambda: str(seqno)
206 expander['n'] = lambda: str(seqno)
207 if total is not None and seqno is not None:
207 if total is not None and seqno is not None:
208 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
208 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
209 if pathname is not None:
209 if pathname is not None:
210 expander['s'] = lambda: os.path.basename(pathname)
210 expander['s'] = lambda: os.path.basename(pathname)
211 expander['d'] = lambda: os.path.dirname(pathname) or '.'
211 expander['d'] = lambda: os.path.dirname(pathname) or '.'
212 expander['p'] = lambda: pathname
212 expander['p'] = lambda: pathname
213
213
214 newname = []
214 newname = []
215 patlen = len(pat)
215 patlen = len(pat)
216 i = 0
216 i = 0
217 while i < patlen:
217 while i < patlen:
218 c = pat[i]
218 c = pat[i]
219 if c == '%':
219 if c == '%':
220 i += 1
220 i += 1
221 c = pat[i]
221 c = pat[i]
222 c = expander[c]()
222 c = expander[c]()
223 newname.append(c)
223 newname.append(c)
224 i += 1
224 i += 1
225 return ''.join(newname)
225 return ''.join(newname)
226 except KeyError, inst:
226 except KeyError, inst:
227 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
227 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
228 inst.args[0])
228 inst.args[0])
229
229
230 def make_file(repo, pat, node=None,
230 def make_file(repo, pat, node=None,
231 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
231 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
232
232
233 writable = 'w' in mode or 'a' in mode
233 writable = 'w' in mode or 'a' in mode
234
234
235 if not pat or pat == '-':
235 if not pat or pat == '-':
236 return writable and sys.stdout or sys.stdin
236 return writable and sys.stdout or sys.stdin
237 if hasattr(pat, 'write') and writable:
237 if hasattr(pat, 'write') and writable:
238 return pat
238 return pat
239 if hasattr(pat, 'read') and 'r' in mode:
239 if hasattr(pat, 'read') and 'r' in mode:
240 return pat
240 return pat
241 return open(make_filename(repo, pat, node, total, seqno, revwidth,
241 return open(make_filename(repo, pat, node, total, seqno, revwidth,
242 pathname),
242 pathname),
243 mode)
243 mode)
244
244
245 def expandpats(pats):
245 def expandpats(pats):
246 if not util.expandglobs:
246 if not util.expandglobs:
247 return list(pats)
247 return list(pats)
248 ret = []
248 ret = []
249 for p in pats:
249 for p in pats:
250 kind, name = matchmod._patsplit(p, None)
250 kind, name = matchmod._patsplit(p, None)
251 if kind is None:
251 if kind is None:
252 try:
252 try:
253 globbed = glob.glob(name)
253 globbed = glob.glob(name)
254 except re.error:
254 except re.error:
255 globbed = [name]
255 globbed = [name]
256 if globbed:
256 if globbed:
257 ret.extend(globbed)
257 ret.extend(globbed)
258 continue
258 continue
259 ret.append(p)
259 ret.append(p)
260 return ret
260 return ret
261
261
262 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
262 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
263 if not globbed and default == 'relpath':
263 if not globbed and default == 'relpath':
264 pats = expandpats(pats or [])
264 pats = expandpats(pats or [])
265 m = matchmod.match(repo.root, repo.getcwd(), pats,
265 m = matchmod.match(repo.root, repo.getcwd(), pats,
266 opts.get('include'), opts.get('exclude'), default,
266 opts.get('include'), opts.get('exclude'), default,
267 auditor=repo.auditor)
267 auditor=repo.auditor)
268 def badfn(f, msg):
268 def badfn(f, msg):
269 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
269 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
270 m.bad = badfn
270 m.bad = badfn
271 return m
271 return m
272
272
273 def matchall(repo):
273 def matchall(repo):
274 return matchmod.always(repo.root, repo.getcwd())
274 return matchmod.always(repo.root, repo.getcwd())
275
275
276 def matchfiles(repo, files):
276 def matchfiles(repo, files):
277 return matchmod.exact(repo.root, repo.getcwd(), files)
277 return matchmod.exact(repo.root, repo.getcwd(), files)
278
278
279 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
279 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
280 if dry_run is None:
280 if dry_run is None:
281 dry_run = opts.get('dry_run')
281 dry_run = opts.get('dry_run')
282 if similarity is None:
282 if similarity is None:
283 similarity = float(opts.get('similarity') or 0)
283 similarity = float(opts.get('similarity') or 0)
284 # we'd use status here, except handling of symlinks and ignore is tricky
284 # we'd use status here, except handling of symlinks and ignore is tricky
285 added, unknown, deleted, removed = [], [], [], []
285 added, unknown, deleted, removed = [], [], [], []
286 audit_path = util.path_auditor(repo.root)
286 audit_path = util.path_auditor(repo.root)
287 m = match(repo, pats, opts)
287 m = match(repo, pats, opts)
288 for abs in repo.walk(m):
288 for abs in repo.walk(m):
289 target = repo.wjoin(abs)
289 target = repo.wjoin(abs)
290 good = True
290 good = True
291 try:
291 try:
292 audit_path(abs)
292 audit_path(abs)
293 except:
293 except:
294 good = False
294 good = False
295 rel = m.rel(abs)
295 rel = m.rel(abs)
296 exact = m.exact(abs)
296 exact = m.exact(abs)
297 if good and abs not in repo.dirstate:
297 if good and abs not in repo.dirstate:
298 unknown.append(abs)
298 unknown.append(abs)
299 if repo.ui.verbose or not exact:
299 if repo.ui.verbose or not exact:
300 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
300 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
301 elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
301 elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
302 or (os.path.isdir(target) and not os.path.islink(target))):
302 or (os.path.isdir(target) and not os.path.islink(target))):
303 deleted.append(abs)
303 deleted.append(abs)
304 if repo.ui.verbose or not exact:
304 if repo.ui.verbose or not exact:
305 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
305 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
306 # for finding renames
306 # for finding renames
307 elif repo.dirstate[abs] == 'r':
307 elif repo.dirstate[abs] == 'r':
308 removed.append(abs)
308 removed.append(abs)
309 elif repo.dirstate[abs] == 'a':
309 elif repo.dirstate[abs] == 'a':
310 added.append(abs)
310 added.append(abs)
311 copies = {}
311 copies = {}
312 if similarity > 0:
312 if similarity > 0:
313 for old, new, score in similar.findrenames(repo,
313 for old, new, score in similar.findrenames(repo,
314 added + unknown, removed + deleted, similarity):
314 added + unknown, removed + deleted, similarity):
315 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
315 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
316 repo.ui.status(_('recording removal of %s as rename to %s '
316 repo.ui.status(_('recording removal of %s as rename to %s '
317 '(%d%% similar)\n') %
317 '(%d%% similar)\n') %
318 (m.rel(old), m.rel(new), score * 100))
318 (m.rel(old), m.rel(new), score * 100))
319 copies[new] = old
319 copies[new] = old
320
320
321 if not dry_run:
321 if not dry_run:
322 wctx = repo[None]
322 wctx = repo[None]
323 wlock = repo.wlock()
323 wlock = repo.wlock()
324 try:
324 try:
325 wctx.remove(deleted)
325 wctx.remove(deleted)
326 wctx.add(unknown)
326 wctx.add(unknown)
327 for new, old in copies.iteritems():
327 for new, old in copies.iteritems():
328 wctx.copy(old, new)
328 wctx.copy(old, new)
329 finally:
329 finally:
330 wlock.release()
330 wlock.release()
331
331
332 def updatedir(ui, repo, patches, similarity=0):
332 def updatedir(ui, repo, patches, similarity=0):
333 '''Update dirstate after patch application according to metadata'''
333 '''Update dirstate after patch application according to metadata'''
334 if not patches:
334 if not patches:
335 return
335 return
336 copies = []
336 copies = []
337 removes = set()
337 removes = set()
338 cfiles = patches.keys()
338 cfiles = patches.keys()
339 cwd = repo.getcwd()
339 cwd = repo.getcwd()
340 if cwd:
340 if cwd:
341 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
341 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
342 for f in patches:
342 for f in patches:
343 gp = patches[f]
343 gp = patches[f]
344 if not gp:
344 if not gp:
345 continue
345 continue
346 if gp.op == 'RENAME':
346 if gp.op == 'RENAME':
347 copies.append((gp.oldpath, gp.path))
347 copies.append((gp.oldpath, gp.path))
348 removes.add(gp.oldpath)
348 removes.add(gp.oldpath)
349 elif gp.op == 'COPY':
349 elif gp.op == 'COPY':
350 copies.append((gp.oldpath, gp.path))
350 copies.append((gp.oldpath, gp.path))
351 elif gp.op == 'DELETE':
351 elif gp.op == 'DELETE':
352 removes.add(gp.path)
352 removes.add(gp.path)
353
353
354 wctx = repo[None]
354 wctx = repo[None]
355 for src, dst in copies:
355 for src, dst in copies:
356 wctx.copy(src, dst)
356 wctx.copy(src, dst)
357 if (not similarity) and removes:
357 if (not similarity) and removes:
358 wctx.remove(sorted(removes), True)
358 wctx.remove(sorted(removes), True)
359
359
360 for f in patches:
360 for f in patches:
361 gp = patches[f]
361 gp = patches[f]
362 if gp and gp.mode:
362 if gp and gp.mode:
363 islink, isexec = gp.mode
363 islink, isexec = gp.mode
364 dst = repo.wjoin(gp.path)
364 dst = repo.wjoin(gp.path)
365 # patch won't create empty files
365 # patch won't create empty files
366 if gp.op == 'ADD' and not os.path.exists(dst):
366 if gp.op == 'ADD' and not os.path.exists(dst):
367 flags = (isexec and 'x' or '') + (islink and 'l' or '')
367 flags = (isexec and 'x' or '') + (islink and 'l' or '')
368 repo.wwrite(gp.path, '', flags)
368 repo.wwrite(gp.path, '', flags)
369 util.set_flags(dst, islink, isexec)
369 util.set_flags(dst, islink, isexec)
370 addremove(repo, cfiles, similarity=similarity)
370 addremove(repo, cfiles, similarity=similarity)
371 files = patches.keys()
371 files = patches.keys()
372 files.extend([r for r in removes if r not in files])
372 files.extend([r for r in removes if r not in files])
373 return sorted(files)
373 return sorted(files)
374
374
375 def copy(ui, repo, pats, opts, rename=False):
375 def copy(ui, repo, pats, opts, rename=False):
376 # called with the repo lock held
376 # called with the repo lock held
377 #
377 #
378 # hgsep => pathname that uses "/" to separate directories
378 # hgsep => pathname that uses "/" to separate directories
379 # ossep => pathname that uses os.sep to separate directories
379 # ossep => pathname that uses os.sep to separate directories
380 cwd = repo.getcwd()
380 cwd = repo.getcwd()
381 targets = {}
381 targets = {}
382 after = opts.get("after")
382 after = opts.get("after")
383 dryrun = opts.get("dry_run")
383 dryrun = opts.get("dry_run")
384 wctx = repo[None]
384 wctx = repo[None]
385
385
386 def walkpat(pat):
386 def walkpat(pat):
387 srcs = []
387 srcs = []
388 badstates = after and '?' or '?r'
388 badstates = after and '?' or '?r'
389 m = match(repo, [pat], opts, globbed=True)
389 m = match(repo, [pat], opts, globbed=True)
390 for abs in repo.walk(m):
390 for abs in repo.walk(m):
391 state = repo.dirstate[abs]
391 state = repo.dirstate[abs]
392 rel = m.rel(abs)
392 rel = m.rel(abs)
393 exact = m.exact(abs)
393 exact = m.exact(abs)
394 if state in badstates:
394 if state in badstates:
395 if exact and state == '?':
395 if exact and state == '?':
396 ui.warn(_('%s: not copying - file is not managed\n') % rel)
396 ui.warn(_('%s: not copying - file is not managed\n') % rel)
397 if exact and state == 'r':
397 if exact and state == 'r':
398 ui.warn(_('%s: not copying - file has been marked for'
398 ui.warn(_('%s: not copying - file has been marked for'
399 ' remove\n') % rel)
399 ' remove\n') % rel)
400 continue
400 continue
401 # abs: hgsep
401 # abs: hgsep
402 # rel: ossep
402 # rel: ossep
403 srcs.append((abs, rel, exact))
403 srcs.append((abs, rel, exact))
404 return srcs
404 return srcs
405
405
406 # abssrc: hgsep
406 # abssrc: hgsep
407 # relsrc: ossep
407 # relsrc: ossep
408 # otarget: ossep
408 # otarget: ossep
409 def copyfile(abssrc, relsrc, otarget, exact):
409 def copyfile(abssrc, relsrc, otarget, exact):
410 abstarget = util.canonpath(repo.root, cwd, otarget)
410 abstarget = util.canonpath(repo.root, cwd, otarget)
411 reltarget = repo.pathto(abstarget, cwd)
411 reltarget = repo.pathto(abstarget, cwd)
412 target = repo.wjoin(abstarget)
412 target = repo.wjoin(abstarget)
413 src = repo.wjoin(abssrc)
413 src = repo.wjoin(abssrc)
414 state = repo.dirstate[abstarget]
414 state = repo.dirstate[abstarget]
415
415
416 # check for collisions
416 # check for collisions
417 prevsrc = targets.get(abstarget)
417 prevsrc = targets.get(abstarget)
418 if prevsrc is not None:
418 if prevsrc is not None:
419 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
419 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
420 (reltarget, repo.pathto(abssrc, cwd),
420 (reltarget, repo.pathto(abssrc, cwd),
421 repo.pathto(prevsrc, cwd)))
421 repo.pathto(prevsrc, cwd)))
422 return
422 return
423
423
424 # check for overwrites
424 # check for overwrites
425 exists = os.path.exists(target)
425 exists = os.path.exists(target)
426 if not after and exists or after and state in 'mn':
426 if not after and exists or after and state in 'mn':
427 if not opts['force']:
427 if not opts['force']:
428 ui.warn(_('%s: not overwriting - file exists\n') %
428 ui.warn(_('%s: not overwriting - file exists\n') %
429 reltarget)
429 reltarget)
430 return
430 return
431
431
432 if after:
432 if after:
433 if not exists:
433 if not exists:
434 if rename:
434 if rename:
435 ui.warn(_('%s: not recording move - %s does not exist\n') %
435 ui.warn(_('%s: not recording move - %s does not exist\n') %
436 (relsrc, reltarget))
436 (relsrc, reltarget))
437 else:
437 else:
438 ui.warn(_('%s: not recording copy - %s does not exist\n') %
438 ui.warn(_('%s: not recording copy - %s does not exist\n') %
439 (relsrc, reltarget))
439 (relsrc, reltarget))
440 return
440 return
441 elif not dryrun:
441 elif not dryrun:
442 try:
442 try:
443 if exists:
443 if exists:
444 os.unlink(target)
444 os.unlink(target)
445 targetdir = os.path.dirname(target) or '.'
445 targetdir = os.path.dirname(target) or '.'
446 if not os.path.isdir(targetdir):
446 if not os.path.isdir(targetdir):
447 os.makedirs(targetdir)
447 os.makedirs(targetdir)
448 util.copyfile(src, target)
448 util.copyfile(src, target)
449 except IOError, inst:
449 except IOError, inst:
450 if inst.errno == errno.ENOENT:
450 if inst.errno == errno.ENOENT:
451 ui.warn(_('%s: deleted in working copy\n') % relsrc)
451 ui.warn(_('%s: deleted in working copy\n') % relsrc)
452 else:
452 else:
453 ui.warn(_('%s: cannot copy - %s\n') %
453 ui.warn(_('%s: cannot copy - %s\n') %
454 (relsrc, inst.strerror))
454 (relsrc, inst.strerror))
455 return True # report a failure
455 return True # report a failure
456
456
457 if ui.verbose or not exact:
457 if ui.verbose or not exact:
458 if rename:
458 if rename:
459 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
459 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
460 else:
460 else:
461 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
461 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
462
462
463 targets[abstarget] = abssrc
463 targets[abstarget] = abssrc
464
464
465 # fix up dirstate
465 # fix up dirstate
466 origsrc = repo.dirstate.copied(abssrc) or abssrc
466 origsrc = repo.dirstate.copied(abssrc) or abssrc
467 if abstarget == origsrc: # copying back a copy?
467 if abstarget == origsrc: # copying back a copy?
468 if state not in 'mn' and not dryrun:
468 if state not in 'mn' and not dryrun:
469 repo.dirstate.normallookup(abstarget)
469 repo.dirstate.normallookup(abstarget)
470 else:
470 else:
471 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
471 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
472 if not ui.quiet:
472 if not ui.quiet:
473 ui.warn(_("%s has not been committed yet, so no copy "
473 ui.warn(_("%s has not been committed yet, so no copy "
474 "data will be stored for %s.\n")
474 "data will be stored for %s.\n")
475 % (repo.pathto(origsrc, cwd), reltarget))
475 % (repo.pathto(origsrc, cwd), reltarget))
476 if repo.dirstate[abstarget] in '?r' and not dryrun:
476 if repo.dirstate[abstarget] in '?r' and not dryrun:
477 wctx.add([abstarget])
477 wctx.add([abstarget])
478 elif not dryrun:
478 elif not dryrun:
479 wctx.copy(origsrc, abstarget)
479 wctx.copy(origsrc, abstarget)
480
480
481 if rename and not dryrun:
481 if rename and not dryrun:
482 wctx.remove([abssrc], not after)
482 wctx.remove([abssrc], not after)
483
483
484 # pat: ossep
484 # pat: ossep
485 # dest ossep
485 # dest ossep
486 # srcs: list of (hgsep, hgsep, ossep, bool)
486 # srcs: list of (hgsep, hgsep, ossep, bool)
487 # return: function that takes hgsep and returns ossep
487 # return: function that takes hgsep and returns ossep
488 def targetpathfn(pat, dest, srcs):
488 def targetpathfn(pat, dest, srcs):
489 if os.path.isdir(pat):
489 if os.path.isdir(pat):
490 abspfx = util.canonpath(repo.root, cwd, pat)
490 abspfx = util.canonpath(repo.root, cwd, pat)
491 abspfx = util.localpath(abspfx)
491 abspfx = util.localpath(abspfx)
492 if destdirexists:
492 if destdirexists:
493 striplen = len(os.path.split(abspfx)[0])
493 striplen = len(os.path.split(abspfx)[0])
494 else:
494 else:
495 striplen = len(abspfx)
495 striplen = len(abspfx)
496 if striplen:
496 if striplen:
497 striplen += len(os.sep)
497 striplen += len(os.sep)
498 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
498 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
499 elif destdirexists:
499 elif destdirexists:
500 res = lambda p: os.path.join(dest,
500 res = lambda p: os.path.join(dest,
501 os.path.basename(util.localpath(p)))
501 os.path.basename(util.localpath(p)))
502 else:
502 else:
503 res = lambda p: dest
503 res = lambda p: dest
504 return res
504 return res
505
505
506 # pat: ossep
506 # pat: ossep
507 # dest ossep
507 # dest ossep
508 # srcs: list of (hgsep, hgsep, ossep, bool)
508 # srcs: list of (hgsep, hgsep, ossep, bool)
509 # return: function that takes hgsep and returns ossep
509 # return: function that takes hgsep and returns ossep
510 def targetpathafterfn(pat, dest, srcs):
510 def targetpathafterfn(pat, dest, srcs):
511 if matchmod.patkind(pat):
511 if matchmod.patkind(pat):
512 # a mercurial pattern
512 # a mercurial pattern
513 res = lambda p: os.path.join(dest,
513 res = lambda p: os.path.join(dest,
514 os.path.basename(util.localpath(p)))
514 os.path.basename(util.localpath(p)))
515 else:
515 else:
516 abspfx = util.canonpath(repo.root, cwd, pat)
516 abspfx = util.canonpath(repo.root, cwd, pat)
517 if len(abspfx) < len(srcs[0][0]):
517 if len(abspfx) < len(srcs[0][0]):
518 # A directory. Either the target path contains the last
518 # A directory. Either the target path contains the last
519 # component of the source path or it does not.
519 # component of the source path or it does not.
520 def evalpath(striplen):
520 def evalpath(striplen):
521 score = 0
521 score = 0
522 for s in srcs:
522 for s in srcs:
523 t = os.path.join(dest, util.localpath(s[0])[striplen:])
523 t = os.path.join(dest, util.localpath(s[0])[striplen:])
524 if os.path.exists(t):
524 if os.path.exists(t):
525 score += 1
525 score += 1
526 return score
526 return score
527
527
528 abspfx = util.localpath(abspfx)
528 abspfx = util.localpath(abspfx)
529 striplen = len(abspfx)
529 striplen = len(abspfx)
530 if striplen:
530 if striplen:
531 striplen += len(os.sep)
531 striplen += len(os.sep)
532 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
532 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
533 score = evalpath(striplen)
533 score = evalpath(striplen)
534 striplen1 = len(os.path.split(abspfx)[0])
534 striplen1 = len(os.path.split(abspfx)[0])
535 if striplen1:
535 if striplen1:
536 striplen1 += len(os.sep)
536 striplen1 += len(os.sep)
537 if evalpath(striplen1) > score:
537 if evalpath(striplen1) > score:
538 striplen = striplen1
538 striplen = striplen1
539 res = lambda p: os.path.join(dest,
539 res = lambda p: os.path.join(dest,
540 util.localpath(p)[striplen:])
540 util.localpath(p)[striplen:])
541 else:
541 else:
542 # a file
542 # a file
543 if destdirexists:
543 if destdirexists:
544 res = lambda p: os.path.join(dest,
544 res = lambda p: os.path.join(dest,
545 os.path.basename(util.localpath(p)))
545 os.path.basename(util.localpath(p)))
546 else:
546 else:
547 res = lambda p: dest
547 res = lambda p: dest
548 return res
548 return res
549
549
550
550
551 pats = expandpats(pats)
551 pats = expandpats(pats)
552 if not pats:
552 if not pats:
553 raise util.Abort(_('no source or destination specified'))
553 raise util.Abort(_('no source or destination specified'))
554 if len(pats) == 1:
554 if len(pats) == 1:
555 raise util.Abort(_('no destination specified'))
555 raise util.Abort(_('no destination specified'))
556 dest = pats.pop()
556 dest = pats.pop()
557 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
557 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
558 if not destdirexists:
558 if not destdirexists:
559 if len(pats) > 1 or matchmod.patkind(pats[0]):
559 if len(pats) > 1 or matchmod.patkind(pats[0]):
560 raise util.Abort(_('with multiple sources, destination must be an '
560 raise util.Abort(_('with multiple sources, destination must be an '
561 'existing directory'))
561 'existing directory'))
562 if util.endswithsep(dest):
562 if util.endswithsep(dest):
563 raise util.Abort(_('destination %s is not a directory') % dest)
563 raise util.Abort(_('destination %s is not a directory') % dest)
564
564
565 tfn = targetpathfn
565 tfn = targetpathfn
566 if after:
566 if after:
567 tfn = targetpathafterfn
567 tfn = targetpathafterfn
568 copylist = []
568 copylist = []
569 for pat in pats:
569 for pat in pats:
570 srcs = walkpat(pat)
570 srcs = walkpat(pat)
571 if not srcs:
571 if not srcs:
572 continue
572 continue
573 copylist.append((tfn(pat, dest, srcs), srcs))
573 copylist.append((tfn(pat, dest, srcs), srcs))
574 if not copylist:
574 if not copylist:
575 raise util.Abort(_('no files to copy'))
575 raise util.Abort(_('no files to copy'))
576
576
577 errors = 0
577 errors = 0
578 for targetpath, srcs in copylist:
578 for targetpath, srcs in copylist:
579 for abssrc, relsrc, exact in srcs:
579 for abssrc, relsrc, exact in srcs:
580 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
580 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
581 errors += 1
581 errors += 1
582
582
583 if errors:
583 if errors:
584 ui.warn(_('(consider using --after)\n'))
584 ui.warn(_('(consider using --after)\n'))
585
585
586 return errors != 0
586 return errors != 0
587
587
588 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
588 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
589 runargs=None, appendpid=False):
589 runargs=None, appendpid=False):
590 '''Run a command as a service.'''
590 '''Run a command as a service.'''
591
591
592 if opts['daemon'] and not opts['daemon_pipefds']:
592 if opts['daemon'] and not opts['daemon_pipefds']:
593 # Signal child process startup with file removal
593 # Signal child process startup with file removal
594 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
594 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
595 os.close(lockfd)
595 os.close(lockfd)
596 try:
596 try:
597 if not runargs:
597 if not runargs:
598 runargs = util.hgcmd() + sys.argv[1:]
598 runargs = util.hgcmd() + sys.argv[1:]
599 runargs.append('--daemon-pipefds=%s' % lockpath)
599 runargs.append('--daemon-pipefds=%s' % lockpath)
600 # Don't pass --cwd to the child process, because we've already
600 # Don't pass --cwd to the child process, because we've already
601 # changed directory.
601 # changed directory.
602 for i in xrange(1, len(runargs)):
602 for i in xrange(1, len(runargs)):
603 if runargs[i].startswith('--cwd='):
603 if runargs[i].startswith('--cwd='):
604 del runargs[i]
604 del runargs[i]
605 break
605 break
606 elif runargs[i].startswith('--cwd'):
606 elif runargs[i].startswith('--cwd'):
607 del runargs[i:i + 2]
607 del runargs[i:i + 2]
608 break
608 break
609 def condfn():
609 def condfn():
610 return not os.path.exists(lockpath)
610 return not os.path.exists(lockpath)
611 pid = util.rundetached(runargs, condfn)
611 pid = util.rundetached(runargs, condfn)
612 if pid < 0:
612 if pid < 0:
613 raise util.Abort(_('child process failed to start'))
613 raise util.Abort(_('child process failed to start'))
614 finally:
614 finally:
615 try:
615 try:
616 os.unlink(lockpath)
616 os.unlink(lockpath)
617 except OSError, e:
617 except OSError, e:
618 if e.errno != errno.ENOENT:
618 if e.errno != errno.ENOENT:
619 raise
619 raise
620 if parentfn:
620 if parentfn:
621 return parentfn(pid)
621 return parentfn(pid)
622 else:
622 else:
623 return
623 return
624
624
625 if initfn:
625 if initfn:
626 initfn()
626 initfn()
627
627
628 if opts['pid_file']:
628 if opts['pid_file']:
629 mode = appendpid and 'a' or 'w'
629 mode = appendpid and 'a' or 'w'
630 fp = open(opts['pid_file'], mode)
630 fp = open(opts['pid_file'], mode)
631 fp.write(str(os.getpid()) + '\n')
631 fp.write(str(os.getpid()) + '\n')
632 fp.close()
632 fp.close()
633
633
634 if opts['daemon_pipefds']:
634 if opts['daemon_pipefds']:
635 lockpath = opts['daemon_pipefds']
635 lockpath = opts['daemon_pipefds']
636 try:
636 try:
637 os.setsid()
637 os.setsid()
638 except AttributeError:
638 except AttributeError:
639 pass
639 pass
640 os.unlink(lockpath)
640 os.unlink(lockpath)
641 util.hidewindow()
641 util.hidewindow()
642 sys.stdout.flush()
642 sys.stdout.flush()
643 sys.stderr.flush()
643 sys.stderr.flush()
644
644
645 nullfd = os.open(util.nulldev, os.O_RDWR)
645 nullfd = os.open(util.nulldev, os.O_RDWR)
646 logfilefd = nullfd
646 logfilefd = nullfd
647 if logfile:
647 if logfile:
648 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
648 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
649 os.dup2(nullfd, 0)
649 os.dup2(nullfd, 0)
650 os.dup2(logfilefd, 1)
650 os.dup2(logfilefd, 1)
651 os.dup2(logfilefd, 2)
651 os.dup2(logfilefd, 2)
652 if nullfd not in (0, 1, 2):
652 if nullfd not in (0, 1, 2):
653 os.close(nullfd)
653 os.close(nullfd)
654 if logfile and logfilefd not in (0, 1, 2):
654 if logfile and logfilefd not in (0, 1, 2):
655 os.close(logfilefd)
655 os.close(logfilefd)
656
656
657 if runfn:
657 if runfn:
658 return runfn()
658 return runfn()
659
659
660 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
660 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
661 opts=None):
661 opts=None):
662 '''export changesets as hg patches.'''
662 '''export changesets as hg patches.'''
663
663
664 total = len(revs)
664 total = len(revs)
665 revwidth = max([len(str(rev)) for rev in revs])
665 revwidth = max([len(str(rev)) for rev in revs])
666
666
667 def single(rev, seqno, fp):
667 def single(rev, seqno, fp):
668 ctx = repo[rev]
668 ctx = repo[rev]
669 node = ctx.node()
669 node = ctx.node()
670 parents = [p.node() for p in ctx.parents() if p]
670 parents = [p.node() for p in ctx.parents() if p]
671 branch = ctx.branch()
671 branch = ctx.branch()
672 if switch_parent:
672 if switch_parent:
673 parents.reverse()
673 parents.reverse()
674 prev = (parents and parents[0]) or nullid
674 prev = (parents and parents[0]) or nullid
675
675
676 if not fp:
676 if not fp:
677 fp = make_file(repo, template, node, total=total, seqno=seqno,
677 fp = make_file(repo, template, node, total=total, seqno=seqno,
678 revwidth=revwidth, mode='ab')
678 revwidth=revwidth, mode='ab')
679 if fp != sys.stdout and hasattr(fp, 'name'):
679 if fp != sys.stdout and hasattr(fp, 'name'):
680 repo.ui.note("%s\n" % fp.name)
680 repo.ui.note("%s\n" % fp.name)
681
681
682 fp.write("# HG changeset patch\n")
682 fp.write("# HG changeset patch\n")
683 fp.write("# User %s\n" % ctx.user())
683 fp.write("# User %s\n" % ctx.user())
684 fp.write("# Date %d %d\n" % ctx.date())
684 fp.write("# Date %d %d\n" % ctx.date())
685 if branch and branch != 'default':
685 if branch and branch != 'default':
686 fp.write("# Branch %s\n" % branch)
686 fp.write("# Branch %s\n" % branch)
687 fp.write("# Node ID %s\n" % hex(node))
687 fp.write("# Node ID %s\n" % hex(node))
688 fp.write("# Parent %s\n" % hex(prev))
688 fp.write("# Parent %s\n" % hex(prev))
689 if len(parents) > 1:
689 if len(parents) > 1:
690 fp.write("# Parent %s\n" % hex(parents[1]))
690 fp.write("# Parent %s\n" % hex(parents[1]))
691 fp.write(ctx.description().rstrip())
691 fp.write(ctx.description().rstrip())
692 fp.write("\n\n")
692 fp.write("\n\n")
693
693
694 for chunk in patch.diff(repo, prev, node, opts=opts):
694 for chunk in patch.diff(repo, prev, node, opts=opts):
695 fp.write(chunk)
695 fp.write(chunk)
696
696
697 for seqno, rev in enumerate(revs):
697 for seqno, rev in enumerate(revs):
698 single(rev, seqno + 1, fp)
698 single(rev, seqno + 1, fp)
699
699
700 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
700 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
701 changes=None, stat=False, fp=None, prefix='',
701 changes=None, stat=False, fp=None, prefix='',
702 listsubrepos=False):
702 listsubrepos=False):
703 '''show diff or diffstat.'''
703 '''show diff or diffstat.'''
704 if fp is None:
704 if fp is None:
705 write = ui.write
705 write = ui.write
706 else:
706 else:
707 def write(s, **kw):
707 def write(s, **kw):
708 fp.write(s)
708 fp.write(s)
709
709
710 if stat:
710 if stat:
711 diffopts = diffopts.copy(context=0)
711 diffopts = diffopts.copy(context=0)
712 width = 80
712 width = 80
713 if not ui.plain():
713 if not ui.plain():
714 width = util.termwidth()
714 width = util.termwidth()
715 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
715 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
716 prefix=prefix)
716 prefix=prefix)
717 for chunk, label in patch.diffstatui(util.iterlines(chunks),
717 for chunk, label in patch.diffstatui(util.iterlines(chunks),
718 width=width,
718 width=width,
719 git=diffopts.git):
719 git=diffopts.git):
720 write(chunk, label=label)
720 write(chunk, label=label)
721 else:
721 else:
722 for chunk, label in patch.diffui(repo, node1, node2, match,
722 for chunk, label in patch.diffui(repo, node1, node2, match,
723 changes, diffopts, prefix=prefix):
723 changes, diffopts, prefix=prefix):
724 write(chunk, label=label)
724 write(chunk, label=label)
725
725
726 if listsubrepos:
726 if listsubrepos:
727 ctx1 = repo[node1]
727 ctx1 = repo[node1]
728 ctx2 = repo[node2]
728 ctx2 = repo[node2]
729 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
729 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
730 if node2 is not None:
730 if node2 is not None:
731 node2 = ctx2.substate[subpath][1]
731 node2 = ctx2.substate[subpath][1]
732 submatch = matchmod.narrowmatcher(subpath, match)
732 submatch = matchmod.narrowmatcher(subpath, match)
733 sub.diff(diffopts, node2, submatch, changes=changes,
733 sub.diff(diffopts, node2, submatch, changes=changes,
734 stat=stat, fp=fp, prefix=prefix)
734 stat=stat, fp=fp, prefix=prefix)
735
735
736 class changeset_printer(object):
736 class changeset_printer(object):
737 '''show changeset information when templating not requested.'''
737 '''show changeset information when templating not requested.'''
738
738
739 def __init__(self, ui, repo, patch, diffopts, buffered):
739 def __init__(self, ui, repo, patch, diffopts, buffered):
740 self.ui = ui
740 self.ui = ui
741 self.repo = repo
741 self.repo = repo
742 self.buffered = buffered
742 self.buffered = buffered
743 self.patch = patch
743 self.patch = patch
744 self.diffopts = diffopts
744 self.diffopts = diffopts
745 self.header = {}
745 self.header = {}
746 self.hunk = {}
746 self.hunk = {}
747 self.lastheader = None
747 self.lastheader = None
748 self.footer = None
748 self.footer = None
749
749
750 def flush(self, rev):
750 def flush(self, rev):
751 if rev in self.header:
751 if rev in self.header:
752 h = self.header[rev]
752 h = self.header[rev]
753 if h != self.lastheader:
753 if h != self.lastheader:
754 self.lastheader = h
754 self.lastheader = h
755 self.ui.write(h)
755 self.ui.write(h)
756 del self.header[rev]
756 del self.header[rev]
757 if rev in self.hunk:
757 if rev in self.hunk:
758 self.ui.write(self.hunk[rev])
758 self.ui.write(self.hunk[rev])
759 del self.hunk[rev]
759 del self.hunk[rev]
760 return 1
760 return 1
761 return 0
761 return 0
762
762
763 def close(self):
763 def close(self):
764 if self.footer:
764 if self.footer:
765 self.ui.write(self.footer)
765 self.ui.write(self.footer)
766
766
767 def show(self, ctx, copies=None, matchfn=None, **props):
767 def show(self, ctx, copies=None, matchfn=None, **props):
768 if self.buffered:
768 if self.buffered:
769 self.ui.pushbuffer()
769 self.ui.pushbuffer()
770 self._show(ctx, copies, matchfn, props)
770 self._show(ctx, copies, matchfn, props)
771 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
771 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
772 else:
772 else:
773 self._show(ctx, copies, matchfn, props)
773 self._show(ctx, copies, matchfn, props)
774
774
775 def _show(self, ctx, copies, matchfn, props):
775 def _show(self, ctx, copies, matchfn, props):
776 '''show a single changeset or file revision'''
776 '''show a single changeset or file revision'''
777 changenode = ctx.node()
777 changenode = ctx.node()
778 rev = ctx.rev()
778 rev = ctx.rev()
779
779
780 if self.ui.quiet:
780 if self.ui.quiet:
781 self.ui.write("%d:%s\n" % (rev, short(changenode)),
781 self.ui.write("%d:%s\n" % (rev, short(changenode)),
782 label='log.node')
782 label='log.node')
783 return
783 return
784
784
785 log = self.repo.changelog
785 log = self.repo.changelog
786 date = util.datestr(ctx.date())
786 date = util.datestr(ctx.date())
787
787
788 hexfunc = self.ui.debugflag and hex or short
788 hexfunc = self.ui.debugflag and hex or short
789
789
790 parents = [(p, hexfunc(log.node(p)))
790 parents = [(p, hexfunc(log.node(p)))
791 for p in self._meaningful_parentrevs(log, rev)]
791 for p in self._meaningful_parentrevs(log, rev)]
792
792
793 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
793 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
794 label='log.changeset')
794 label='log.changeset')
795
795
796 branch = ctx.branch()
796 branch = ctx.branch()
797 # don't show the default branch name
797 # don't show the default branch name
798 if branch != 'default':
798 if branch != 'default':
799 branch = encoding.tolocal(branch)
799 branch = encoding.tolocal(branch)
800 self.ui.write(_("branch: %s\n") % branch,
800 self.ui.write(_("branch: %s\n") % branch,
801 label='log.branch')
801 label='log.branch')
802 for tag in self.repo.nodetags(changenode):
802 for tag in self.repo.nodetags(changenode):
803 self.ui.write(_("tag: %s\n") % tag,
803 self.ui.write(_("tag: %s\n") % tag,
804 label='log.tag')
804 label='log.tag')
805 for parent in parents:
805 for parent in parents:
806 self.ui.write(_("parent: %d:%s\n") % parent,
806 self.ui.write(_("parent: %d:%s\n") % parent,
807 label='log.parent')
807 label='log.parent')
808
808
809 if self.ui.debugflag:
809 if self.ui.debugflag:
810 mnode = ctx.manifestnode()
810 mnode = ctx.manifestnode()
811 self.ui.write(_("manifest: %d:%s\n") %
811 self.ui.write(_("manifest: %d:%s\n") %
812 (self.repo.manifest.rev(mnode), hex(mnode)),
812 (self.repo.manifest.rev(mnode), hex(mnode)),
813 label='ui.debug log.manifest')
813 label='ui.debug log.manifest')
814 self.ui.write(_("user: %s\n") % ctx.user(),
814 self.ui.write(_("user: %s\n") % ctx.user(),
815 label='log.user')
815 label='log.user')
816 self.ui.write(_("date: %s\n") % date,
816 self.ui.write(_("date: %s\n") % date,
817 label='log.date')
817 label='log.date')
818
818
819 if self.ui.debugflag:
819 if self.ui.debugflag:
820 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
820 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
821 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
821 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
822 files):
822 files):
823 if value:
823 if value:
824 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
824 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
825 label='ui.debug log.files')
825 label='ui.debug log.files')
826 elif ctx.files() and self.ui.verbose:
826 elif ctx.files() and self.ui.verbose:
827 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
827 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
828 label='ui.note log.files')
828 label='ui.note log.files')
829 if copies and self.ui.verbose:
829 if copies and self.ui.verbose:
830 copies = ['%s (%s)' % c for c in copies]
830 copies = ['%s (%s)' % c for c in copies]
831 self.ui.write(_("copies: %s\n") % ' '.join(copies),
831 self.ui.write(_("copies: %s\n") % ' '.join(copies),
832 label='ui.note log.copies')
832 label='ui.note log.copies')
833
833
834 extra = ctx.extra()
834 extra = ctx.extra()
835 if extra and self.ui.debugflag:
835 if extra and self.ui.debugflag:
836 for key, value in sorted(extra.items()):
836 for key, value in sorted(extra.items()):
837 self.ui.write(_("extra: %s=%s\n")
837 self.ui.write(_("extra: %s=%s\n")
838 % (key, value.encode('string_escape')),
838 % (key, value.encode('string_escape')),
839 label='ui.debug log.extra')
839 label='ui.debug log.extra')
840
840
841 description = ctx.description().strip()
841 description = ctx.description().strip()
842 if description:
842 if description:
843 if self.ui.verbose:
843 if self.ui.verbose:
844 self.ui.write(_("description:\n"),
844 self.ui.write(_("description:\n"),
845 label='ui.note log.description')
845 label='ui.note log.description')
846 self.ui.write(description,
846 self.ui.write(description,
847 label='ui.note log.description')
847 label='ui.note log.description')
848 self.ui.write("\n\n")
848 self.ui.write("\n\n")
849 else:
849 else:
850 self.ui.write(_("summary: %s\n") %
850 self.ui.write(_("summary: %s\n") %
851 description.splitlines()[0],
851 description.splitlines()[0],
852 label='log.summary')
852 label='log.summary')
853 self.ui.write("\n")
853 self.ui.write("\n")
854
854
855 self.showpatch(changenode, matchfn)
855 self.showpatch(changenode, matchfn)
856
856
857 def showpatch(self, node, matchfn):
857 def showpatch(self, node, matchfn):
858 if not matchfn:
858 if not matchfn:
859 matchfn = self.patch
859 matchfn = self.patch
860 if matchfn:
860 if matchfn:
861 stat = self.diffopts.get('stat')
861 stat = self.diffopts.get('stat')
862 diff = self.diffopts.get('patch')
862 diff = self.diffopts.get('patch')
863 diffopts = patch.diffopts(self.ui, self.diffopts)
863 diffopts = patch.diffopts(self.ui, self.diffopts)
864 prev = self.repo.changelog.parents(node)[0]
864 prev = self.repo.changelog.parents(node)[0]
865 if stat:
865 if stat:
866 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
866 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
867 match=matchfn, stat=True)
867 match=matchfn, stat=True)
868 if diff:
868 if diff:
869 if stat:
869 if stat:
870 self.ui.write("\n")
870 self.ui.write("\n")
871 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
871 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
872 match=matchfn, stat=False)
872 match=matchfn, stat=False)
873 self.ui.write("\n")
873 self.ui.write("\n")
874
874
875 def _meaningful_parentrevs(self, log, rev):
875 def _meaningful_parentrevs(self, log, rev):
876 """Return list of meaningful (or all if debug) parentrevs for rev.
876 """Return list of meaningful (or all if debug) parentrevs for rev.
877
877
878 For merges (two non-nullrev revisions) both parents are meaningful.
878 For merges (two non-nullrev revisions) both parents are meaningful.
879 Otherwise the first parent revision is considered meaningful if it
879 Otherwise the first parent revision is considered meaningful if it
880 is not the preceding revision.
880 is not the preceding revision.
881 """
881 """
882 parents = log.parentrevs(rev)
882 parents = log.parentrevs(rev)
883 if not self.ui.debugflag and parents[1] == nullrev:
883 if not self.ui.debugflag and parents[1] == nullrev:
884 if parents[0] >= rev - 1:
884 if parents[0] >= rev - 1:
885 parents = []
885 parents = []
886 else:
886 else:
887 parents = [parents[0]]
887 parents = [parents[0]]
888 return parents
888 return parents
889
889
890
890
891 class changeset_templater(changeset_printer):
891 class changeset_templater(changeset_printer):
892 '''format changeset information.'''
892 '''format changeset information.'''
893
893
894 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
894 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
895 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
895 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
896 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
896 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
897 defaulttempl = {
897 defaulttempl = {
898 'parent': '{rev}:{node|formatnode} ',
898 'parent': '{rev}:{node|formatnode} ',
899 'manifest': '{rev}:{node|formatnode}',
899 'manifest': '{rev}:{node|formatnode}',
900 'file_copy': '{name} ({source})',
900 'file_copy': '{name} ({source})',
901 'extra': '{key}={value|stringescape}'
901 'extra': '{key}={value|stringescape}'
902 }
902 }
903 # filecopy is preserved for compatibility reasons
903 # filecopy is preserved for compatibility reasons
904 defaulttempl['filecopy'] = defaulttempl['file_copy']
904 defaulttempl['filecopy'] = defaulttempl['file_copy']
905 self.t = templater.templater(mapfile, {'formatnode': formatnode},
905 self.t = templater.templater(mapfile, {'formatnode': formatnode},
906 cache=defaulttempl)
906 cache=defaulttempl)
907 self.cache = {}
907 self.cache = {}
908
908
909 def use_template(self, t):
909 def use_template(self, t):
910 '''set template string to use'''
910 '''set template string to use'''
911 self.t.cache['changeset'] = t
911 self.t.cache['changeset'] = t
912
912
913 def _meaningful_parentrevs(self, ctx):
913 def _meaningful_parentrevs(self, ctx):
914 """Return list of meaningful (or all if debug) parentrevs for rev.
914 """Return list of meaningful (or all if debug) parentrevs for rev.
915 """
915 """
916 parents = ctx.parents()
916 parents = ctx.parents()
917 if len(parents) > 1:
917 if len(parents) > 1:
918 return parents
918 return parents
919 if self.ui.debugflag:
919 if self.ui.debugflag:
920 return [parents[0], self.repo['null']]
920 return [parents[0], self.repo['null']]
921 if parents[0].rev() >= ctx.rev() - 1:
921 if parents[0].rev() >= ctx.rev() - 1:
922 return []
922 return []
923 return parents
923 return parents
924
924
925 def _show(self, ctx, copies, matchfn, props):
925 def _show(self, ctx, copies, matchfn, props):
926 '''show a single changeset or file revision'''
926 '''show a single changeset or file revision'''
927
927
928 showlist = templatekw.showlist
928 showlist = templatekw.showlist
929
929
930 # showparents() behaviour depends on ui trace level which
930 # showparents() behaviour depends on ui trace level which
931 # causes unexpected behaviours at templating level and makes
931 # causes unexpected behaviours at templating level and makes
932 # it harder to extract it in a standalone function. Its
932 # it harder to extract it in a standalone function. Its
933 # behaviour cannot be changed so leave it here for now.
933 # behaviour cannot be changed so leave it here for now.
934 def showparents(**args):
934 def showparents(**args):
935 ctx = args['ctx']
935 ctx = args['ctx']
936 parents = [[('rev', p.rev()), ('node', p.hex())]
936 parents = [[('rev', p.rev()), ('node', p.hex())]
937 for p in self._meaningful_parentrevs(ctx)]
937 for p in self._meaningful_parentrevs(ctx)]
938 return showlist('parent', parents, **args)
938 return showlist('parent', parents, **args)
939
939
940 props = props.copy()
940 props = props.copy()
941 props.update(templatekw.keywords)
941 props.update(templatekw.keywords)
942 props['parents'] = showparents
942 props['parents'] = showparents
943 props['templ'] = self.t
943 props['templ'] = self.t
944 props['ctx'] = ctx
944 props['ctx'] = ctx
945 props['repo'] = self.repo
945 props['repo'] = self.repo
946 props['revcache'] = {'copies': copies}
946 props['revcache'] = {'copies': copies}
947 props['cache'] = self.cache
947 props['cache'] = self.cache
948
948
949 # find correct templates for current mode
949 # find correct templates for current mode
950
950
951 tmplmodes = [
951 tmplmodes = [
952 (True, None),
952 (True, None),
953 (self.ui.verbose, 'verbose'),
953 (self.ui.verbose, 'verbose'),
954 (self.ui.quiet, 'quiet'),
954 (self.ui.quiet, 'quiet'),
955 (self.ui.debugflag, 'debug'),
955 (self.ui.debugflag, 'debug'),
956 ]
956 ]
957
957
958 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
958 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
959 for mode, postfix in tmplmodes:
959 for mode, postfix in tmplmodes:
960 for type in types:
960 for type in types:
961 cur = postfix and ('%s_%s' % (type, postfix)) or type
961 cur = postfix and ('%s_%s' % (type, postfix)) or type
962 if mode and cur in self.t:
962 if mode and cur in self.t:
963 types[type] = cur
963 types[type] = cur
964
964
965 try:
965 try:
966
966
967 # write header
967 # write header
968 if types['header']:
968 if types['header']:
969 h = templater.stringify(self.t(types['header'], **props))
969 h = templater.stringify(self.t(types['header'], **props))
970 if self.buffered:
970 if self.buffered:
971 self.header[ctx.rev()] = h
971 self.header[ctx.rev()] = h
972 else:
972 else:
973 if self.lastheader != h:
973 if self.lastheader != h:
974 self.lastheader = h
974 self.lastheader = h
975 self.ui.write(h)
975 self.ui.write(h)
976
976
977 # write changeset metadata, then patch if requested
977 # write changeset metadata, then patch if requested
978 key = types['changeset']
978 key = types['changeset']
979 self.ui.write(templater.stringify(self.t(key, **props)))
979 self.ui.write(templater.stringify(self.t(key, **props)))
980 self.showpatch(ctx.node(), matchfn)
980 self.showpatch(ctx.node(), matchfn)
981
981
982 if types['footer']:
982 if types['footer']:
983 if not self.footer:
983 if not self.footer:
984 self.footer = templater.stringify(self.t(types['footer'],
984 self.footer = templater.stringify(self.t(types['footer'],
985 **props))
985 **props))
986
986
987 except KeyError, inst:
987 except KeyError, inst:
988 msg = _("%s: no key named '%s'")
988 msg = _("%s: no key named '%s'")
989 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
989 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
990 except SyntaxError, inst:
990 except SyntaxError, inst:
991 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
991 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
992
992
993 def show_changeset(ui, repo, opts, buffered=False):
993 def show_changeset(ui, repo, opts, buffered=False):
994 """show one changeset using template or regular display.
994 """show one changeset using template or regular display.
995
995
996 Display format will be the first non-empty hit of:
996 Display format will be the first non-empty hit of:
997 1. option 'template'
997 1. option 'template'
998 2. option 'style'
998 2. option 'style'
999 3. [ui] setting 'logtemplate'
999 3. [ui] setting 'logtemplate'
1000 4. [ui] setting 'style'
1000 4. [ui] setting 'style'
1001 If all of these values are either the unset or the empty string,
1001 If all of these values are either the unset or the empty string,
1002 regular display via changeset_printer() is done.
1002 regular display via changeset_printer() is done.
1003 """
1003 """
1004 # options
1004 # options
1005 patch = False
1005 patch = False
1006 if opts.get('patch') or opts.get('stat'):
1006 if opts.get('patch') or opts.get('stat'):
1007 patch = matchall(repo)
1007 patch = matchall(repo)
1008
1008
1009 tmpl = opts.get('template')
1009 tmpl = opts.get('template')
1010 style = None
1010 style = None
1011 if tmpl:
1011 if tmpl:
1012 tmpl = templater.parsestring(tmpl, quoted=False)
1012 tmpl = templater.parsestring(tmpl, quoted=False)
1013 else:
1013 else:
1014 style = opts.get('style')
1014 style = opts.get('style')
1015
1015
1016 # ui settings
1016 # ui settings
1017 if not (tmpl or style):
1017 if not (tmpl or style):
1018 tmpl = ui.config('ui', 'logtemplate')
1018 tmpl = ui.config('ui', 'logtemplate')
1019 if tmpl:
1019 if tmpl:
1020 tmpl = templater.parsestring(tmpl)
1020 tmpl = templater.parsestring(tmpl)
1021 else:
1021 else:
1022 style = util.expandpath(ui.config('ui', 'style', ''))
1022 style = util.expandpath(ui.config('ui', 'style', ''))
1023
1023
1024 if not (tmpl or style):
1024 if not (tmpl or style):
1025 return changeset_printer(ui, repo, patch, opts, buffered)
1025 return changeset_printer(ui, repo, patch, opts, buffered)
1026
1026
1027 mapfile = None
1027 mapfile = None
1028 if style and not tmpl:
1028 if style and not tmpl:
1029 mapfile = style
1029 mapfile = style
1030 if not os.path.split(mapfile)[0]:
1030 if not os.path.split(mapfile)[0]:
1031 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1031 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1032 or templater.templatepath(mapfile))
1032 or templater.templatepath(mapfile))
1033 if mapname:
1033 if mapname:
1034 mapfile = mapname
1034 mapfile = mapname
1035
1035
1036 try:
1036 try:
1037 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
1037 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
1038 except SyntaxError, inst:
1038 except SyntaxError, inst:
1039 raise util.Abort(inst.args[0])
1039 raise util.Abort(inst.args[0])
1040 if tmpl:
1040 if tmpl:
1041 t.use_template(tmpl)
1041 t.use_template(tmpl)
1042 return t
1042 return t
1043
1043
1044 def finddate(ui, repo, date):
1044 def finddate(ui, repo, date):
1045 """Find the tipmost changeset that matches the given date spec"""
1045 """Find the tipmost changeset that matches the given date spec"""
1046
1046
1047 df = util.matchdate(date)
1047 df = util.matchdate(date)
1048 m = matchall(repo)
1048 m = matchall(repo)
1049 results = {}
1049 results = {}
1050
1050
1051 def prep(ctx, fns):
1051 def prep(ctx, fns):
1052 d = ctx.date()
1052 d = ctx.date()
1053 if df(d[0]):
1053 if df(d[0]):
1054 results[ctx.rev()] = d
1054 results[ctx.rev()] = d
1055
1055
1056 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1056 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1057 rev = ctx.rev()
1057 rev = ctx.rev()
1058 if rev in results:
1058 if rev in results:
1059 ui.status(_("Found revision %s from %s\n") %
1059 ui.status(_("Found revision %s from %s\n") %
1060 (rev, util.datestr(results[rev])))
1060 (rev, util.datestr(results[rev])))
1061 return str(rev)
1061 return str(rev)
1062
1062
1063 raise util.Abort(_("revision matching date not found"))
1063 raise util.Abort(_("revision matching date not found"))
1064
1064
1065 def walkchangerevs(repo, match, opts, prepare):
1065 def walkchangerevs(repo, match, opts, prepare):
1066 '''Iterate over files and the revs in which they changed.
1066 '''Iterate over files and the revs in which they changed.
1067
1067
1068 Callers most commonly need to iterate backwards over the history
1068 Callers most commonly need to iterate backwards over the history
1069 in which they are interested. Doing so has awful (quadratic-looking)
1069 in which they are interested. Doing so has awful (quadratic-looking)
1070 performance, so we use iterators in a "windowed" way.
1070 performance, so we use iterators in a "windowed" way.
1071
1071
1072 We walk a window of revisions in the desired order. Within the
1072 We walk a window of revisions in the desired order. Within the
1073 window, we first walk forwards to gather data, then in the desired
1073 window, we first walk forwards to gather data, then in the desired
1074 order (usually backwards) to display it.
1074 order (usually backwards) to display it.
1075
1075
1076 This function returns an iterator yielding contexts. Before
1076 This function returns an iterator yielding contexts. Before
1077 yielding each context, the iterator will first call the prepare
1077 yielding each context, the iterator will first call the prepare
1078 function on each context in the window in forward order.'''
1078 function on each context in the window in forward order.'''
1079
1079
1080 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1080 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1081 if start < end:
1081 if start < end:
1082 while start < end:
1082 while start < end:
1083 yield start, min(windowsize, end - start)
1083 yield start, min(windowsize, end - start)
1084 start += windowsize
1084 start += windowsize
1085 if windowsize < sizelimit:
1085 if windowsize < sizelimit:
1086 windowsize *= 2
1086 windowsize *= 2
1087 else:
1087 else:
1088 while start > end:
1088 while start > end:
1089 yield start, min(windowsize, start - end - 1)
1089 yield start, min(windowsize, start - end - 1)
1090 start -= windowsize
1090 start -= windowsize
1091 if windowsize < sizelimit:
1091 if windowsize < sizelimit:
1092 windowsize *= 2
1092 windowsize *= 2
1093
1093
1094 follow = opts.get('follow') or opts.get('follow_first')
1094 follow = opts.get('follow') or opts.get('follow_first')
1095
1095
1096 if not len(repo):
1096 if not len(repo):
1097 return []
1097 return []
1098
1098
1099 if follow:
1099 if follow:
1100 defrange = '%s:0' % repo['.'].rev()
1100 defrange = '%s:0' % repo['.'].rev()
1101 else:
1101 else:
1102 defrange = '-1:0'
1102 defrange = '-1:0'
1103 revs = revrange(repo, opts['rev'] or [defrange])
1103 revs = revrange(repo, opts['rev'] or [defrange])
1104 if not revs:
1104 if not revs:
1105 return []
1105 return []
1106 wanted = set()
1106 wanted = set()
1107 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1107 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1108 fncache = {}
1108 fncache = {}
1109 change = util.cachefunc(repo.changectx)
1109 change = util.cachefunc(repo.changectx)
1110
1110
1111 # First step is to fill wanted, the set of revisions that we want to yield.
1111 # First step is to fill wanted, the set of revisions that we want to yield.
1112 # When it does not induce extra cost, we also fill fncache for revisions in
1112 # When it does not induce extra cost, we also fill fncache for revisions in
1113 # wanted: a cache of filenames that were changed (ctx.files()) and that
1113 # wanted: a cache of filenames that were changed (ctx.files()) and that
1114 # match the file filtering conditions.
1114 # match the file filtering conditions.
1115
1115
1116 if not slowpath and not match.files():
1116 if not slowpath and not match.files():
1117 # No files, no patterns. Display all revs.
1117 # No files, no patterns. Display all revs.
1118 wanted = set(revs)
1118 wanted = set(revs)
1119 copies = []
1119 copies = []
1120
1120
1121 if not slowpath:
1121 if not slowpath:
1122 # We only have to read through the filelog to find wanted revisions
1122 # We only have to read through the filelog to find wanted revisions
1123
1123
1124 minrev, maxrev = min(revs), max(revs)
1124 minrev, maxrev = min(revs), max(revs)
1125 def filerevgen(filelog, last):
1125 def filerevgen(filelog, last):
1126 """
1126 """
1127 Only files, no patterns. Check the history of each file.
1127 Only files, no patterns. Check the history of each file.
1128
1128
1129 Examines filelog entries within minrev, maxrev linkrev range
1129 Examines filelog entries within minrev, maxrev linkrev range
1130 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1130 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1131 tuples in backwards order
1131 tuples in backwards order
1132 """
1132 """
1133 cl_count = len(repo)
1133 cl_count = len(repo)
1134 revs = []
1134 revs = []
1135 for j in xrange(0, last + 1):
1135 for j in xrange(0, last + 1):
1136 linkrev = filelog.linkrev(j)
1136 linkrev = filelog.linkrev(j)
1137 if linkrev < minrev:
1137 if linkrev < minrev:
1138 continue
1138 continue
1139 # only yield rev for which we have the changelog, it can
1139 # only yield rev for which we have the changelog, it can
1140 # happen while doing "hg log" during a pull or commit
1140 # happen while doing "hg log" during a pull or commit
1141 if linkrev > maxrev or linkrev >= cl_count:
1141 if linkrev > maxrev or linkrev >= cl_count:
1142 break
1142 break
1143
1143
1144 parentlinkrevs = []
1144 parentlinkrevs = []
1145 for p in filelog.parentrevs(j):
1145 for p in filelog.parentrevs(j):
1146 if p != nullrev:
1146 if p != nullrev:
1147 parentlinkrevs.append(filelog.linkrev(p))
1147 parentlinkrevs.append(filelog.linkrev(p))
1148 n = filelog.node(j)
1148 n = filelog.node(j)
1149 revs.append((linkrev, parentlinkrevs,
1149 revs.append((linkrev, parentlinkrevs,
1150 follow and filelog.renamed(n)))
1150 follow and filelog.renamed(n)))
1151
1151
1152 return reversed(revs)
1152 return reversed(revs)
1153 def iterfiles():
1153 def iterfiles():
1154 for filename in match.files():
1154 for filename in match.files():
1155 yield filename, None
1155 yield filename, None
1156 for filename_node in copies:
1156 for filename_node in copies:
1157 yield filename_node
1157 yield filename_node
1158 for file_, node in iterfiles():
1158 for file_, node in iterfiles():
1159 filelog = repo.file(file_)
1159 filelog = repo.file(file_)
1160 if not len(filelog):
1160 if not len(filelog):
1161 if node is None:
1161 if node is None:
1162 # A zero count may be a directory or deleted file, so
1162 # A zero count may be a directory or deleted file, so
1163 # try to find matching entries on the slow path.
1163 # try to find matching entries on the slow path.
1164 if follow:
1164 if follow:
1165 raise util.Abort(
1165 raise util.Abort(
1166 _('cannot follow nonexistent file: "%s"') % file_)
1166 _('cannot follow nonexistent file: "%s"') % file_)
1167 slowpath = True
1167 slowpath = True
1168 break
1168 break
1169 else:
1169 else:
1170 continue
1170 continue
1171
1171
1172 if node is None:
1172 if node is None:
1173 last = len(filelog) - 1
1173 last = len(filelog) - 1
1174 else:
1174 else:
1175 last = filelog.rev(node)
1175 last = filelog.rev(node)
1176
1176
1177
1177
1178 # keep track of all ancestors of the file
1178 # keep track of all ancestors of the file
1179 ancestors = set([filelog.linkrev(last)])
1179 ancestors = set([filelog.linkrev(last)])
1180
1180
1181 # iterate from latest to oldest revision
1181 # iterate from latest to oldest revision
1182 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1182 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1183 if rev not in ancestors:
1183 if rev not in ancestors:
1184 continue
1184 continue
1185 # XXX insert 1327 fix here
1185 # XXX insert 1327 fix here
1186 if flparentlinkrevs:
1186 if flparentlinkrevs:
1187 ancestors.update(flparentlinkrevs)
1187 ancestors.update(flparentlinkrevs)
1188
1188
1189 fncache.setdefault(rev, []).append(file_)
1189 fncache.setdefault(rev, []).append(file_)
1190 wanted.add(rev)
1190 wanted.add(rev)
1191 if copied:
1191 if copied:
1192 copies.append(copied)
1192 copies.append(copied)
1193 if slowpath:
1193 if slowpath:
1194 # We have to read the changelog to match filenames against
1194 # We have to read the changelog to match filenames against
1195 # changed files
1195 # changed files
1196
1196
1197 if follow:
1197 if follow:
1198 raise util.Abort(_('can only follow copies/renames for explicit '
1198 raise util.Abort(_('can only follow copies/renames for explicit '
1199 'filenames'))
1199 'filenames'))
1200
1200
1201 # The slow path checks files modified in every changeset.
1201 # The slow path checks files modified in every changeset.
1202 for i in sorted(revs):
1202 for i in sorted(revs):
1203 ctx = change(i)
1203 ctx = change(i)
1204 matches = filter(match, ctx.files())
1204 matches = filter(match, ctx.files())
1205 if matches:
1205 if matches:
1206 fncache[i] = matches
1206 fncache[i] = matches
1207 wanted.add(i)
1207 wanted.add(i)
1208
1208
1209 class followfilter(object):
1209 class followfilter(object):
1210 def __init__(self, onlyfirst=False):
1210 def __init__(self, onlyfirst=False):
1211 self.startrev = nullrev
1211 self.startrev = nullrev
1212 self.roots = set()
1212 self.roots = set()
1213 self.onlyfirst = onlyfirst
1213 self.onlyfirst = onlyfirst
1214
1214
1215 def match(self, rev):
1215 def match(self, rev):
1216 def realparents(rev):
1216 def realparents(rev):
1217 if self.onlyfirst:
1217 if self.onlyfirst:
1218 return repo.changelog.parentrevs(rev)[0:1]
1218 return repo.changelog.parentrevs(rev)[0:1]
1219 else:
1219 else:
1220 return filter(lambda x: x != nullrev,
1220 return filter(lambda x: x != nullrev,
1221 repo.changelog.parentrevs(rev))
1221 repo.changelog.parentrevs(rev))
1222
1222
1223 if self.startrev == nullrev:
1223 if self.startrev == nullrev:
1224 self.startrev = rev
1224 self.startrev = rev
1225 return True
1225 return True
1226
1226
1227 if rev > self.startrev:
1227 if rev > self.startrev:
1228 # forward: all descendants
1228 # forward: all descendants
1229 if not self.roots:
1229 if not self.roots:
1230 self.roots.add(self.startrev)
1230 self.roots.add(self.startrev)
1231 for parent in realparents(rev):
1231 for parent in realparents(rev):
1232 if parent in self.roots:
1232 if parent in self.roots:
1233 self.roots.add(rev)
1233 self.roots.add(rev)
1234 return True
1234 return True
1235 else:
1235 else:
1236 # backwards: all parents
1236 # backwards: all parents
1237 if not self.roots:
1237 if not self.roots:
1238 self.roots.update(realparents(self.startrev))
1238 self.roots.update(realparents(self.startrev))
1239 if rev in self.roots:
1239 if rev in self.roots:
1240 self.roots.remove(rev)
1240 self.roots.remove(rev)
1241 self.roots.update(realparents(rev))
1241 self.roots.update(realparents(rev))
1242 return True
1242 return True
1243
1243
1244 return False
1244 return False
1245
1245
1246 # it might be worthwhile to do this in the iterator if the rev range
1246 # it might be worthwhile to do this in the iterator if the rev range
1247 # is descending and the prune args are all within that range
1247 # is descending and the prune args are all within that range
1248 for rev in opts.get('prune', ()):
1248 for rev in opts.get('prune', ()):
1249 rev = repo.changelog.rev(repo.lookup(rev))
1249 rev = repo.changelog.rev(repo.lookup(rev))
1250 ff = followfilter()
1250 ff = followfilter()
1251 stop = min(revs[0], revs[-1])
1251 stop = min(revs[0], revs[-1])
1252 for x in xrange(rev, stop - 1, -1):
1252 for x in xrange(rev, stop - 1, -1):
1253 if ff.match(x):
1253 if ff.match(x):
1254 wanted.discard(x)
1254 wanted.discard(x)
1255
1255
1256 # Now that wanted is correctly initialized, we can iterate over the
1256 # Now that wanted is correctly initialized, we can iterate over the
1257 # revision range, yielding only revisions in wanted.
1257 # revision range, yielding only revisions in wanted.
1258 def iterate():
1258 def iterate():
1259 if follow and not match.files():
1259 if follow and not match.files():
1260 ff = followfilter(onlyfirst=opts.get('follow_first'))
1260 ff = followfilter(onlyfirst=opts.get('follow_first'))
1261 def want(rev):
1261 def want(rev):
1262 return ff.match(rev) and rev in wanted
1262 return ff.match(rev) and rev in wanted
1263 else:
1263 else:
1264 def want(rev):
1264 def want(rev):
1265 return rev in wanted
1265 return rev in wanted
1266
1266
1267 for i, window in increasing_windows(0, len(revs)):
1267 for i, window in increasing_windows(0, len(revs)):
1268 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1268 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1269 for rev in sorted(nrevs):
1269 for rev in sorted(nrevs):
1270 fns = fncache.get(rev)
1270 fns = fncache.get(rev)
1271 ctx = change(rev)
1271 ctx = change(rev)
1272 if not fns:
1272 if not fns:
1273 def fns_generator():
1273 def fns_generator():
1274 for f in ctx.files():
1274 for f in ctx.files():
1275 if match(f):
1275 if match(f):
1276 yield f
1276 yield f
1277 fns = fns_generator()
1277 fns = fns_generator()
1278 prepare(ctx, fns)
1278 prepare(ctx, fns)
1279 for rev in nrevs:
1279 for rev in nrevs:
1280 yield change(rev)
1280 yield change(rev)
1281 return iterate()
1281 return iterate()
1282
1282
1283 def add(ui, repo, match, dryrun):
1284 bad = []
1285 oldbad = match.bad
1286 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1287 names = []
1288 for f in repo.walk(match):
1289 exact = match.exact(f)
1290 if exact or f not in repo.dirstate:
1291 names.append(f)
1292 if ui.verbose or not exact:
1293 ui.status(_('adding %s\n') % match.rel(f))
1294 if not dryrun:
1295 rejected = repo[None].add(names)
1296 bad.extend(f for f in rejected if f in match.files())
1297 return bad
1298
1283 def commit(ui, repo, commitfunc, pats, opts):
1299 def commit(ui, repo, commitfunc, pats, opts):
1284 '''commit the specified files or all outstanding changes'''
1300 '''commit the specified files or all outstanding changes'''
1285 date = opts.get('date')
1301 date = opts.get('date')
1286 if date:
1302 if date:
1287 opts['date'] = util.parsedate(date)
1303 opts['date'] = util.parsedate(date)
1288 message = logmessage(opts)
1304 message = logmessage(opts)
1289
1305
1290 # extract addremove carefully -- this function can be called from a command
1306 # extract addremove carefully -- this function can be called from a command
1291 # that doesn't support addremove
1307 # that doesn't support addremove
1292 if opts.get('addremove'):
1308 if opts.get('addremove'):
1293 addremove(repo, pats, opts)
1309 addremove(repo, pats, opts)
1294
1310
1295 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1311 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1296
1312
1297 def commiteditor(repo, ctx, subs):
1313 def commiteditor(repo, ctx, subs):
1298 if ctx.description():
1314 if ctx.description():
1299 return ctx.description()
1315 return ctx.description()
1300 return commitforceeditor(repo, ctx, subs)
1316 return commitforceeditor(repo, ctx, subs)
1301
1317
1302 def commitforceeditor(repo, ctx, subs):
1318 def commitforceeditor(repo, ctx, subs):
1303 edittext = []
1319 edittext = []
1304 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1320 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1305 if ctx.description():
1321 if ctx.description():
1306 edittext.append(ctx.description())
1322 edittext.append(ctx.description())
1307 edittext.append("")
1323 edittext.append("")
1308 edittext.append("") # Empty line between message and comments.
1324 edittext.append("") # Empty line between message and comments.
1309 edittext.append(_("HG: Enter commit message."
1325 edittext.append(_("HG: Enter commit message."
1310 " Lines beginning with 'HG:' are removed."))
1326 " Lines beginning with 'HG:' are removed."))
1311 edittext.append(_("HG: Leave message empty to abort commit."))
1327 edittext.append(_("HG: Leave message empty to abort commit."))
1312 edittext.append("HG: --")
1328 edittext.append("HG: --")
1313 edittext.append(_("HG: user: %s") % ctx.user())
1329 edittext.append(_("HG: user: %s") % ctx.user())
1314 if ctx.p2():
1330 if ctx.p2():
1315 edittext.append(_("HG: branch merge"))
1331 edittext.append(_("HG: branch merge"))
1316 if ctx.branch():
1332 if ctx.branch():
1317 edittext.append(_("HG: branch '%s'")
1333 edittext.append(_("HG: branch '%s'")
1318 % encoding.tolocal(ctx.branch()))
1334 % encoding.tolocal(ctx.branch()))
1319 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1335 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1320 edittext.extend([_("HG: added %s") % f for f in added])
1336 edittext.extend([_("HG: added %s") % f for f in added])
1321 edittext.extend([_("HG: changed %s") % f for f in modified])
1337 edittext.extend([_("HG: changed %s") % f for f in modified])
1322 edittext.extend([_("HG: removed %s") % f for f in removed])
1338 edittext.extend([_("HG: removed %s") % f for f in removed])
1323 if not added and not modified and not removed:
1339 if not added and not modified and not removed:
1324 edittext.append(_("HG: no files changed"))
1340 edittext.append(_("HG: no files changed"))
1325 edittext.append("")
1341 edittext.append("")
1326 # run editor in the repository root
1342 # run editor in the repository root
1327 olddir = os.getcwd()
1343 olddir = os.getcwd()
1328 os.chdir(repo.root)
1344 os.chdir(repo.root)
1329 text = repo.ui.edit("\n".join(edittext), ctx.user())
1345 text = repo.ui.edit("\n".join(edittext), ctx.user())
1330 text = re.sub("(?m)^HG:.*\n", "", text)
1346 text = re.sub("(?m)^HG:.*\n", "", text)
1331 os.chdir(olddir)
1347 os.chdir(olddir)
1332
1348
1333 if not text.strip():
1349 if not text.strip():
1334 raise util.Abort(_("empty commit message"))
1350 raise util.Abort(_("empty commit message"))
1335
1351
1336 return text
1352 return text
@@ -1,4522 +1,4509 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, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
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, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 bad = []
50 names = []
51 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
52 oldbad = m.bad
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'))
53 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
51 return rejected and 1 or 0
54
55 for f in repo.walk(m):
56 exact = m.exact(f)
57 if exact or f not in repo.dirstate:
58 names.append(f)
59 if ui.verbose or not exact:
60 ui.status(_('adding %s\n') % m.rel(f))
61 if not opts.get('dry_run'):
62 rejected = repo[None].add(names)
63 bad += [f for f in rejected if f in m.files()]
64 return bad and 1 or 0
65
52
66 def addremove(ui, repo, *pats, **opts):
53 def addremove(ui, repo, *pats, **opts):
67 """add all new files, delete all missing files
54 """add all new files, delete all missing files
68
55
69 Add all new files and remove all missing files from the
56 Add all new files and remove all missing files from the
70 repository.
57 repository.
71
58
72 New files are ignored if they match any of the patterns in
59 New files are ignored if they match any of the patterns in
73 .hgignore. As with add, these changes take effect at the next
60 .hgignore. As with add, these changes take effect at the next
74 commit.
61 commit.
75
62
76 Use the -s/--similarity option to detect renamed files. With a
63 Use the -s/--similarity option to detect renamed files. With a
77 parameter greater than 0, this compares every removed file with
64 parameter greater than 0, this compares every removed file with
78 every added file and records those similar enough as renames. This
65 every added file and records those similar enough as renames. This
79 option takes a percentage between 0 (disabled) and 100 (files must
66 option takes a percentage between 0 (disabled) and 100 (files must
80 be identical) as its parameter. Detecting renamed files this way
67 be identical) as its parameter. Detecting renamed files this way
81 can be expensive. After using this option, :hg:`status -C` can be
68 can be expensive. After using this option, :hg:`status -C` can be
82 used to check which files were identified as moved or renamed.
69 used to check which files were identified as moved or renamed.
83
70
84 Returns 0 if all files are successfully added.
71 Returns 0 if all files are successfully added.
85 """
72 """
86 try:
73 try:
87 sim = float(opts.get('similarity') or 100)
74 sim = float(opts.get('similarity') or 100)
88 except ValueError:
75 except ValueError:
89 raise util.Abort(_('similarity must be a number'))
76 raise util.Abort(_('similarity must be a number'))
90 if sim < 0 or sim > 100:
77 if sim < 0 or sim > 100:
91 raise util.Abort(_('similarity must be between 0 and 100'))
78 raise util.Abort(_('similarity must be between 0 and 100'))
92 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
79 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
93
80
94 def annotate(ui, repo, *pats, **opts):
81 def annotate(ui, repo, *pats, **opts):
95 """show changeset information by line for each file
82 """show changeset information by line for each file
96
83
97 List changes in files, showing the revision id responsible for
84 List changes in files, showing the revision id responsible for
98 each line
85 each line
99
86
100 This command is useful for discovering when a change was made and
87 This command is useful for discovering when a change was made and
101 by whom.
88 by whom.
102
89
103 Without the -a/--text option, annotate will avoid processing files
90 Without the -a/--text option, annotate will avoid processing files
104 it detects as binary. With -a, annotate will annotate the file
91 it detects as binary. With -a, annotate will annotate the file
105 anyway, although the results will probably be neither useful
92 anyway, although the results will probably be neither useful
106 nor desirable.
93 nor desirable.
107
94
108 Returns 0 on success.
95 Returns 0 on success.
109 """
96 """
110 if opts.get('follow'):
97 if opts.get('follow'):
111 # --follow is deprecated and now just an alias for -f/--file
98 # --follow is deprecated and now just an alias for -f/--file
112 # to mimic the behavior of Mercurial before version 1.5
99 # to mimic the behavior of Mercurial before version 1.5
113 opts['file'] = 1
100 opts['file'] = 1
114
101
115 datefunc = ui.quiet and util.shortdate or util.datestr
102 datefunc = ui.quiet and util.shortdate or util.datestr
116 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
103 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
117
104
118 if not pats:
105 if not pats:
119 raise util.Abort(_('at least one filename or pattern is required'))
106 raise util.Abort(_('at least one filename or pattern is required'))
120
107
121 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
108 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
122 ('number', lambda x: str(x[0].rev())),
109 ('number', lambda x: str(x[0].rev())),
123 ('changeset', lambda x: short(x[0].node())),
110 ('changeset', lambda x: short(x[0].node())),
124 ('date', getdate),
111 ('date', getdate),
125 ('file', lambda x: x[0].path()),
112 ('file', lambda x: x[0].path()),
126 ]
113 ]
127
114
128 if (not opts.get('user') and not opts.get('changeset')
115 if (not opts.get('user') and not opts.get('changeset')
129 and not opts.get('date') and not opts.get('file')):
116 and not opts.get('date') and not opts.get('file')):
130 opts['number'] = 1
117 opts['number'] = 1
131
118
132 linenumber = opts.get('line_number') is not None
119 linenumber = opts.get('line_number') is not None
133 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
120 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
134 raise util.Abort(_('at least one of -n/-c is required for -l'))
121 raise util.Abort(_('at least one of -n/-c is required for -l'))
135
122
136 funcmap = [func for op, func in opmap if opts.get(op)]
123 funcmap = [func for op, func in opmap if opts.get(op)]
137 if linenumber:
124 if linenumber:
138 lastfunc = funcmap[-1]
125 lastfunc = funcmap[-1]
139 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
126 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
140
127
141 ctx = repo[opts.get('rev')]
128 ctx = repo[opts.get('rev')]
142 m = cmdutil.match(repo, pats, opts)
129 m = cmdutil.match(repo, pats, opts)
143 follow = not opts.get('no_follow')
130 follow = not opts.get('no_follow')
144 for abs in ctx.walk(m):
131 for abs in ctx.walk(m):
145 fctx = ctx[abs]
132 fctx = ctx[abs]
146 if not opts.get('text') and util.binary(fctx.data()):
133 if not opts.get('text') and util.binary(fctx.data()):
147 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
134 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
148 continue
135 continue
149
136
150 lines = fctx.annotate(follow=follow, linenumber=linenumber)
137 lines = fctx.annotate(follow=follow, linenumber=linenumber)
151 pieces = []
138 pieces = []
152
139
153 for f in funcmap:
140 for f in funcmap:
154 l = [f(n) for n, dummy in lines]
141 l = [f(n) for n, dummy in lines]
155 if l:
142 if l:
156 sized = [(x, encoding.colwidth(x)) for x in l]
143 sized = [(x, encoding.colwidth(x)) for x in l]
157 ml = max([w for x, w in sized])
144 ml = max([w for x, w in sized])
158 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
145 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
159
146
160 if pieces:
147 if pieces:
161 for p, l in zip(zip(*pieces), lines):
148 for p, l in zip(zip(*pieces), lines):
162 ui.write("%s: %s" % (" ".join(p), l[1]))
149 ui.write("%s: %s" % (" ".join(p), l[1]))
163
150
164 def archive(ui, repo, dest, **opts):
151 def archive(ui, repo, dest, **opts):
165 '''create an unversioned archive of a repository revision
152 '''create an unversioned archive of a repository revision
166
153
167 By default, the revision used is the parent of the working
154 By default, the revision used is the parent of the working
168 directory; use -r/--rev to specify a different revision.
155 directory; use -r/--rev to specify a different revision.
169
156
170 The archive type is automatically detected based on file
157 The archive type is automatically detected based on file
171 extension (or override using -t/--type).
158 extension (or override using -t/--type).
172
159
173 Valid types are:
160 Valid types are:
174
161
175 :``files``: a directory full of files (default)
162 :``files``: a directory full of files (default)
176 :``tar``: tar archive, uncompressed
163 :``tar``: tar archive, uncompressed
177 :``tbz2``: tar archive, compressed using bzip2
164 :``tbz2``: tar archive, compressed using bzip2
178 :``tgz``: tar archive, compressed using gzip
165 :``tgz``: tar archive, compressed using gzip
179 :``uzip``: zip archive, uncompressed
166 :``uzip``: zip archive, uncompressed
180 :``zip``: zip archive, compressed using deflate
167 :``zip``: zip archive, compressed using deflate
181
168
182 The exact name of the destination archive or directory is given
169 The exact name of the destination archive or directory is given
183 using a format string; see :hg:`help export` for details.
170 using a format string; see :hg:`help export` for details.
184
171
185 Each member added to an archive file has a directory prefix
172 Each member added to an archive file has a directory prefix
186 prepended. Use -p/--prefix to specify a format string for the
173 prepended. Use -p/--prefix to specify a format string for the
187 prefix. The default is the basename of the archive, with suffixes
174 prefix. The default is the basename of the archive, with suffixes
188 removed.
175 removed.
189
176
190 Returns 0 on success.
177 Returns 0 on success.
191 '''
178 '''
192
179
193 ctx = repo[opts.get('rev')]
180 ctx = repo[opts.get('rev')]
194 if not ctx:
181 if not ctx:
195 raise util.Abort(_('no working directory: please specify a revision'))
182 raise util.Abort(_('no working directory: please specify a revision'))
196 node = ctx.node()
183 node = ctx.node()
197 dest = cmdutil.make_filename(repo, dest, node)
184 dest = cmdutil.make_filename(repo, dest, node)
198 if os.path.realpath(dest) == repo.root:
185 if os.path.realpath(dest) == repo.root:
199 raise util.Abort(_('repository root cannot be destination'))
186 raise util.Abort(_('repository root cannot be destination'))
200
187
201 kind = opts.get('type') or archival.guesskind(dest) or 'files'
188 kind = opts.get('type') or archival.guesskind(dest) or 'files'
202 prefix = opts.get('prefix')
189 prefix = opts.get('prefix')
203
190
204 if dest == '-':
191 if dest == '-':
205 if kind == 'files':
192 if kind == 'files':
206 raise util.Abort(_('cannot archive plain files to stdout'))
193 raise util.Abort(_('cannot archive plain files to stdout'))
207 dest = sys.stdout
194 dest = sys.stdout
208 if not prefix:
195 if not prefix:
209 prefix = os.path.basename(repo.root) + '-%h'
196 prefix = os.path.basename(repo.root) + '-%h'
210
197
211 prefix = cmdutil.make_filename(repo, prefix, node)
198 prefix = cmdutil.make_filename(repo, prefix, node)
212 matchfn = cmdutil.match(repo, [], opts)
199 matchfn = cmdutil.match(repo, [], opts)
213 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
200 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
214 matchfn, prefix)
201 matchfn, prefix)
215
202
216 def backout(ui, repo, node=None, rev=None, **opts):
203 def backout(ui, repo, node=None, rev=None, **opts):
217 '''reverse effect of earlier changeset
204 '''reverse effect of earlier changeset
218
205
219 Commit the backed out changes as a new changeset. The new
206 Commit the backed out changes as a new changeset. The new
220 changeset is a child of the backed out changeset.
207 changeset is a child of the backed out changeset.
221
208
222 If you backout a changeset other than the tip, a new head is
209 If you backout a changeset other than the tip, a new head is
223 created. This head will be the new tip and you should merge this
210 created. This head will be the new tip and you should merge this
224 backout changeset with another head.
211 backout changeset with another head.
225
212
226 The --merge option remembers the parent of the working directory
213 The --merge option remembers the parent of the working directory
227 before starting the backout, then merges the new head with that
214 before starting the backout, then merges the new head with that
228 changeset afterwards. This saves you from doing the merge by hand.
215 changeset afterwards. This saves you from doing the merge by hand.
229 The result of this merge is not committed, as with a normal merge.
216 The result of this merge is not committed, as with a normal merge.
230
217
231 See :hg:`help dates` for a list of formats valid for -d/--date.
218 See :hg:`help dates` for a list of formats valid for -d/--date.
232
219
233 Returns 0 on success.
220 Returns 0 on success.
234 '''
221 '''
235 if rev and node:
222 if rev and node:
236 raise util.Abort(_("please specify just one revision"))
223 raise util.Abort(_("please specify just one revision"))
237
224
238 if not rev:
225 if not rev:
239 rev = node
226 rev = node
240
227
241 if not rev:
228 if not rev:
242 raise util.Abort(_("please specify a revision to backout"))
229 raise util.Abort(_("please specify a revision to backout"))
243
230
244 date = opts.get('date')
231 date = opts.get('date')
245 if date:
232 if date:
246 opts['date'] = util.parsedate(date)
233 opts['date'] = util.parsedate(date)
247
234
248 cmdutil.bail_if_changed(repo)
235 cmdutil.bail_if_changed(repo)
249 node = repo.lookup(rev)
236 node = repo.lookup(rev)
250
237
251 op1, op2 = repo.dirstate.parents()
238 op1, op2 = repo.dirstate.parents()
252 a = repo.changelog.ancestor(op1, node)
239 a = repo.changelog.ancestor(op1, node)
253 if a != node:
240 if a != node:
254 raise util.Abort(_('cannot backout change on a different branch'))
241 raise util.Abort(_('cannot backout change on a different branch'))
255
242
256 p1, p2 = repo.changelog.parents(node)
243 p1, p2 = repo.changelog.parents(node)
257 if p1 == nullid:
244 if p1 == nullid:
258 raise util.Abort(_('cannot backout a change with no parents'))
245 raise util.Abort(_('cannot backout a change with no parents'))
259 if p2 != nullid:
246 if p2 != nullid:
260 if not opts.get('parent'):
247 if not opts.get('parent'):
261 raise util.Abort(_('cannot backout a merge changeset without '
248 raise util.Abort(_('cannot backout a merge changeset without '
262 '--parent'))
249 '--parent'))
263 p = repo.lookup(opts['parent'])
250 p = repo.lookup(opts['parent'])
264 if p not in (p1, p2):
251 if p not in (p1, p2):
265 raise util.Abort(_('%s is not a parent of %s') %
252 raise util.Abort(_('%s is not a parent of %s') %
266 (short(p), short(node)))
253 (short(p), short(node)))
267 parent = p
254 parent = p
268 else:
255 else:
269 if opts.get('parent'):
256 if opts.get('parent'):
270 raise util.Abort(_('cannot use --parent on non-merge changeset'))
257 raise util.Abort(_('cannot use --parent on non-merge changeset'))
271 parent = p1
258 parent = p1
272
259
273 # the backout should appear on the same branch
260 # the backout should appear on the same branch
274 branch = repo.dirstate.branch()
261 branch = repo.dirstate.branch()
275 hg.clean(repo, node, show_stats=False)
262 hg.clean(repo, node, show_stats=False)
276 repo.dirstate.setbranch(branch)
263 repo.dirstate.setbranch(branch)
277 revert_opts = opts.copy()
264 revert_opts = opts.copy()
278 revert_opts['date'] = None
265 revert_opts['date'] = None
279 revert_opts['all'] = True
266 revert_opts['all'] = True
280 revert_opts['rev'] = hex(parent)
267 revert_opts['rev'] = hex(parent)
281 revert_opts['no_backup'] = None
268 revert_opts['no_backup'] = None
282 revert(ui, repo, **revert_opts)
269 revert(ui, repo, **revert_opts)
283 commit_opts = opts.copy()
270 commit_opts = opts.copy()
284 commit_opts['addremove'] = False
271 commit_opts['addremove'] = False
285 if not commit_opts['message'] and not commit_opts['logfile']:
272 if not commit_opts['message'] and not commit_opts['logfile']:
286 # we don't translate commit messages
273 # we don't translate commit messages
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
274 commit_opts['message'] = "Backed out changeset %s" % short(node)
288 commit_opts['force_editor'] = True
275 commit_opts['force_editor'] = True
289 commit(ui, repo, **commit_opts)
276 commit(ui, repo, **commit_opts)
290 def nice(node):
277 def nice(node):
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
278 return '%d:%s' % (repo.changelog.rev(node), short(node))
292 ui.status(_('changeset %s backs out changeset %s\n') %
279 ui.status(_('changeset %s backs out changeset %s\n') %
293 (nice(repo.changelog.tip()), nice(node)))
280 (nice(repo.changelog.tip()), nice(node)))
294 if op1 != node:
281 if op1 != node:
295 hg.clean(repo, op1, show_stats=False)
282 hg.clean(repo, op1, show_stats=False)
296 if opts.get('merge'):
283 if opts.get('merge'):
297 ui.status(_('merging with changeset %s\n')
284 ui.status(_('merging with changeset %s\n')
298 % nice(repo.changelog.tip()))
285 % nice(repo.changelog.tip()))
299 hg.merge(repo, hex(repo.changelog.tip()))
286 hg.merge(repo, hex(repo.changelog.tip()))
300 else:
287 else:
301 ui.status(_('the backout changeset is a new head - '
288 ui.status(_('the backout changeset is a new head - '
302 'do not forget to merge\n'))
289 'do not forget to merge\n'))
303 ui.status(_('(use "backout --merge" '
290 ui.status(_('(use "backout --merge" '
304 'if you want to auto-merge)\n'))
291 'if you want to auto-merge)\n'))
305
292
306 def bisect(ui, repo, rev=None, extra=None, command=None,
293 def bisect(ui, repo, rev=None, extra=None, command=None,
307 reset=None, good=None, bad=None, skip=None, noupdate=None):
294 reset=None, good=None, bad=None, skip=None, noupdate=None):
308 """subdivision search of changesets
295 """subdivision search of changesets
309
296
310 This command helps to find changesets which introduce problems. To
297 This command helps to find changesets which introduce problems. To
311 use, mark the earliest changeset you know exhibits the problem as
298 use, mark the earliest changeset you know exhibits the problem as
312 bad, then mark the latest changeset which is free from the problem
299 bad, then mark the latest changeset which is free from the problem
313 as good. Bisect will update your working directory to a revision
300 as good. Bisect will update your working directory to a revision
314 for testing (unless the -U/--noupdate option is specified). Once
301 for testing (unless the -U/--noupdate option is specified). Once
315 you have performed tests, mark the working directory as good or
302 you have performed tests, mark the working directory as good or
316 bad, and bisect will either update to another candidate changeset
303 bad, and bisect will either update to another candidate changeset
317 or announce that it has found the bad revision.
304 or announce that it has found the bad revision.
318
305
319 As a shortcut, you can also use the revision argument to mark a
306 As a shortcut, you can also use the revision argument to mark a
320 revision as good or bad without checking it out first.
307 revision as good or bad without checking it out first.
321
308
322 If you supply a command, it will be used for automatic bisection.
309 If you supply a command, it will be used for automatic bisection.
323 Its exit status will be used to mark revisions as good or bad:
310 Its exit status will be used to mark revisions as good or bad:
324 status 0 means good, 125 means to skip the revision, 127
311 status 0 means good, 125 means to skip the revision, 127
325 (command not found) will abort the bisection, and any other
312 (command not found) will abort the bisection, and any other
326 non-zero exit status means the revision is bad.
313 non-zero exit status means the revision is bad.
327
314
328 Returns 0 on success.
315 Returns 0 on success.
329 """
316 """
330 def print_result(nodes, good):
317 def print_result(nodes, good):
331 displayer = cmdutil.show_changeset(ui, repo, {})
318 displayer = cmdutil.show_changeset(ui, repo, {})
332 if len(nodes) == 1:
319 if len(nodes) == 1:
333 # narrowed it down to a single revision
320 # narrowed it down to a single revision
334 if good:
321 if good:
335 ui.write(_("The first good revision is:\n"))
322 ui.write(_("The first good revision is:\n"))
336 else:
323 else:
337 ui.write(_("The first bad revision is:\n"))
324 ui.write(_("The first bad revision is:\n"))
338 displayer.show(repo[nodes[0]])
325 displayer.show(repo[nodes[0]])
339 parents = repo[nodes[0]].parents()
326 parents = repo[nodes[0]].parents()
340 if len(parents) > 1:
327 if len(parents) > 1:
341 side = good and state['bad'] or state['good']
328 side = good and state['bad'] or state['good']
342 num = len(set(i.node() for i in parents) & set(side))
329 num = len(set(i.node() for i in parents) & set(side))
343 if num == 1:
330 if num == 1:
344 common = parents[0].ancestor(parents[1])
331 common = parents[0].ancestor(parents[1])
345 ui.write(_('Not all ancestors of this changeset have been'
332 ui.write(_('Not all ancestors of this changeset have been'
346 ' checked.\nTo check the other ancestors, start'
333 ' checked.\nTo check the other ancestors, start'
347 ' from the common ancestor, %s.\n' % common))
334 ' from the common ancestor, %s.\n' % common))
348 else:
335 else:
349 # multiple possible revisions
336 # multiple possible revisions
350 if good:
337 if good:
351 ui.write(_("Due to skipped revisions, the first "
338 ui.write(_("Due to skipped revisions, the first "
352 "good revision could be any of:\n"))
339 "good revision could be any of:\n"))
353 else:
340 else:
354 ui.write(_("Due to skipped revisions, the first "
341 ui.write(_("Due to skipped revisions, the first "
355 "bad revision could be any of:\n"))
342 "bad revision could be any of:\n"))
356 for n in nodes:
343 for n in nodes:
357 displayer.show(repo[n])
344 displayer.show(repo[n])
358 displayer.close()
345 displayer.close()
359
346
360 def check_state(state, interactive=True):
347 def check_state(state, interactive=True):
361 if not state['good'] or not state['bad']:
348 if not state['good'] or not state['bad']:
362 if (good or bad or skip or reset) and interactive:
349 if (good or bad or skip or reset) and interactive:
363 return
350 return
364 if not state['good']:
351 if not state['good']:
365 raise util.Abort(_('cannot bisect (no known good revisions)'))
352 raise util.Abort(_('cannot bisect (no known good revisions)'))
366 else:
353 else:
367 raise util.Abort(_('cannot bisect (no known bad revisions)'))
354 raise util.Abort(_('cannot bisect (no known bad revisions)'))
368 return True
355 return True
369
356
370 # backward compatibility
357 # backward compatibility
371 if rev in "good bad reset init".split():
358 if rev in "good bad reset init".split():
372 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
359 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
373 cmd, rev, extra = rev, extra, None
360 cmd, rev, extra = rev, extra, None
374 if cmd == "good":
361 if cmd == "good":
375 good = True
362 good = True
376 elif cmd == "bad":
363 elif cmd == "bad":
377 bad = True
364 bad = True
378 else:
365 else:
379 reset = True
366 reset = True
380 elif extra or good + bad + skip + reset + bool(command) > 1:
367 elif extra or good + bad + skip + reset + bool(command) > 1:
381 raise util.Abort(_('incompatible arguments'))
368 raise util.Abort(_('incompatible arguments'))
382
369
383 if reset:
370 if reset:
384 p = repo.join("bisect.state")
371 p = repo.join("bisect.state")
385 if os.path.exists(p):
372 if os.path.exists(p):
386 os.unlink(p)
373 os.unlink(p)
387 return
374 return
388
375
389 state = hbisect.load_state(repo)
376 state = hbisect.load_state(repo)
390
377
391 if command:
378 if command:
392 changesets = 1
379 changesets = 1
393 try:
380 try:
394 while changesets:
381 while changesets:
395 # update state
382 # update state
396 status = util.system(command)
383 status = util.system(command)
397 if status == 125:
384 if status == 125:
398 transition = "skip"
385 transition = "skip"
399 elif status == 0:
386 elif status == 0:
400 transition = "good"
387 transition = "good"
401 # status < 0 means process was killed
388 # status < 0 means process was killed
402 elif status == 127:
389 elif status == 127:
403 raise util.Abort(_("failed to execute %s") % command)
390 raise util.Abort(_("failed to execute %s") % command)
404 elif status < 0:
391 elif status < 0:
405 raise util.Abort(_("%s killed") % command)
392 raise util.Abort(_("%s killed") % command)
406 else:
393 else:
407 transition = "bad"
394 transition = "bad"
408 ctx = repo[rev or '.']
395 ctx = repo[rev or '.']
409 state[transition].append(ctx.node())
396 state[transition].append(ctx.node())
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
397 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
411 check_state(state, interactive=False)
398 check_state(state, interactive=False)
412 # bisect
399 # bisect
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
400 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
414 # update to next check
401 # update to next check
415 cmdutil.bail_if_changed(repo)
402 cmdutil.bail_if_changed(repo)
416 hg.clean(repo, nodes[0], show_stats=False)
403 hg.clean(repo, nodes[0], show_stats=False)
417 finally:
404 finally:
418 hbisect.save_state(repo, state)
405 hbisect.save_state(repo, state)
419 print_result(nodes, good)
406 print_result(nodes, good)
420 return
407 return
421
408
422 # update state
409 # update state
423
410
424 if rev:
411 if rev:
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
412 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
426 else:
413 else:
427 nodes = [repo.lookup('.')]
414 nodes = [repo.lookup('.')]
428
415
429 if good or bad or skip:
416 if good or bad or skip:
430 if good:
417 if good:
431 state['good'] += nodes
418 state['good'] += nodes
432 elif bad:
419 elif bad:
433 state['bad'] += nodes
420 state['bad'] += nodes
434 elif skip:
421 elif skip:
435 state['skip'] += nodes
422 state['skip'] += nodes
436 hbisect.save_state(repo, state)
423 hbisect.save_state(repo, state)
437
424
438 if not check_state(state):
425 if not check_state(state):
439 return
426 return
440
427
441 # actually bisect
428 # actually bisect
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
429 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
443 if changesets == 0:
430 if changesets == 0:
444 print_result(nodes, good)
431 print_result(nodes, good)
445 else:
432 else:
446 assert len(nodes) == 1 # only a single node can be tested next
433 assert len(nodes) == 1 # only a single node can be tested next
447 node = nodes[0]
434 node = nodes[0]
448 # compute the approximate number of remaining tests
435 # compute the approximate number of remaining tests
449 tests, size = 0, 2
436 tests, size = 0, 2
450 while size <= changesets:
437 while size <= changesets:
451 tests, size = tests + 1, size * 2
438 tests, size = tests + 1, size * 2
452 rev = repo.changelog.rev(node)
439 rev = repo.changelog.rev(node)
453 ui.write(_("Testing changeset %d:%s "
440 ui.write(_("Testing changeset %d:%s "
454 "(%d changesets remaining, ~%d tests)\n")
441 "(%d changesets remaining, ~%d tests)\n")
455 % (rev, short(node), changesets, tests))
442 % (rev, short(node), changesets, tests))
456 if not noupdate:
443 if not noupdate:
457 cmdutil.bail_if_changed(repo)
444 cmdutil.bail_if_changed(repo)
458 return hg.clean(repo, node)
445 return hg.clean(repo, node)
459
446
460 def branch(ui, repo, label=None, **opts):
447 def branch(ui, repo, label=None, **opts):
461 """set or show the current branch name
448 """set or show the current branch name
462
449
463 With no argument, show the current branch name. With one argument,
450 With no argument, show the current branch name. With one argument,
464 set the working directory branch name (the branch will not exist
451 set the working directory branch name (the branch will not exist
465 in the repository until the next commit). Standard practice
452 in the repository until the next commit). Standard practice
466 recommends that primary development take place on the 'default'
453 recommends that primary development take place on the 'default'
467 branch.
454 branch.
468
455
469 Unless -f/--force is specified, branch will not let you set a
456 Unless -f/--force is specified, branch will not let you set a
470 branch name that already exists, even if it's inactive.
457 branch name that already exists, even if it's inactive.
471
458
472 Use -C/--clean to reset the working directory branch to that of
459 Use -C/--clean to reset the working directory branch to that of
473 the parent of the working directory, negating a previous branch
460 the parent of the working directory, negating a previous branch
474 change.
461 change.
475
462
476 Use the command :hg:`update` to switch to an existing branch. Use
463 Use the command :hg:`update` to switch to an existing branch. Use
477 :hg:`commit --close-branch` to mark this branch as closed.
464 :hg:`commit --close-branch` to mark this branch as closed.
478
465
479 Returns 0 on success.
466 Returns 0 on success.
480 """
467 """
481
468
482 if opts.get('clean'):
469 if opts.get('clean'):
483 label = repo[None].parents()[0].branch()
470 label = repo[None].parents()[0].branch()
484 repo.dirstate.setbranch(label)
471 repo.dirstate.setbranch(label)
485 ui.status(_('reset working directory to branch %s\n') % label)
472 ui.status(_('reset working directory to branch %s\n') % label)
486 elif label:
473 elif label:
487 utflabel = encoding.fromlocal(label)
474 utflabel = encoding.fromlocal(label)
488 if not opts.get('force') and utflabel in repo.branchtags():
475 if not opts.get('force') and utflabel in repo.branchtags():
489 if label not in [p.branch() for p in repo.parents()]:
476 if label not in [p.branch() for p in repo.parents()]:
490 raise util.Abort(_('a branch of the same name already exists'
477 raise util.Abort(_('a branch of the same name already exists'
491 " (use 'hg update' to switch to it)"))
478 " (use 'hg update' to switch to it)"))
492 repo.dirstate.setbranch(utflabel)
479 repo.dirstate.setbranch(utflabel)
493 ui.status(_('marked working directory as branch %s\n') % label)
480 ui.status(_('marked working directory as branch %s\n') % label)
494 else:
481 else:
495 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
482 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
496
483
497 def branches(ui, repo, active=False, closed=False):
484 def branches(ui, repo, active=False, closed=False):
498 """list repository named branches
485 """list repository named branches
499
486
500 List the repository's named branches, indicating which ones are
487 List the repository's named branches, indicating which ones are
501 inactive. If -c/--closed is specified, also list branches which have
488 inactive. If -c/--closed is specified, also list branches which have
502 been marked closed (see :hg:`commit --close-branch`).
489 been marked closed (see :hg:`commit --close-branch`).
503
490
504 If -a/--active is specified, only show active branches. A branch
491 If -a/--active is specified, only show active branches. A branch
505 is considered active if it contains repository heads.
492 is considered active if it contains repository heads.
506
493
507 Use the command :hg:`update` to switch to an existing branch.
494 Use the command :hg:`update` to switch to an existing branch.
508
495
509 Returns 0.
496 Returns 0.
510 """
497 """
511
498
512 hexfunc = ui.debugflag and hex or short
499 hexfunc = ui.debugflag and hex or short
513 activebranches = [repo[n].branch() for n in repo.heads()]
500 activebranches = [repo[n].branch() for n in repo.heads()]
514 def testactive(tag, node):
501 def testactive(tag, node):
515 realhead = tag in activebranches
502 realhead = tag in activebranches
516 open = node in repo.branchheads(tag, closed=False)
503 open = node in repo.branchheads(tag, closed=False)
517 return realhead and open
504 return realhead and open
518 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
505 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
519 for tag, node in repo.branchtags().items()],
506 for tag, node in repo.branchtags().items()],
520 reverse=True)
507 reverse=True)
521
508
522 for isactive, node, tag in branches:
509 for isactive, node, tag in branches:
523 if (not active) or isactive:
510 if (not active) or isactive:
524 encodedtag = encoding.tolocal(tag)
511 encodedtag = encoding.tolocal(tag)
525 if ui.quiet:
512 if ui.quiet:
526 ui.write("%s\n" % encodedtag)
513 ui.write("%s\n" % encodedtag)
527 else:
514 else:
528 hn = repo.lookup(node)
515 hn = repo.lookup(node)
529 if isactive:
516 if isactive:
530 label = 'branches.active'
517 label = 'branches.active'
531 notice = ''
518 notice = ''
532 elif hn not in repo.branchheads(tag, closed=False):
519 elif hn not in repo.branchheads(tag, closed=False):
533 if not closed:
520 if not closed:
534 continue
521 continue
535 label = 'branches.closed'
522 label = 'branches.closed'
536 notice = _(' (closed)')
523 notice = _(' (closed)')
537 else:
524 else:
538 label = 'branches.inactive'
525 label = 'branches.inactive'
539 notice = _(' (inactive)')
526 notice = _(' (inactive)')
540 if tag == repo.dirstate.branch():
527 if tag == repo.dirstate.branch():
541 label = 'branches.current'
528 label = 'branches.current'
542 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
529 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
543 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
530 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
544 encodedtag = ui.label(encodedtag, label)
531 encodedtag = ui.label(encodedtag, label)
545 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
532 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
546
533
547 def bundle(ui, repo, fname, dest=None, **opts):
534 def bundle(ui, repo, fname, dest=None, **opts):
548 """create a changegroup file
535 """create a changegroup file
549
536
550 Generate a compressed changegroup file collecting changesets not
537 Generate a compressed changegroup file collecting changesets not
551 known to be in another repository.
538 known to be in another repository.
552
539
553 If you omit the destination repository, then hg assumes the
540 If you omit the destination repository, then hg assumes the
554 destination will have all the nodes you specify with --base
541 destination will have all the nodes you specify with --base
555 parameters. To create a bundle containing all changesets, use
542 parameters. To create a bundle containing all changesets, use
556 -a/--all (or --base null).
543 -a/--all (or --base null).
557
544
558 You can change compression method with the -t/--type option.
545 You can change compression method with the -t/--type option.
559 The available compression methods are: none, bzip2, and
546 The available compression methods are: none, bzip2, and
560 gzip (by default, bundles are compressed using bzip2).
547 gzip (by default, bundles are compressed using bzip2).
561
548
562 The bundle file can then be transferred using conventional means
549 The bundle file can then be transferred using conventional means
563 and applied to another repository with the unbundle or pull
550 and applied to another repository with the unbundle or pull
564 command. This is useful when direct push and pull are not
551 command. This is useful when direct push and pull are not
565 available or when exporting an entire repository is undesirable.
552 available or when exporting an entire repository is undesirable.
566
553
567 Applying bundles preserves all changeset contents including
554 Applying bundles preserves all changeset contents including
568 permissions, copy/rename information, and revision history.
555 permissions, copy/rename information, and revision history.
569
556
570 Returns 0 on success, 1 if no changes found.
557 Returns 0 on success, 1 if no changes found.
571 """
558 """
572 revs = opts.get('rev') or None
559 revs = opts.get('rev') or None
573 if opts.get('all'):
560 if opts.get('all'):
574 base = ['null']
561 base = ['null']
575 else:
562 else:
576 base = opts.get('base')
563 base = opts.get('base')
577 if base:
564 if base:
578 if dest:
565 if dest:
579 raise util.Abort(_("--base is incompatible with specifying "
566 raise util.Abort(_("--base is incompatible with specifying "
580 "a destination"))
567 "a destination"))
581 base = [repo.lookup(rev) for rev in base]
568 base = [repo.lookup(rev) for rev in base]
582 # create the right base
569 # create the right base
583 # XXX: nodesbetween / changegroup* should be "fixed" instead
570 # XXX: nodesbetween / changegroup* should be "fixed" instead
584 o = []
571 o = []
585 has = set((nullid,))
572 has = set((nullid,))
586 for n in base:
573 for n in base:
587 has.update(repo.changelog.reachable(n))
574 has.update(repo.changelog.reachable(n))
588 if revs:
575 if revs:
589 revs = [repo.lookup(rev) for rev in revs]
576 revs = [repo.lookup(rev) for rev in revs]
590 visit = revs[:]
577 visit = revs[:]
591 has.difference_update(visit)
578 has.difference_update(visit)
592 else:
579 else:
593 visit = repo.changelog.heads()
580 visit = repo.changelog.heads()
594 seen = {}
581 seen = {}
595 while visit:
582 while visit:
596 n = visit.pop(0)
583 n = visit.pop(0)
597 parents = [p for p in repo.changelog.parents(n) if p not in has]
584 parents = [p for p in repo.changelog.parents(n) if p not in has]
598 if len(parents) == 0:
585 if len(parents) == 0:
599 if n not in has:
586 if n not in has:
600 o.append(n)
587 o.append(n)
601 else:
588 else:
602 for p in parents:
589 for p in parents:
603 if p not in seen:
590 if p not in seen:
604 seen[p] = 1
591 seen[p] = 1
605 visit.append(p)
592 visit.append(p)
606 else:
593 else:
607 dest = ui.expandpath(dest or 'default-push', dest or 'default')
594 dest = ui.expandpath(dest or 'default-push', dest or 'default')
608 dest, branches = hg.parseurl(dest, opts.get('branch'))
595 dest, branches = hg.parseurl(dest, opts.get('branch'))
609 other = hg.repository(hg.remoteui(repo, opts), dest)
596 other = hg.repository(hg.remoteui(repo, opts), dest)
610 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
597 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
611 if revs:
598 if revs:
612 revs = [repo.lookup(rev) for rev in revs]
599 revs = [repo.lookup(rev) for rev in revs]
613 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
600 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
614
601
615 if not o:
602 if not o:
616 ui.status(_("no changes found\n"))
603 ui.status(_("no changes found\n"))
617 return 1
604 return 1
618
605
619 if revs:
606 if revs:
620 cg = repo.changegroupsubset(o, revs, 'bundle')
607 cg = repo.changegroupsubset(o, revs, 'bundle')
621 else:
608 else:
622 cg = repo.changegroup(o, 'bundle')
609 cg = repo.changegroup(o, 'bundle')
623
610
624 bundletype = opts.get('type', 'bzip2').lower()
611 bundletype = opts.get('type', 'bzip2').lower()
625 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
612 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
626 bundletype = btypes.get(bundletype)
613 bundletype = btypes.get(bundletype)
627 if bundletype not in changegroup.bundletypes:
614 if bundletype not in changegroup.bundletypes:
628 raise util.Abort(_('unknown bundle type specified with --type'))
615 raise util.Abort(_('unknown bundle type specified with --type'))
629
616
630 changegroup.writebundle(cg, fname, bundletype)
617 changegroup.writebundle(cg, fname, bundletype)
631
618
632 def cat(ui, repo, file1, *pats, **opts):
619 def cat(ui, repo, file1, *pats, **opts):
633 """output the current or given revision of files
620 """output the current or given revision of files
634
621
635 Print the specified files as they were at the given revision. If
622 Print the specified files as they were at the given revision. If
636 no revision is given, the parent of the working directory is used,
623 no revision is given, the parent of the working directory is used,
637 or tip if no revision is checked out.
624 or tip if no revision is checked out.
638
625
639 Output may be to a file, in which case the name of the file is
626 Output may be to a file, in which case the name of the file is
640 given using a format string. The formatting rules are the same as
627 given using a format string. The formatting rules are the same as
641 for the export command, with the following additions:
628 for the export command, with the following additions:
642
629
643 :``%s``: basename of file being printed
630 :``%s``: basename of file being printed
644 :``%d``: dirname of file being printed, or '.' if in repository root
631 :``%d``: dirname of file being printed, or '.' if in repository root
645 :``%p``: root-relative path name of file being printed
632 :``%p``: root-relative path name of file being printed
646
633
647 Returns 0 on success.
634 Returns 0 on success.
648 """
635 """
649 ctx = repo[opts.get('rev')]
636 ctx = repo[opts.get('rev')]
650 err = 1
637 err = 1
651 m = cmdutil.match(repo, (file1,) + pats, opts)
638 m = cmdutil.match(repo, (file1,) + pats, opts)
652 for abs in ctx.walk(m):
639 for abs in ctx.walk(m):
653 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
640 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
654 data = ctx[abs].data()
641 data = ctx[abs].data()
655 if opts.get('decode'):
642 if opts.get('decode'):
656 data = repo.wwritedata(abs, data)
643 data = repo.wwritedata(abs, data)
657 fp.write(data)
644 fp.write(data)
658 err = 0
645 err = 0
659 return err
646 return err
660
647
661 def clone(ui, source, dest=None, **opts):
648 def clone(ui, source, dest=None, **opts):
662 """make a copy of an existing repository
649 """make a copy of an existing repository
663
650
664 Create a copy of an existing repository in a new directory.
651 Create a copy of an existing repository in a new directory.
665
652
666 If no destination directory name is specified, it defaults to the
653 If no destination directory name is specified, it defaults to the
667 basename of the source.
654 basename of the source.
668
655
669 The location of the source is added to the new repository's
656 The location of the source is added to the new repository's
670 .hg/hgrc file, as the default to be used for future pulls.
657 .hg/hgrc file, as the default to be used for future pulls.
671
658
672 See :hg:`help urls` for valid source format details.
659 See :hg:`help urls` for valid source format details.
673
660
674 It is possible to specify an ``ssh://`` URL as the destination, but no
661 It is possible to specify an ``ssh://`` URL as the destination, but no
675 .hg/hgrc and working directory will be created on the remote side.
662 .hg/hgrc and working directory will be created on the remote side.
676 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
663 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
677
664
678 A set of changesets (tags, or branch names) to pull may be specified
665 A set of changesets (tags, or branch names) to pull may be specified
679 by listing each changeset (tag, or branch name) with -r/--rev.
666 by listing each changeset (tag, or branch name) with -r/--rev.
680 If -r/--rev is used, the cloned repository will contain only a subset
667 If -r/--rev is used, the cloned repository will contain only a subset
681 of the changesets of the source repository. Only the set of changesets
668 of the changesets of the source repository. Only the set of changesets
682 defined by all -r/--rev options (including all their ancestors)
669 defined by all -r/--rev options (including all their ancestors)
683 will be pulled into the destination repository.
670 will be pulled into the destination repository.
684 No subsequent changesets (including subsequent tags) will be present
671 No subsequent changesets (including subsequent tags) will be present
685 in the destination.
672 in the destination.
686
673
687 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
674 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
688 local source repositories.
675 local source repositories.
689
676
690 For efficiency, hardlinks are used for cloning whenever the source
677 For efficiency, hardlinks are used for cloning whenever the source
691 and destination are on the same filesystem (note this applies only
678 and destination are on the same filesystem (note this applies only
692 to the repository data, not to the working directory). Some
679 to the repository data, not to the working directory). Some
693 filesystems, such as AFS, implement hardlinking incorrectly, but
680 filesystems, such as AFS, implement hardlinking incorrectly, but
694 do not report errors. In these cases, use the --pull option to
681 do not report errors. In these cases, use the --pull option to
695 avoid hardlinking.
682 avoid hardlinking.
696
683
697 In some cases, you can clone repositories and the working directory
684 In some cases, you can clone repositories and the working directory
698 using full hardlinks with ::
685 using full hardlinks with ::
699
686
700 $ cp -al REPO REPOCLONE
687 $ cp -al REPO REPOCLONE
701
688
702 This is the fastest way to clone, but it is not always safe. The
689 This is the fastest way to clone, but it is not always safe. The
703 operation is not atomic (making sure REPO is not modified during
690 operation is not atomic (making sure REPO is not modified during
704 the operation is up to you) and you have to make sure your editor
691 the operation is up to you) and you have to make sure your editor
705 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
692 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
706 this is not compatible with certain extensions that place their
693 this is not compatible with certain extensions that place their
707 metadata under the .hg directory, such as mq.
694 metadata under the .hg directory, such as mq.
708
695
709 Mercurial will update the working directory to the first applicable
696 Mercurial will update the working directory to the first applicable
710 revision from this list:
697 revision from this list:
711
698
712 a) null if -U or the source repository has no changesets
699 a) null if -U or the source repository has no changesets
713 b) if -u . and the source repository is local, the first parent of
700 b) if -u . and the source repository is local, the first parent of
714 the source repository's working directory
701 the source repository's working directory
715 c) the changeset specified with -u (if a branch name, this means the
702 c) the changeset specified with -u (if a branch name, this means the
716 latest head of that branch)
703 latest head of that branch)
717 d) the changeset specified with -r
704 d) the changeset specified with -r
718 e) the tipmost head specified with -b
705 e) the tipmost head specified with -b
719 f) the tipmost head specified with the url#branch source syntax
706 f) the tipmost head specified with the url#branch source syntax
720 g) the tipmost head of the default branch
707 g) the tipmost head of the default branch
721 h) tip
708 h) tip
722
709
723 Returns 0 on success.
710 Returns 0 on success.
724 """
711 """
725 if opts.get('noupdate') and opts.get('updaterev'):
712 if opts.get('noupdate') and opts.get('updaterev'):
726 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
713 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
727
714
728 r = hg.clone(hg.remoteui(ui, opts), source, dest,
715 r = hg.clone(hg.remoteui(ui, opts), source, dest,
729 pull=opts.get('pull'),
716 pull=opts.get('pull'),
730 stream=opts.get('uncompressed'),
717 stream=opts.get('uncompressed'),
731 rev=opts.get('rev'),
718 rev=opts.get('rev'),
732 update=opts.get('updaterev') or not opts.get('noupdate'),
719 update=opts.get('updaterev') or not opts.get('noupdate'),
733 branch=opts.get('branch'))
720 branch=opts.get('branch'))
734
721
735 return r is None
722 return r is None
736
723
737 def commit(ui, repo, *pats, **opts):
724 def commit(ui, repo, *pats, **opts):
738 """commit the specified files or all outstanding changes
725 """commit the specified files or all outstanding changes
739
726
740 Commit changes to the given files into the repository. Unlike a
727 Commit changes to the given files into the repository. Unlike a
741 centralized RCS, this operation is a local operation. See
728 centralized RCS, this operation is a local operation. See
742 :hg:`push` for a way to actively distribute your changes.
729 :hg:`push` for a way to actively distribute your changes.
743
730
744 If a list of files is omitted, all changes reported by :hg:`status`
731 If a list of files is omitted, all changes reported by :hg:`status`
745 will be committed.
732 will be committed.
746
733
747 If you are committing the result of a merge, do not provide any
734 If you are committing the result of a merge, do not provide any
748 filenames or -I/-X filters.
735 filenames or -I/-X filters.
749
736
750 If no commit message is specified, Mercurial starts your
737 If no commit message is specified, Mercurial starts your
751 configured editor where you can enter a message. In case your
738 configured editor where you can enter a message. In case your
752 commit fails, you will find a backup of your message in
739 commit fails, you will find a backup of your message in
753 ``.hg/last-message.txt``.
740 ``.hg/last-message.txt``.
754
741
755 See :hg:`help dates` for a list of formats valid for -d/--date.
742 See :hg:`help dates` for a list of formats valid for -d/--date.
756
743
757 Returns 0 on success, 1 if nothing changed.
744 Returns 0 on success, 1 if nothing changed.
758 """
745 """
759 extra = {}
746 extra = {}
760 if opts.get('close_branch'):
747 if opts.get('close_branch'):
761 if repo['.'].node() not in repo.branchheads():
748 if repo['.'].node() not in repo.branchheads():
762 # The topo heads set is included in the branch heads set of the
749 # The topo heads set is included in the branch heads set of the
763 # current branch, so it's sufficient to test branchheads
750 # current branch, so it's sufficient to test branchheads
764 raise util.Abort(_('can only close branch heads'))
751 raise util.Abort(_('can only close branch heads'))
765 extra['close'] = 1
752 extra['close'] = 1
766 e = cmdutil.commiteditor
753 e = cmdutil.commiteditor
767 if opts.get('force_editor'):
754 if opts.get('force_editor'):
768 e = cmdutil.commitforceeditor
755 e = cmdutil.commitforceeditor
769
756
770 def commitfunc(ui, repo, message, match, opts):
757 def commitfunc(ui, repo, message, match, opts):
771 return repo.commit(message, opts.get('user'), opts.get('date'), match,
758 return repo.commit(message, opts.get('user'), opts.get('date'), match,
772 editor=e, extra=extra)
759 editor=e, extra=extra)
773
760
774 branch = repo[None].branch()
761 branch = repo[None].branch()
775 bheads = repo.branchheads(branch)
762 bheads = repo.branchheads(branch)
776
763
777 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
764 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
778 if not node:
765 if not node:
779 ui.status(_("nothing changed\n"))
766 ui.status(_("nothing changed\n"))
780 return 1
767 return 1
781
768
782 ctx = repo[node]
769 ctx = repo[node]
783 parents = ctx.parents()
770 parents = ctx.parents()
784
771
785 if bheads and not [x for x in parents
772 if bheads and not [x for x in parents
786 if x.node() in bheads and x.branch() == branch]:
773 if x.node() in bheads and x.branch() == branch]:
787 ui.status(_('created new head\n'))
774 ui.status(_('created new head\n'))
788 # The message is not printed for initial roots. For the other
775 # The message is not printed for initial roots. For the other
789 # changesets, it is printed in the following situations:
776 # changesets, it is printed in the following situations:
790 #
777 #
791 # Par column: for the 2 parents with ...
778 # Par column: for the 2 parents with ...
792 # N: null or no parent
779 # N: null or no parent
793 # B: parent is on another named branch
780 # B: parent is on another named branch
794 # C: parent is a regular non head changeset
781 # C: parent is a regular non head changeset
795 # H: parent was a branch head of the current branch
782 # H: parent was a branch head of the current branch
796 # Msg column: whether we print "created new head" message
783 # Msg column: whether we print "created new head" message
797 # In the following, it is assumed that there already exists some
784 # In the following, it is assumed that there already exists some
798 # initial branch heads of the current branch, otherwise nothing is
785 # initial branch heads of the current branch, otherwise nothing is
799 # printed anyway.
786 # printed anyway.
800 #
787 #
801 # Par Msg Comment
788 # Par Msg Comment
802 # NN y additional topo root
789 # NN y additional topo root
803 #
790 #
804 # BN y additional branch root
791 # BN y additional branch root
805 # CN y additional topo head
792 # CN y additional topo head
806 # HN n usual case
793 # HN n usual case
807 #
794 #
808 # BB y weird additional branch root
795 # BB y weird additional branch root
809 # CB y branch merge
796 # CB y branch merge
810 # HB n merge with named branch
797 # HB n merge with named branch
811 #
798 #
812 # CC y additional head from merge
799 # CC y additional head from merge
813 # CH n merge with a head
800 # CH n merge with a head
814 #
801 #
815 # HH n head merge: head count decreases
802 # HH n head merge: head count decreases
816
803
817 if not opts.get('close_branch'):
804 if not opts.get('close_branch'):
818 for r in parents:
805 for r in parents:
819 if r.extra().get('close') and r.branch() == branch:
806 if r.extra().get('close') and r.branch() == branch:
820 ui.status(_('reopening closed branch head %d\n') % r)
807 ui.status(_('reopening closed branch head %d\n') % r)
821
808
822 if ui.debugflag:
809 if ui.debugflag:
823 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
810 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
824 elif ui.verbose:
811 elif ui.verbose:
825 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
812 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
826
813
827 def copy(ui, repo, *pats, **opts):
814 def copy(ui, repo, *pats, **opts):
828 """mark files as copied for the next commit
815 """mark files as copied for the next commit
829
816
830 Mark dest as having copies of source files. If dest is a
817 Mark dest as having copies of source files. If dest is a
831 directory, copies are put in that directory. If dest is a file,
818 directory, copies are put in that directory. If dest is a file,
832 the source must be a single file.
819 the source must be a single file.
833
820
834 By default, this command copies the contents of files as they
821 By default, this command copies the contents of files as they
835 exist in the working directory. If invoked with -A/--after, the
822 exist in the working directory. If invoked with -A/--after, the
836 operation is recorded, but no copying is performed.
823 operation is recorded, but no copying is performed.
837
824
838 This command takes effect with the next commit. To undo a copy
825 This command takes effect with the next commit. To undo a copy
839 before that, see :hg:`revert`.
826 before that, see :hg:`revert`.
840
827
841 Returns 0 on success, 1 if errors are encountered.
828 Returns 0 on success, 1 if errors are encountered.
842 """
829 """
843 wlock = repo.wlock(False)
830 wlock = repo.wlock(False)
844 try:
831 try:
845 return cmdutil.copy(ui, repo, pats, opts)
832 return cmdutil.copy(ui, repo, pats, opts)
846 finally:
833 finally:
847 wlock.release()
834 wlock.release()
848
835
849 def debugancestor(ui, repo, *args):
836 def debugancestor(ui, repo, *args):
850 """find the ancestor revision of two revisions in a given index"""
837 """find the ancestor revision of two revisions in a given index"""
851 if len(args) == 3:
838 if len(args) == 3:
852 index, rev1, rev2 = args
839 index, rev1, rev2 = args
853 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
840 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
854 lookup = r.lookup
841 lookup = r.lookup
855 elif len(args) == 2:
842 elif len(args) == 2:
856 if not repo:
843 if not repo:
857 raise util.Abort(_("there is no Mercurial repository here "
844 raise util.Abort(_("there is no Mercurial repository here "
858 "(.hg not found)"))
845 "(.hg not found)"))
859 rev1, rev2 = args
846 rev1, rev2 = args
860 r = repo.changelog
847 r = repo.changelog
861 lookup = repo.lookup
848 lookup = repo.lookup
862 else:
849 else:
863 raise util.Abort(_('either two or three arguments required'))
850 raise util.Abort(_('either two or three arguments required'))
864 a = r.ancestor(lookup(rev1), lookup(rev2))
851 a = r.ancestor(lookup(rev1), lookup(rev2))
865 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
852 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
866
853
867 def debugbuilddag(ui, repo, text,
854 def debugbuilddag(ui, repo, text,
868 mergeable_file=False,
855 mergeable_file=False,
869 appended_file=False,
856 appended_file=False,
870 overwritten_file=False,
857 overwritten_file=False,
871 new_file=False):
858 new_file=False):
872 """builds a repo with a given dag from scratch in the current empty repo
859 """builds a repo with a given dag from scratch in the current empty repo
873
860
874 Elements:
861 Elements:
875
862
876 - "+n" is a linear run of n nodes based on the current default parent
863 - "+n" is a linear run of n nodes based on the current default parent
877 - "." is a single node based on the current default parent
864 - "." is a single node based on the current default parent
878 - "$" resets the default parent to null (implied at the start);
865 - "$" resets the default parent to null (implied at the start);
879 otherwise the default parent is always the last node created
866 otherwise the default parent is always the last node created
880 - "<p" sets the default parent to the backref p
867 - "<p" sets the default parent to the backref p
881 - "*p" is a fork at parent p, which is a backref
868 - "*p" is a fork at parent p, which is a backref
882 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
869 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
883 - "/p2" is a merge of the preceding node and p2
870 - "/p2" is a merge of the preceding node and p2
884 - ":tag" defines a local tag for the preceding node
871 - ":tag" defines a local tag for the preceding node
885 - "@branch" sets the named branch for subsequent nodes
872 - "@branch" sets the named branch for subsequent nodes
886 - "!command" runs the command using your shell
873 - "!command" runs the command using your shell
887 - "!!my command\\n" is like "!", but to the end of the line
874 - "!!my command\\n" is like "!", but to the end of the line
888 - "#...\\n" is a comment up to the end of the line
875 - "#...\\n" is a comment up to the end of the line
889
876
890 Whitespace between the above elements is ignored.
877 Whitespace between the above elements is ignored.
891
878
892 A backref is either
879 A backref is either
893
880
894 - a number n, which references the node curr-n, where curr is the current
881 - a number n, which references the node curr-n, where curr is the current
895 node, or
882 node, or
896 - the name of a local tag you placed earlier using ":tag", or
883 - the name of a local tag you placed earlier using ":tag", or
897 - empty to denote the default parent.
884 - empty to denote the default parent.
898
885
899 All string valued-elements are either strictly alphanumeric, or must
886 All string valued-elements are either strictly alphanumeric, or must
900 be enclosed in double quotes ("..."), with "\\" as escape character.
887 be enclosed in double quotes ("..."), with "\\" as escape character.
901
888
902 Note that the --overwritten-file and --appended-file options imply the
889 Note that the --overwritten-file and --appended-file options imply the
903 use of "HGMERGE=internal:local" during DAG buildup.
890 use of "HGMERGE=internal:local" during DAG buildup.
904 """
891 """
905
892
906 if not (mergeable_file or appended_file or overwritten_file or new_file):
893 if not (mergeable_file or appended_file or overwritten_file or new_file):
907 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
894 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
908
895
909 if len(repo.changelog) > 0:
896 if len(repo.changelog) > 0:
910 raise util.Abort(_('repository is not empty'))
897 raise util.Abort(_('repository is not empty'))
911
898
912 if overwritten_file or appended_file:
899 if overwritten_file or appended_file:
913 # we don't want to fail in merges during buildup
900 # we don't want to fail in merges during buildup
914 os.environ['HGMERGE'] = 'internal:local'
901 os.environ['HGMERGE'] = 'internal:local'
915
902
916 def writefile(fname, text, fmode="wb"):
903 def writefile(fname, text, fmode="wb"):
917 f = open(fname, fmode)
904 f = open(fname, fmode)
918 try:
905 try:
919 f.write(text)
906 f.write(text)
920 finally:
907 finally:
921 f.close()
908 f.close()
922
909
923 if mergeable_file:
910 if mergeable_file:
924 linesperrev = 2
911 linesperrev = 2
925 # determine number of revs in DAG
912 # determine number of revs in DAG
926 n = 0
913 n = 0
927 for type, data in dagparser.parsedag(text):
914 for type, data in dagparser.parsedag(text):
928 if type == 'n':
915 if type == 'n':
929 n += 1
916 n += 1
930 # make a file with k lines per rev
917 # make a file with k lines per rev
931 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
918 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
932 + "\n")
919 + "\n")
933
920
934 at = -1
921 at = -1
935 atbranch = 'default'
922 atbranch = 'default'
936 for type, data in dagparser.parsedag(text):
923 for type, data in dagparser.parsedag(text):
937 if type == 'n':
924 if type == 'n':
938 ui.status('node %s\n' % str(data))
925 ui.status('node %s\n' % str(data))
939 id, ps = data
926 id, ps = data
940 p1 = ps[0]
927 p1 = ps[0]
941 if p1 != at:
928 if p1 != at:
942 update(ui, repo, node=p1, clean=True)
929 update(ui, repo, node=p1, clean=True)
943 at = p1
930 at = p1
944 if repo.dirstate.branch() != atbranch:
931 if repo.dirstate.branch() != atbranch:
945 branch(ui, repo, atbranch, force=True)
932 branch(ui, repo, atbranch, force=True)
946 if len(ps) > 1:
933 if len(ps) > 1:
947 p2 = ps[1]
934 p2 = ps[1]
948 merge(ui, repo, node=p2)
935 merge(ui, repo, node=p2)
949
936
950 if mergeable_file:
937 if mergeable_file:
951 f = open("mf", "rb+")
938 f = open("mf", "rb+")
952 try:
939 try:
953 lines = f.read().split("\n")
940 lines = f.read().split("\n")
954 lines[id * linesperrev] += " r%i" % id
941 lines[id * linesperrev] += " r%i" % id
955 f.seek(0)
942 f.seek(0)
956 f.write("\n".join(lines))
943 f.write("\n".join(lines))
957 finally:
944 finally:
958 f.close()
945 f.close()
959
946
960 if appended_file:
947 if appended_file:
961 writefile("af", "r%i\n" % id, "ab")
948 writefile("af", "r%i\n" % id, "ab")
962
949
963 if overwritten_file:
950 if overwritten_file:
964 writefile("of", "r%i\n" % id)
951 writefile("of", "r%i\n" % id)
965
952
966 if new_file:
953 if new_file:
967 writefile("nf%i" % id, "r%i\n" % id)
954 writefile("nf%i" % id, "r%i\n" % id)
968
955
969 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
956 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
970 at = id
957 at = id
971 elif type == 'l':
958 elif type == 'l':
972 id, name = data
959 id, name = data
973 ui.status('tag %s\n' % name)
960 ui.status('tag %s\n' % name)
974 tag(ui, repo, name, local=True)
961 tag(ui, repo, name, local=True)
975 elif type == 'a':
962 elif type == 'a':
976 ui.status('branch %s\n' % data)
963 ui.status('branch %s\n' % data)
977 atbranch = data
964 atbranch = data
978 elif type in 'cC':
965 elif type in 'cC':
979 r = util.system(data, cwd=repo.root)
966 r = util.system(data, cwd=repo.root)
980 if r:
967 if r:
981 desc, r = util.explain_exit(r)
968 desc, r = util.explain_exit(r)
982 raise util.Abort(_('%s command %s') % (data, desc))
969 raise util.Abort(_('%s command %s') % (data, desc))
983
970
984 def debugcommands(ui, cmd='', *args):
971 def debugcommands(ui, cmd='', *args):
985 """list all available commands and options"""
972 """list all available commands and options"""
986 for cmd, vals in sorted(table.iteritems()):
973 for cmd, vals in sorted(table.iteritems()):
987 cmd = cmd.split('|')[0].strip('^')
974 cmd = cmd.split('|')[0].strip('^')
988 opts = ', '.join([i[1] for i in vals[1]])
975 opts = ', '.join([i[1] for i in vals[1]])
989 ui.write('%s: %s\n' % (cmd, opts))
976 ui.write('%s: %s\n' % (cmd, opts))
990
977
991 def debugcomplete(ui, cmd='', **opts):
978 def debugcomplete(ui, cmd='', **opts):
992 """returns the completion list associated with the given command"""
979 """returns the completion list associated with the given command"""
993
980
994 if opts.get('options'):
981 if opts.get('options'):
995 options = []
982 options = []
996 otables = [globalopts]
983 otables = [globalopts]
997 if cmd:
984 if cmd:
998 aliases, entry = cmdutil.findcmd(cmd, table, False)
985 aliases, entry = cmdutil.findcmd(cmd, table, False)
999 otables.append(entry[1])
986 otables.append(entry[1])
1000 for t in otables:
987 for t in otables:
1001 for o in t:
988 for o in t:
1002 if "(DEPRECATED)" in o[3]:
989 if "(DEPRECATED)" in o[3]:
1003 continue
990 continue
1004 if o[0]:
991 if o[0]:
1005 options.append('-%s' % o[0])
992 options.append('-%s' % o[0])
1006 options.append('--%s' % o[1])
993 options.append('--%s' % o[1])
1007 ui.write("%s\n" % "\n".join(options))
994 ui.write("%s\n" % "\n".join(options))
1008 return
995 return
1009
996
1010 cmdlist = cmdutil.findpossible(cmd, table)
997 cmdlist = cmdutil.findpossible(cmd, table)
1011 if ui.verbose:
998 if ui.verbose:
1012 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
999 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1013 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1000 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1014
1001
1015 def debugfsinfo(ui, path = "."):
1002 def debugfsinfo(ui, path = "."):
1016 """show information detected about current filesystem"""
1003 """show information detected about current filesystem"""
1017 open('.debugfsinfo', 'w').write('')
1004 open('.debugfsinfo', 'w').write('')
1018 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1005 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1019 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1006 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1020 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1007 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1021 and 'yes' or 'no'))
1008 and 'yes' or 'no'))
1022 os.unlink('.debugfsinfo')
1009 os.unlink('.debugfsinfo')
1023
1010
1024 def debugrebuildstate(ui, repo, rev="tip"):
1011 def debugrebuildstate(ui, repo, rev="tip"):
1025 """rebuild the dirstate as it would look like for the given revision"""
1012 """rebuild the dirstate as it would look like for the given revision"""
1026 ctx = repo[rev]
1013 ctx = repo[rev]
1027 wlock = repo.wlock()
1014 wlock = repo.wlock()
1028 try:
1015 try:
1029 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1016 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1030 finally:
1017 finally:
1031 wlock.release()
1018 wlock.release()
1032
1019
1033 def debugcheckstate(ui, repo):
1020 def debugcheckstate(ui, repo):
1034 """validate the correctness of the current dirstate"""
1021 """validate the correctness of the current dirstate"""
1035 parent1, parent2 = repo.dirstate.parents()
1022 parent1, parent2 = repo.dirstate.parents()
1036 m1 = repo[parent1].manifest()
1023 m1 = repo[parent1].manifest()
1037 m2 = repo[parent2].manifest()
1024 m2 = repo[parent2].manifest()
1038 errors = 0
1025 errors = 0
1039 for f in repo.dirstate:
1026 for f in repo.dirstate:
1040 state = repo.dirstate[f]
1027 state = repo.dirstate[f]
1041 if state in "nr" and f not in m1:
1028 if state in "nr" and f not in m1:
1042 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1029 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1043 errors += 1
1030 errors += 1
1044 if state in "a" and f in m1:
1031 if state in "a" and f in m1:
1045 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1032 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1046 errors += 1
1033 errors += 1
1047 if state in "m" and f not in m1 and f not in m2:
1034 if state in "m" and f not in m1 and f not in m2:
1048 ui.warn(_("%s in state %s, but not in either manifest\n") %
1035 ui.warn(_("%s in state %s, but not in either manifest\n") %
1049 (f, state))
1036 (f, state))
1050 errors += 1
1037 errors += 1
1051 for f in m1:
1038 for f in m1:
1052 state = repo.dirstate[f]
1039 state = repo.dirstate[f]
1053 if state not in "nrm":
1040 if state not in "nrm":
1054 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1041 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1055 errors += 1
1042 errors += 1
1056 if errors:
1043 if errors:
1057 error = _(".hg/dirstate inconsistent with current parent's manifest")
1044 error = _(".hg/dirstate inconsistent with current parent's manifest")
1058 raise util.Abort(error)
1045 raise util.Abort(error)
1059
1046
1060 def showconfig(ui, repo, *values, **opts):
1047 def showconfig(ui, repo, *values, **opts):
1061 """show combined config settings from all hgrc files
1048 """show combined config settings from all hgrc files
1062
1049
1063 With no arguments, print names and values of all config items.
1050 With no arguments, print names and values of all config items.
1064
1051
1065 With one argument of the form section.name, print just the value
1052 With one argument of the form section.name, print just the value
1066 of that config item.
1053 of that config item.
1067
1054
1068 With multiple arguments, print names and values of all config
1055 With multiple arguments, print names and values of all config
1069 items with matching section names.
1056 items with matching section names.
1070
1057
1071 With --debug, the source (filename and line number) is printed
1058 With --debug, the source (filename and line number) is printed
1072 for each config item.
1059 for each config item.
1073
1060
1074 Returns 0 on success.
1061 Returns 0 on success.
1075 """
1062 """
1076
1063
1077 for f in util.rcpath():
1064 for f in util.rcpath():
1078 ui.debug(_('read config from: %s\n') % f)
1065 ui.debug(_('read config from: %s\n') % f)
1079 untrusted = bool(opts.get('untrusted'))
1066 untrusted = bool(opts.get('untrusted'))
1080 if values:
1067 if values:
1081 if len([v for v in values if '.' in v]) > 1:
1068 if len([v for v in values if '.' in v]) > 1:
1082 raise util.Abort(_('only one config item permitted'))
1069 raise util.Abort(_('only one config item permitted'))
1083 for section, name, value in ui.walkconfig(untrusted=untrusted):
1070 for section, name, value in ui.walkconfig(untrusted=untrusted):
1084 sectname = section + '.' + name
1071 sectname = section + '.' + name
1085 if values:
1072 if values:
1086 for v in values:
1073 for v in values:
1087 if v == section:
1074 if v == section:
1088 ui.debug('%s: ' %
1075 ui.debug('%s: ' %
1089 ui.configsource(section, name, untrusted))
1076 ui.configsource(section, name, untrusted))
1090 ui.write('%s=%s\n' % (sectname, value))
1077 ui.write('%s=%s\n' % (sectname, value))
1091 elif v == sectname:
1078 elif v == sectname:
1092 ui.debug('%s: ' %
1079 ui.debug('%s: ' %
1093 ui.configsource(section, name, untrusted))
1080 ui.configsource(section, name, untrusted))
1094 ui.write(value, '\n')
1081 ui.write(value, '\n')
1095 else:
1082 else:
1096 ui.debug('%s: ' %
1083 ui.debug('%s: ' %
1097 ui.configsource(section, name, untrusted))
1084 ui.configsource(section, name, untrusted))
1098 ui.write('%s=%s\n' % (sectname, value))
1085 ui.write('%s=%s\n' % (sectname, value))
1099
1086
1100 def debugpushkey(ui, repopath, namespace, *keyinfo):
1087 def debugpushkey(ui, repopath, namespace, *keyinfo):
1101 '''access the pushkey key/value protocol
1088 '''access the pushkey key/value protocol
1102
1089
1103 With two args, list the keys in the given namespace.
1090 With two args, list the keys in the given namespace.
1104
1091
1105 With five args, set a key to new if it currently is set to old.
1092 With five args, set a key to new if it currently is set to old.
1106 Reports success or failure.
1093 Reports success or failure.
1107 '''
1094 '''
1108
1095
1109 target = hg.repository(ui, repopath)
1096 target = hg.repository(ui, repopath)
1110 if keyinfo:
1097 if keyinfo:
1111 key, old, new = keyinfo
1098 key, old, new = keyinfo
1112 r = target.pushkey(namespace, key, old, new)
1099 r = target.pushkey(namespace, key, old, new)
1113 ui.status(str(r) + '\n')
1100 ui.status(str(r) + '\n')
1114 return not(r)
1101 return not(r)
1115 else:
1102 else:
1116 for k, v in target.listkeys(namespace).iteritems():
1103 for k, v in target.listkeys(namespace).iteritems():
1117 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1104 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1118 v.encode('string-escape')))
1105 v.encode('string-escape')))
1119
1106
1120 def debugrevspec(ui, repo, expr):
1107 def debugrevspec(ui, repo, expr):
1121 '''parse and apply a revision specification'''
1108 '''parse and apply a revision specification'''
1122 if ui.verbose:
1109 if ui.verbose:
1123 tree = revset.parse(expr)
1110 tree = revset.parse(expr)
1124 ui.note(tree, "\n")
1111 ui.note(tree, "\n")
1125 func = revset.match(expr)
1112 func = revset.match(expr)
1126 for c in func(repo, range(len(repo))):
1113 for c in func(repo, range(len(repo))):
1127 ui.write("%s\n" % c)
1114 ui.write("%s\n" % c)
1128
1115
1129 def debugsetparents(ui, repo, rev1, rev2=None):
1116 def debugsetparents(ui, repo, rev1, rev2=None):
1130 """manually set the parents of the current working directory
1117 """manually set the parents of the current working directory
1131
1118
1132 This is useful for writing repository conversion tools, but should
1119 This is useful for writing repository conversion tools, but should
1133 be used with care.
1120 be used with care.
1134
1121
1135 Returns 0 on success.
1122 Returns 0 on success.
1136 """
1123 """
1137
1124
1138 if not rev2:
1125 if not rev2:
1139 rev2 = hex(nullid)
1126 rev2 = hex(nullid)
1140
1127
1141 wlock = repo.wlock()
1128 wlock = repo.wlock()
1142 try:
1129 try:
1143 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1130 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1144 finally:
1131 finally:
1145 wlock.release()
1132 wlock.release()
1146
1133
1147 def debugstate(ui, repo, nodates=None):
1134 def debugstate(ui, repo, nodates=None):
1148 """show the contents of the current dirstate"""
1135 """show the contents of the current dirstate"""
1149 timestr = ""
1136 timestr = ""
1150 showdate = not nodates
1137 showdate = not nodates
1151 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1138 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1152 if showdate:
1139 if showdate:
1153 if ent[3] == -1:
1140 if ent[3] == -1:
1154 # Pad or slice to locale representation
1141 # Pad or slice to locale representation
1155 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1142 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1156 time.localtime(0)))
1143 time.localtime(0)))
1157 timestr = 'unset'
1144 timestr = 'unset'
1158 timestr = (timestr[:locale_len] +
1145 timestr = (timestr[:locale_len] +
1159 ' ' * (locale_len - len(timestr)))
1146 ' ' * (locale_len - len(timestr)))
1160 else:
1147 else:
1161 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1148 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1162 time.localtime(ent[3]))
1149 time.localtime(ent[3]))
1163 if ent[1] & 020000:
1150 if ent[1] & 020000:
1164 mode = 'lnk'
1151 mode = 'lnk'
1165 else:
1152 else:
1166 mode = '%3o' % (ent[1] & 0777)
1153 mode = '%3o' % (ent[1] & 0777)
1167 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1154 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1168 for f in repo.dirstate.copies():
1155 for f in repo.dirstate.copies():
1169 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1156 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1170
1157
1171 def debugsub(ui, repo, rev=None):
1158 def debugsub(ui, repo, rev=None):
1172 if rev == '':
1159 if rev == '':
1173 rev = None
1160 rev = None
1174 for k, v in sorted(repo[rev].substate.items()):
1161 for k, v in sorted(repo[rev].substate.items()):
1175 ui.write('path %s\n' % k)
1162 ui.write('path %s\n' % k)
1176 ui.write(' source %s\n' % v[0])
1163 ui.write(' source %s\n' % v[0])
1177 ui.write(' revision %s\n' % v[1])
1164 ui.write(' revision %s\n' % v[1])
1178
1165
1179 def debugdag(ui, repo, file_=None, *revs, **opts):
1166 def debugdag(ui, repo, file_=None, *revs, **opts):
1180 """format the changelog or an index DAG as a concise textual description
1167 """format the changelog or an index DAG as a concise textual description
1181
1168
1182 If you pass a revlog index, the revlog's DAG is emitted. If you list
1169 If you pass a revlog index, the revlog's DAG is emitted. If you list
1183 revision numbers, they get labelled in the output as rN.
1170 revision numbers, they get labelled in the output as rN.
1184
1171
1185 Otherwise, the changelog DAG of the current repo is emitted.
1172 Otherwise, the changelog DAG of the current repo is emitted.
1186 """
1173 """
1187 spaces = opts.get('spaces')
1174 spaces = opts.get('spaces')
1188 dots = opts.get('dots')
1175 dots = opts.get('dots')
1189 if file_:
1176 if file_:
1190 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1177 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1191 revs = set((int(r) for r in revs))
1178 revs = set((int(r) for r in revs))
1192 def events():
1179 def events():
1193 for r in rlog:
1180 for r in rlog:
1194 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1181 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1195 if r in revs:
1182 if r in revs:
1196 yield 'l', (r, "r%i" % r)
1183 yield 'l', (r, "r%i" % r)
1197 elif repo:
1184 elif repo:
1198 cl = repo.changelog
1185 cl = repo.changelog
1199 tags = opts.get('tags')
1186 tags = opts.get('tags')
1200 branches = opts.get('branches')
1187 branches = opts.get('branches')
1201 if tags:
1188 if tags:
1202 labels = {}
1189 labels = {}
1203 for l, n in repo.tags().items():
1190 for l, n in repo.tags().items():
1204 labels.setdefault(cl.rev(n), []).append(l)
1191 labels.setdefault(cl.rev(n), []).append(l)
1205 def events():
1192 def events():
1206 b = "default"
1193 b = "default"
1207 for r in cl:
1194 for r in cl:
1208 if branches:
1195 if branches:
1209 newb = cl.read(cl.node(r))[5]['branch']
1196 newb = cl.read(cl.node(r))[5]['branch']
1210 if newb != b:
1197 if newb != b:
1211 yield 'a', newb
1198 yield 'a', newb
1212 b = newb
1199 b = newb
1213 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1200 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1214 if tags:
1201 if tags:
1215 ls = labels.get(r)
1202 ls = labels.get(r)
1216 if ls:
1203 if ls:
1217 for l in ls:
1204 for l in ls:
1218 yield 'l', (r, l)
1205 yield 'l', (r, l)
1219 else:
1206 else:
1220 raise util.Abort(_('need repo for changelog dag'))
1207 raise util.Abort(_('need repo for changelog dag'))
1221
1208
1222 for line in dagparser.dagtextlines(events(),
1209 for line in dagparser.dagtextlines(events(),
1223 addspaces=spaces,
1210 addspaces=spaces,
1224 wraplabels=True,
1211 wraplabels=True,
1225 wrapannotations=True,
1212 wrapannotations=True,
1226 wrapnonlinear=dots,
1213 wrapnonlinear=dots,
1227 usedots=dots,
1214 usedots=dots,
1228 maxlinewidth=70):
1215 maxlinewidth=70):
1229 ui.write(line)
1216 ui.write(line)
1230 ui.write("\n")
1217 ui.write("\n")
1231
1218
1232 def debugdata(ui, repo, file_, rev):
1219 def debugdata(ui, repo, file_, rev):
1233 """dump the contents of a data file revision"""
1220 """dump the contents of a data file revision"""
1234 r = None
1221 r = None
1235 if repo:
1222 if repo:
1236 filelog = repo.file(file_)
1223 filelog = repo.file(file_)
1237 if len(filelog):
1224 if len(filelog):
1238 r = filelog
1225 r = filelog
1239 if not r:
1226 if not r:
1240 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1227 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1241 try:
1228 try:
1242 ui.write(r.revision(r.lookup(rev)))
1229 ui.write(r.revision(r.lookup(rev)))
1243 except KeyError:
1230 except KeyError:
1244 raise util.Abort(_('invalid revision identifier %s') % rev)
1231 raise util.Abort(_('invalid revision identifier %s') % rev)
1245
1232
1246 def debugdate(ui, date, range=None, **opts):
1233 def debugdate(ui, date, range=None, **opts):
1247 """parse and display a date"""
1234 """parse and display a date"""
1248 if opts["extended"]:
1235 if opts["extended"]:
1249 d = util.parsedate(date, util.extendeddateformats)
1236 d = util.parsedate(date, util.extendeddateformats)
1250 else:
1237 else:
1251 d = util.parsedate(date)
1238 d = util.parsedate(date)
1252 ui.write("internal: %s %s\n" % d)
1239 ui.write("internal: %s %s\n" % d)
1253 ui.write("standard: %s\n" % util.datestr(d))
1240 ui.write("standard: %s\n" % util.datestr(d))
1254 if range:
1241 if range:
1255 m = util.matchdate(range)
1242 m = util.matchdate(range)
1256 ui.write("match: %s\n" % m(d[0]))
1243 ui.write("match: %s\n" % m(d[0]))
1257
1244
1258 def debugindex(ui, repo, file_):
1245 def debugindex(ui, repo, file_):
1259 """dump the contents of an index file"""
1246 """dump the contents of an index file"""
1260 r = None
1247 r = None
1261 if repo:
1248 if repo:
1262 filelog = repo.file(file_)
1249 filelog = repo.file(file_)
1263 if len(filelog):
1250 if len(filelog):
1264 r = filelog
1251 r = filelog
1265 if not r:
1252 if not r:
1266 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1253 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1267 ui.write(" rev offset length base linkrev"
1254 ui.write(" rev offset length base linkrev"
1268 " nodeid p1 p2\n")
1255 " nodeid p1 p2\n")
1269 for i in r:
1256 for i in r:
1270 node = r.node(i)
1257 node = r.node(i)
1271 try:
1258 try:
1272 pp = r.parents(node)
1259 pp = r.parents(node)
1273 except:
1260 except:
1274 pp = [nullid, nullid]
1261 pp = [nullid, nullid]
1275 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1262 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1276 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1263 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1277 short(node), short(pp[0]), short(pp[1])))
1264 short(node), short(pp[0]), short(pp[1])))
1278
1265
1279 def debugindexdot(ui, repo, file_):
1266 def debugindexdot(ui, repo, file_):
1280 """dump an index DAG as a graphviz dot file"""
1267 """dump an index DAG as a graphviz dot file"""
1281 r = None
1268 r = None
1282 if repo:
1269 if repo:
1283 filelog = repo.file(file_)
1270 filelog = repo.file(file_)
1284 if len(filelog):
1271 if len(filelog):
1285 r = filelog
1272 r = filelog
1286 if not r:
1273 if not r:
1287 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1274 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1288 ui.write("digraph G {\n")
1275 ui.write("digraph G {\n")
1289 for i in r:
1276 for i in r:
1290 node = r.node(i)
1277 node = r.node(i)
1291 pp = r.parents(node)
1278 pp = r.parents(node)
1292 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1279 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1293 if pp[1] != nullid:
1280 if pp[1] != nullid:
1294 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1281 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1295 ui.write("}\n")
1282 ui.write("}\n")
1296
1283
1297 def debuginstall(ui):
1284 def debuginstall(ui):
1298 '''test Mercurial installation
1285 '''test Mercurial installation
1299
1286
1300 Returns 0 on success.
1287 Returns 0 on success.
1301 '''
1288 '''
1302
1289
1303 def writetemp(contents):
1290 def writetemp(contents):
1304 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1291 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1305 f = os.fdopen(fd, "wb")
1292 f = os.fdopen(fd, "wb")
1306 f.write(contents)
1293 f.write(contents)
1307 f.close()
1294 f.close()
1308 return name
1295 return name
1309
1296
1310 problems = 0
1297 problems = 0
1311
1298
1312 # encoding
1299 # encoding
1313 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1300 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1314 try:
1301 try:
1315 encoding.fromlocal("test")
1302 encoding.fromlocal("test")
1316 except util.Abort, inst:
1303 except util.Abort, inst:
1317 ui.write(" %s\n" % inst)
1304 ui.write(" %s\n" % inst)
1318 ui.write(_(" (check that your locale is properly set)\n"))
1305 ui.write(_(" (check that your locale is properly set)\n"))
1319 problems += 1
1306 problems += 1
1320
1307
1321 # compiled modules
1308 # compiled modules
1322 ui.status(_("Checking installed modules (%s)...\n")
1309 ui.status(_("Checking installed modules (%s)...\n")
1323 % os.path.dirname(__file__))
1310 % os.path.dirname(__file__))
1324 try:
1311 try:
1325 import bdiff, mpatch, base85, osutil
1312 import bdiff, mpatch, base85, osutil
1326 except Exception, inst:
1313 except Exception, inst:
1327 ui.write(" %s\n" % inst)
1314 ui.write(" %s\n" % inst)
1328 ui.write(_(" One or more extensions could not be found"))
1315 ui.write(_(" One or more extensions could not be found"))
1329 ui.write(_(" (check that you compiled the extensions)\n"))
1316 ui.write(_(" (check that you compiled the extensions)\n"))
1330 problems += 1
1317 problems += 1
1331
1318
1332 # templates
1319 # templates
1333 ui.status(_("Checking templates...\n"))
1320 ui.status(_("Checking templates...\n"))
1334 try:
1321 try:
1335 import templater
1322 import templater
1336 templater.templater(templater.templatepath("map-cmdline.default"))
1323 templater.templater(templater.templatepath("map-cmdline.default"))
1337 except Exception, inst:
1324 except Exception, inst:
1338 ui.write(" %s\n" % inst)
1325 ui.write(" %s\n" % inst)
1339 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1326 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1340 problems += 1
1327 problems += 1
1341
1328
1342 # patch
1329 # patch
1343 ui.status(_("Checking patch...\n"))
1330 ui.status(_("Checking patch...\n"))
1344 patchproblems = 0
1331 patchproblems = 0
1345 a = "1\n2\n3\n4\n"
1332 a = "1\n2\n3\n4\n"
1346 b = "1\n2\n3\ninsert\n4\n"
1333 b = "1\n2\n3\ninsert\n4\n"
1347 fa = writetemp(a)
1334 fa = writetemp(a)
1348 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1335 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1349 os.path.basename(fa))
1336 os.path.basename(fa))
1350 fd = writetemp(d)
1337 fd = writetemp(d)
1351
1338
1352 files = {}
1339 files = {}
1353 try:
1340 try:
1354 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1341 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1355 except util.Abort, e:
1342 except util.Abort, e:
1356 ui.write(_(" patch call failed:\n"))
1343 ui.write(_(" patch call failed:\n"))
1357 ui.write(" " + str(e) + "\n")
1344 ui.write(" " + str(e) + "\n")
1358 patchproblems += 1
1345 patchproblems += 1
1359 else:
1346 else:
1360 if list(files) != [os.path.basename(fa)]:
1347 if list(files) != [os.path.basename(fa)]:
1361 ui.write(_(" unexpected patch output!\n"))
1348 ui.write(_(" unexpected patch output!\n"))
1362 patchproblems += 1
1349 patchproblems += 1
1363 a = open(fa).read()
1350 a = open(fa).read()
1364 if a != b:
1351 if a != b:
1365 ui.write(_(" patch test failed!\n"))
1352 ui.write(_(" patch test failed!\n"))
1366 patchproblems += 1
1353 patchproblems += 1
1367
1354
1368 if patchproblems:
1355 if patchproblems:
1369 if ui.config('ui', 'patch'):
1356 if ui.config('ui', 'patch'):
1370 ui.write(_(" (Current patch tool may be incompatible with patch,"
1357 ui.write(_(" (Current patch tool may be incompatible with patch,"
1371 " or misconfigured. Please check your configuration"
1358 " or misconfigured. Please check your configuration"
1372 " file)\n"))
1359 " file)\n"))
1373 else:
1360 else:
1374 ui.write(_(" Internal patcher failure, please report this error"
1361 ui.write(_(" Internal patcher failure, please report this error"
1375 " to http://mercurial.selenic.com/bts/\n"))
1362 " to http://mercurial.selenic.com/bts/\n"))
1376 problems += patchproblems
1363 problems += patchproblems
1377
1364
1378 os.unlink(fa)
1365 os.unlink(fa)
1379 os.unlink(fd)
1366 os.unlink(fd)
1380
1367
1381 # editor
1368 # editor
1382 ui.status(_("Checking commit editor...\n"))
1369 ui.status(_("Checking commit editor...\n"))
1383 editor = ui.geteditor()
1370 editor = ui.geteditor()
1384 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1371 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1385 if not cmdpath:
1372 if not cmdpath:
1386 if editor == 'vi':
1373 if editor == 'vi':
1387 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1374 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1388 ui.write(_(" (specify a commit editor in your configuration"
1375 ui.write(_(" (specify a commit editor in your configuration"
1389 " file)\n"))
1376 " file)\n"))
1390 else:
1377 else:
1391 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1378 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1392 ui.write(_(" (specify a commit editor in your configuration"
1379 ui.write(_(" (specify a commit editor in your configuration"
1393 " file)\n"))
1380 " file)\n"))
1394 problems += 1
1381 problems += 1
1395
1382
1396 # check username
1383 # check username
1397 ui.status(_("Checking username...\n"))
1384 ui.status(_("Checking username...\n"))
1398 try:
1385 try:
1399 ui.username()
1386 ui.username()
1400 except util.Abort, e:
1387 except util.Abort, e:
1401 ui.write(" %s\n" % e)
1388 ui.write(" %s\n" % e)
1402 ui.write(_(" (specify a username in your configuration file)\n"))
1389 ui.write(_(" (specify a username in your configuration file)\n"))
1403 problems += 1
1390 problems += 1
1404
1391
1405 if not problems:
1392 if not problems:
1406 ui.status(_("No problems detected\n"))
1393 ui.status(_("No problems detected\n"))
1407 else:
1394 else:
1408 ui.write(_("%s problems detected,"
1395 ui.write(_("%s problems detected,"
1409 " please check your install!\n") % problems)
1396 " please check your install!\n") % problems)
1410
1397
1411 return problems
1398 return problems
1412
1399
1413 def debugrename(ui, repo, file1, *pats, **opts):
1400 def debugrename(ui, repo, file1, *pats, **opts):
1414 """dump rename information"""
1401 """dump rename information"""
1415
1402
1416 ctx = repo[opts.get('rev')]
1403 ctx = repo[opts.get('rev')]
1417 m = cmdutil.match(repo, (file1,) + pats, opts)
1404 m = cmdutil.match(repo, (file1,) + pats, opts)
1418 for abs in ctx.walk(m):
1405 for abs in ctx.walk(m):
1419 fctx = ctx[abs]
1406 fctx = ctx[abs]
1420 o = fctx.filelog().renamed(fctx.filenode())
1407 o = fctx.filelog().renamed(fctx.filenode())
1421 rel = m.rel(abs)
1408 rel = m.rel(abs)
1422 if o:
1409 if o:
1423 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1410 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1424 else:
1411 else:
1425 ui.write(_("%s not renamed\n") % rel)
1412 ui.write(_("%s not renamed\n") % rel)
1426
1413
1427 def debugwalk(ui, repo, *pats, **opts):
1414 def debugwalk(ui, repo, *pats, **opts):
1428 """show how files match on given patterns"""
1415 """show how files match on given patterns"""
1429 m = cmdutil.match(repo, pats, opts)
1416 m = cmdutil.match(repo, pats, opts)
1430 items = list(repo.walk(m))
1417 items = list(repo.walk(m))
1431 if not items:
1418 if not items:
1432 return
1419 return
1433 fmt = 'f %%-%ds %%-%ds %%s' % (
1420 fmt = 'f %%-%ds %%-%ds %%s' % (
1434 max([len(abs) for abs in items]),
1421 max([len(abs) for abs in items]),
1435 max([len(m.rel(abs)) for abs in items]))
1422 max([len(m.rel(abs)) for abs in items]))
1436 for abs in items:
1423 for abs in items:
1437 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1424 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1438 ui.write("%s\n" % line.rstrip())
1425 ui.write("%s\n" % line.rstrip())
1439
1426
1440 def diff(ui, repo, *pats, **opts):
1427 def diff(ui, repo, *pats, **opts):
1441 """diff repository (or selected files)
1428 """diff repository (or selected files)
1442
1429
1443 Show differences between revisions for the specified files.
1430 Show differences between revisions for the specified files.
1444
1431
1445 Differences between files are shown using the unified diff format.
1432 Differences between files are shown using the unified diff format.
1446
1433
1447 NOTE: diff may generate unexpected results for merges, as it will
1434 NOTE: diff may generate unexpected results for merges, as it will
1448 default to comparing against the working directory's first parent
1435 default to comparing against the working directory's first parent
1449 changeset if no revisions are specified.
1436 changeset if no revisions are specified.
1450
1437
1451 When two revision arguments are given, then changes are shown
1438 When two revision arguments are given, then changes are shown
1452 between those revisions. If only one revision is specified then
1439 between those revisions. If only one revision is specified then
1453 that revision is compared to the working directory, and, when no
1440 that revision is compared to the working directory, and, when no
1454 revisions are specified, the working directory files are compared
1441 revisions are specified, the working directory files are compared
1455 to its parent.
1442 to its parent.
1456
1443
1457 Alternatively you can specify -c/--change with a revision to see
1444 Alternatively you can specify -c/--change with a revision to see
1458 the changes in that changeset relative to its first parent.
1445 the changes in that changeset relative to its first parent.
1459
1446
1460 Without the -a/--text option, diff will avoid generating diffs of
1447 Without the -a/--text option, diff will avoid generating diffs of
1461 files it detects as binary. With -a, diff will generate a diff
1448 files it detects as binary. With -a, diff will generate a diff
1462 anyway, probably with undesirable results.
1449 anyway, probably with undesirable results.
1463
1450
1464 Use the -g/--git option to generate diffs in the git extended diff
1451 Use the -g/--git option to generate diffs in the git extended diff
1465 format. For more information, read :hg:`help diffs`.
1452 format. For more information, read :hg:`help diffs`.
1466
1453
1467 Returns 0 on success.
1454 Returns 0 on success.
1468 """
1455 """
1469
1456
1470 revs = opts.get('rev')
1457 revs = opts.get('rev')
1471 change = opts.get('change')
1458 change = opts.get('change')
1472 stat = opts.get('stat')
1459 stat = opts.get('stat')
1473 reverse = opts.get('reverse')
1460 reverse = opts.get('reverse')
1474
1461
1475 if revs and change:
1462 if revs and change:
1476 msg = _('cannot specify --rev and --change at the same time')
1463 msg = _('cannot specify --rev and --change at the same time')
1477 raise util.Abort(msg)
1464 raise util.Abort(msg)
1478 elif change:
1465 elif change:
1479 node2 = repo.lookup(change)
1466 node2 = repo.lookup(change)
1480 node1 = repo[node2].parents()[0].node()
1467 node1 = repo[node2].parents()[0].node()
1481 else:
1468 else:
1482 node1, node2 = cmdutil.revpair(repo, revs)
1469 node1, node2 = cmdutil.revpair(repo, revs)
1483
1470
1484 if reverse:
1471 if reverse:
1485 node1, node2 = node2, node1
1472 node1, node2 = node2, node1
1486
1473
1487 diffopts = patch.diffopts(ui, opts)
1474 diffopts = patch.diffopts(ui, opts)
1488 m = cmdutil.match(repo, pats, opts)
1475 m = cmdutil.match(repo, pats, opts)
1489 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1476 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1490 listsubrepos=opts.get('subrepos'))
1477 listsubrepos=opts.get('subrepos'))
1491
1478
1492 def export(ui, repo, *changesets, **opts):
1479 def export(ui, repo, *changesets, **opts):
1493 """dump the header and diffs for one or more changesets
1480 """dump the header and diffs for one or more changesets
1494
1481
1495 Print the changeset header and diffs for one or more revisions.
1482 Print the changeset header and diffs for one or more revisions.
1496
1483
1497 The information shown in the changeset header is: author, date,
1484 The information shown in the changeset header is: author, date,
1498 branch name (if non-default), changeset hash, parent(s) and commit
1485 branch name (if non-default), changeset hash, parent(s) and commit
1499 comment.
1486 comment.
1500
1487
1501 NOTE: export may generate unexpected diff output for merge
1488 NOTE: export may generate unexpected diff output for merge
1502 changesets, as it will compare the merge changeset against its
1489 changesets, as it will compare the merge changeset against its
1503 first parent only.
1490 first parent only.
1504
1491
1505 Output may be to a file, in which case the name of the file is
1492 Output may be to a file, in which case the name of the file is
1506 given using a format string. The formatting rules are as follows:
1493 given using a format string. The formatting rules are as follows:
1507
1494
1508 :``%%``: literal "%" character
1495 :``%%``: literal "%" character
1509 :``%H``: changeset hash (40 hexadecimal digits)
1496 :``%H``: changeset hash (40 hexadecimal digits)
1510 :``%N``: number of patches being generated
1497 :``%N``: number of patches being generated
1511 :``%R``: changeset revision number
1498 :``%R``: changeset revision number
1512 :``%b``: basename of the exporting repository
1499 :``%b``: basename of the exporting repository
1513 :``%h``: short-form changeset hash (12 hexadecimal digits)
1500 :``%h``: short-form changeset hash (12 hexadecimal digits)
1514 :``%n``: zero-padded sequence number, starting at 1
1501 :``%n``: zero-padded sequence number, starting at 1
1515 :``%r``: zero-padded changeset revision number
1502 :``%r``: zero-padded changeset revision number
1516
1503
1517 Without the -a/--text option, export will avoid generating diffs
1504 Without the -a/--text option, export will avoid generating diffs
1518 of files it detects as binary. With -a, export will generate a
1505 of files it detects as binary. With -a, export will generate a
1519 diff anyway, probably with undesirable results.
1506 diff anyway, probably with undesirable results.
1520
1507
1521 Use the -g/--git option to generate diffs in the git extended diff
1508 Use the -g/--git option to generate diffs in the git extended diff
1522 format. See :hg:`help diffs` for more information.
1509 format. See :hg:`help diffs` for more information.
1523
1510
1524 With the --switch-parent option, the diff will be against the
1511 With the --switch-parent option, the diff will be against the
1525 second parent. It can be useful to review a merge.
1512 second parent. It can be useful to review a merge.
1526
1513
1527 Returns 0 on success.
1514 Returns 0 on success.
1528 """
1515 """
1529 changesets += tuple(opts.get('rev', []))
1516 changesets += tuple(opts.get('rev', []))
1530 if not changesets:
1517 if not changesets:
1531 raise util.Abort(_("export requires at least one changeset"))
1518 raise util.Abort(_("export requires at least one changeset"))
1532 revs = cmdutil.revrange(repo, changesets)
1519 revs = cmdutil.revrange(repo, changesets)
1533 if len(revs) > 1:
1520 if len(revs) > 1:
1534 ui.note(_('exporting patches:\n'))
1521 ui.note(_('exporting patches:\n'))
1535 else:
1522 else:
1536 ui.note(_('exporting patch:\n'))
1523 ui.note(_('exporting patch:\n'))
1537 cmdutil.export(repo, revs, template=opts.get('output'),
1524 cmdutil.export(repo, revs, template=opts.get('output'),
1538 switch_parent=opts.get('switch_parent'),
1525 switch_parent=opts.get('switch_parent'),
1539 opts=patch.diffopts(ui, opts))
1526 opts=patch.diffopts(ui, opts))
1540
1527
1541 def forget(ui, repo, *pats, **opts):
1528 def forget(ui, repo, *pats, **opts):
1542 """forget the specified files on the next commit
1529 """forget the specified files on the next commit
1543
1530
1544 Mark the specified files so they will no longer be tracked
1531 Mark the specified files so they will no longer be tracked
1545 after the next commit.
1532 after the next commit.
1546
1533
1547 This only removes files from the current branch, not from the
1534 This only removes files from the current branch, not from the
1548 entire project history, and it does not delete them from the
1535 entire project history, and it does not delete them from the
1549 working directory.
1536 working directory.
1550
1537
1551 To undo a forget before the next commit, see :hg:`add`.
1538 To undo a forget before the next commit, see :hg:`add`.
1552
1539
1553 Returns 0 on success.
1540 Returns 0 on success.
1554 """
1541 """
1555
1542
1556 if not pats:
1543 if not pats:
1557 raise util.Abort(_('no files specified'))
1544 raise util.Abort(_('no files specified'))
1558
1545
1559 m = cmdutil.match(repo, pats, opts)
1546 m = cmdutil.match(repo, pats, opts)
1560 s = repo.status(match=m, clean=True)
1547 s = repo.status(match=m, clean=True)
1561 forget = sorted(s[0] + s[1] + s[3] + s[6])
1548 forget = sorted(s[0] + s[1] + s[3] + s[6])
1562 errs = 0
1549 errs = 0
1563
1550
1564 for f in m.files():
1551 for f in m.files():
1565 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1552 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1566 ui.warn(_('not removing %s: file is already untracked\n')
1553 ui.warn(_('not removing %s: file is already untracked\n')
1567 % m.rel(f))
1554 % m.rel(f))
1568 errs = 1
1555 errs = 1
1569
1556
1570 for f in forget:
1557 for f in forget:
1571 if ui.verbose or not m.exact(f):
1558 if ui.verbose or not m.exact(f):
1572 ui.status(_('removing %s\n') % m.rel(f))
1559 ui.status(_('removing %s\n') % m.rel(f))
1573
1560
1574 repo[None].remove(forget, unlink=False)
1561 repo[None].remove(forget, unlink=False)
1575 return errs
1562 return errs
1576
1563
1577 def grep(ui, repo, pattern, *pats, **opts):
1564 def grep(ui, repo, pattern, *pats, **opts):
1578 """search for a pattern in specified files and revisions
1565 """search for a pattern in specified files and revisions
1579
1566
1580 Search revisions of files for a regular expression.
1567 Search revisions of files for a regular expression.
1581
1568
1582 This command behaves differently than Unix grep. It only accepts
1569 This command behaves differently than Unix grep. It only accepts
1583 Python/Perl regexps. It searches repository history, not the
1570 Python/Perl regexps. It searches repository history, not the
1584 working directory. It always prints the revision number in which a
1571 working directory. It always prints the revision number in which a
1585 match appears.
1572 match appears.
1586
1573
1587 By default, grep only prints output for the first revision of a
1574 By default, grep only prints output for the first revision of a
1588 file in which it finds a match. To get it to print every revision
1575 file in which it finds a match. To get it to print every revision
1589 that contains a change in match status ("-" for a match that
1576 that contains a change in match status ("-" for a match that
1590 becomes a non-match, or "+" for a non-match that becomes a match),
1577 becomes a non-match, or "+" for a non-match that becomes a match),
1591 use the --all flag.
1578 use the --all flag.
1592
1579
1593 Returns 0 if a match is found, 1 otherwise.
1580 Returns 0 if a match is found, 1 otherwise.
1594 """
1581 """
1595 reflags = 0
1582 reflags = 0
1596 if opts.get('ignore_case'):
1583 if opts.get('ignore_case'):
1597 reflags |= re.I
1584 reflags |= re.I
1598 try:
1585 try:
1599 regexp = re.compile(pattern, reflags)
1586 regexp = re.compile(pattern, reflags)
1600 except Exception, inst:
1587 except Exception, inst:
1601 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1588 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1602 return 1
1589 return 1
1603 sep, eol = ':', '\n'
1590 sep, eol = ':', '\n'
1604 if opts.get('print0'):
1591 if opts.get('print0'):
1605 sep = eol = '\0'
1592 sep = eol = '\0'
1606
1593
1607 getfile = util.lrucachefunc(repo.file)
1594 getfile = util.lrucachefunc(repo.file)
1608
1595
1609 def matchlines(body):
1596 def matchlines(body):
1610 begin = 0
1597 begin = 0
1611 linenum = 0
1598 linenum = 0
1612 while True:
1599 while True:
1613 match = regexp.search(body, begin)
1600 match = regexp.search(body, begin)
1614 if not match:
1601 if not match:
1615 break
1602 break
1616 mstart, mend = match.span()
1603 mstart, mend = match.span()
1617 linenum += body.count('\n', begin, mstart) + 1
1604 linenum += body.count('\n', begin, mstart) + 1
1618 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1605 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1619 begin = body.find('\n', mend) + 1 or len(body)
1606 begin = body.find('\n', mend) + 1 or len(body)
1620 lend = begin - 1
1607 lend = begin - 1
1621 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1608 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1622
1609
1623 class linestate(object):
1610 class linestate(object):
1624 def __init__(self, line, linenum, colstart, colend):
1611 def __init__(self, line, linenum, colstart, colend):
1625 self.line = line
1612 self.line = line
1626 self.linenum = linenum
1613 self.linenum = linenum
1627 self.colstart = colstart
1614 self.colstart = colstart
1628 self.colend = colend
1615 self.colend = colend
1629
1616
1630 def __hash__(self):
1617 def __hash__(self):
1631 return hash((self.linenum, self.line))
1618 return hash((self.linenum, self.line))
1632
1619
1633 def __eq__(self, other):
1620 def __eq__(self, other):
1634 return self.line == other.line
1621 return self.line == other.line
1635
1622
1636 matches = {}
1623 matches = {}
1637 copies = {}
1624 copies = {}
1638 def grepbody(fn, rev, body):
1625 def grepbody(fn, rev, body):
1639 matches[rev].setdefault(fn, [])
1626 matches[rev].setdefault(fn, [])
1640 m = matches[rev][fn]
1627 m = matches[rev][fn]
1641 for lnum, cstart, cend, line in matchlines(body):
1628 for lnum, cstart, cend, line in matchlines(body):
1642 s = linestate(line, lnum, cstart, cend)
1629 s = linestate(line, lnum, cstart, cend)
1643 m.append(s)
1630 m.append(s)
1644
1631
1645 def difflinestates(a, b):
1632 def difflinestates(a, b):
1646 sm = difflib.SequenceMatcher(None, a, b)
1633 sm = difflib.SequenceMatcher(None, a, b)
1647 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1634 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1648 if tag == 'insert':
1635 if tag == 'insert':
1649 for i in xrange(blo, bhi):
1636 for i in xrange(blo, bhi):
1650 yield ('+', b[i])
1637 yield ('+', b[i])
1651 elif tag == 'delete':
1638 elif tag == 'delete':
1652 for i in xrange(alo, ahi):
1639 for i in xrange(alo, ahi):
1653 yield ('-', a[i])
1640 yield ('-', a[i])
1654 elif tag == 'replace':
1641 elif tag == 'replace':
1655 for i in xrange(alo, ahi):
1642 for i in xrange(alo, ahi):
1656 yield ('-', a[i])
1643 yield ('-', a[i])
1657 for i in xrange(blo, bhi):
1644 for i in xrange(blo, bhi):
1658 yield ('+', b[i])
1645 yield ('+', b[i])
1659
1646
1660 def display(fn, ctx, pstates, states):
1647 def display(fn, ctx, pstates, states):
1661 rev = ctx.rev()
1648 rev = ctx.rev()
1662 datefunc = ui.quiet and util.shortdate or util.datestr
1649 datefunc = ui.quiet and util.shortdate or util.datestr
1663 found = False
1650 found = False
1664 filerevmatches = {}
1651 filerevmatches = {}
1665 if opts.get('all'):
1652 if opts.get('all'):
1666 iter = difflinestates(pstates, states)
1653 iter = difflinestates(pstates, states)
1667 else:
1654 else:
1668 iter = [('', l) for l in states]
1655 iter = [('', l) for l in states]
1669 for change, l in iter:
1656 for change, l in iter:
1670 cols = [fn, str(rev)]
1657 cols = [fn, str(rev)]
1671 before, match, after = None, None, None
1658 before, match, after = None, None, None
1672 if opts.get('line_number'):
1659 if opts.get('line_number'):
1673 cols.append(str(l.linenum))
1660 cols.append(str(l.linenum))
1674 if opts.get('all'):
1661 if opts.get('all'):
1675 cols.append(change)
1662 cols.append(change)
1676 if opts.get('user'):
1663 if opts.get('user'):
1677 cols.append(ui.shortuser(ctx.user()))
1664 cols.append(ui.shortuser(ctx.user()))
1678 if opts.get('date'):
1665 if opts.get('date'):
1679 cols.append(datefunc(ctx.date()))
1666 cols.append(datefunc(ctx.date()))
1680 if opts.get('files_with_matches'):
1667 if opts.get('files_with_matches'):
1681 c = (fn, rev)
1668 c = (fn, rev)
1682 if c in filerevmatches:
1669 if c in filerevmatches:
1683 continue
1670 continue
1684 filerevmatches[c] = 1
1671 filerevmatches[c] = 1
1685 else:
1672 else:
1686 before = l.line[:l.colstart]
1673 before = l.line[:l.colstart]
1687 match = l.line[l.colstart:l.colend]
1674 match = l.line[l.colstart:l.colend]
1688 after = l.line[l.colend:]
1675 after = l.line[l.colend:]
1689 ui.write(sep.join(cols))
1676 ui.write(sep.join(cols))
1690 if before is not None:
1677 if before is not None:
1691 ui.write(sep + before)
1678 ui.write(sep + before)
1692 ui.write(match, label='grep.match')
1679 ui.write(match, label='grep.match')
1693 ui.write(after)
1680 ui.write(after)
1694 ui.write(eol)
1681 ui.write(eol)
1695 found = True
1682 found = True
1696 return found
1683 return found
1697
1684
1698 skip = {}
1685 skip = {}
1699 revfiles = {}
1686 revfiles = {}
1700 matchfn = cmdutil.match(repo, pats, opts)
1687 matchfn = cmdutil.match(repo, pats, opts)
1701 found = False
1688 found = False
1702 follow = opts.get('follow')
1689 follow = opts.get('follow')
1703
1690
1704 def prep(ctx, fns):
1691 def prep(ctx, fns):
1705 rev = ctx.rev()
1692 rev = ctx.rev()
1706 pctx = ctx.parents()[0]
1693 pctx = ctx.parents()[0]
1707 parent = pctx.rev()
1694 parent = pctx.rev()
1708 matches.setdefault(rev, {})
1695 matches.setdefault(rev, {})
1709 matches.setdefault(parent, {})
1696 matches.setdefault(parent, {})
1710 files = revfiles.setdefault(rev, [])
1697 files = revfiles.setdefault(rev, [])
1711 for fn in fns:
1698 for fn in fns:
1712 flog = getfile(fn)
1699 flog = getfile(fn)
1713 try:
1700 try:
1714 fnode = ctx.filenode(fn)
1701 fnode = ctx.filenode(fn)
1715 except error.LookupError:
1702 except error.LookupError:
1716 continue
1703 continue
1717
1704
1718 copied = flog.renamed(fnode)
1705 copied = flog.renamed(fnode)
1719 copy = follow and copied and copied[0]
1706 copy = follow and copied and copied[0]
1720 if copy:
1707 if copy:
1721 copies.setdefault(rev, {})[fn] = copy
1708 copies.setdefault(rev, {})[fn] = copy
1722 if fn in skip:
1709 if fn in skip:
1723 if copy:
1710 if copy:
1724 skip[copy] = True
1711 skip[copy] = True
1725 continue
1712 continue
1726 files.append(fn)
1713 files.append(fn)
1727
1714
1728 if fn not in matches[rev]:
1715 if fn not in matches[rev]:
1729 grepbody(fn, rev, flog.read(fnode))
1716 grepbody(fn, rev, flog.read(fnode))
1730
1717
1731 pfn = copy or fn
1718 pfn = copy or fn
1732 if pfn not in matches[parent]:
1719 if pfn not in matches[parent]:
1733 try:
1720 try:
1734 fnode = pctx.filenode(pfn)
1721 fnode = pctx.filenode(pfn)
1735 grepbody(pfn, parent, flog.read(fnode))
1722 grepbody(pfn, parent, flog.read(fnode))
1736 except error.LookupError:
1723 except error.LookupError:
1737 pass
1724 pass
1738
1725
1739 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1726 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1740 rev = ctx.rev()
1727 rev = ctx.rev()
1741 parent = ctx.parents()[0].rev()
1728 parent = ctx.parents()[0].rev()
1742 for fn in sorted(revfiles.get(rev, [])):
1729 for fn in sorted(revfiles.get(rev, [])):
1743 states = matches[rev][fn]
1730 states = matches[rev][fn]
1744 copy = copies.get(rev, {}).get(fn)
1731 copy = copies.get(rev, {}).get(fn)
1745 if fn in skip:
1732 if fn in skip:
1746 if copy:
1733 if copy:
1747 skip[copy] = True
1734 skip[copy] = True
1748 continue
1735 continue
1749 pstates = matches.get(parent, {}).get(copy or fn, [])
1736 pstates = matches.get(parent, {}).get(copy or fn, [])
1750 if pstates or states:
1737 if pstates or states:
1751 r = display(fn, ctx, pstates, states)
1738 r = display(fn, ctx, pstates, states)
1752 found = found or r
1739 found = found or r
1753 if r and not opts.get('all'):
1740 if r and not opts.get('all'):
1754 skip[fn] = True
1741 skip[fn] = True
1755 if copy:
1742 if copy:
1756 skip[copy] = True
1743 skip[copy] = True
1757 del matches[rev]
1744 del matches[rev]
1758 del revfiles[rev]
1745 del revfiles[rev]
1759
1746
1760 return not found
1747 return not found
1761
1748
1762 def heads(ui, repo, *branchrevs, **opts):
1749 def heads(ui, repo, *branchrevs, **opts):
1763 """show current repository heads or show branch heads
1750 """show current repository heads or show branch heads
1764
1751
1765 With no arguments, show all repository branch heads.
1752 With no arguments, show all repository branch heads.
1766
1753
1767 Repository "heads" are changesets with no child changesets. They are
1754 Repository "heads" are changesets with no child changesets. They are
1768 where development generally takes place and are the usual targets
1755 where development generally takes place and are the usual targets
1769 for update and merge operations. Branch heads are changesets that have
1756 for update and merge operations. Branch heads are changesets that have
1770 no child changeset on the same branch.
1757 no child changeset on the same branch.
1771
1758
1772 If one or more REVs are given, only branch heads on the branches
1759 If one or more REVs are given, only branch heads on the branches
1773 associated with the specified changesets are shown.
1760 associated with the specified changesets are shown.
1774
1761
1775 If -c/--closed is specified, also show branch heads marked closed
1762 If -c/--closed is specified, also show branch heads marked closed
1776 (see :hg:`commit --close-branch`).
1763 (see :hg:`commit --close-branch`).
1777
1764
1778 If STARTREV is specified, only those heads that are descendants of
1765 If STARTREV is specified, only those heads that are descendants of
1779 STARTREV will be displayed.
1766 STARTREV will be displayed.
1780
1767
1781 If -t/--topo is specified, named branch mechanics will be ignored and only
1768 If -t/--topo is specified, named branch mechanics will be ignored and only
1782 changesets without children will be shown.
1769 changesets without children will be shown.
1783
1770
1784 Returns 0 if matching heads are found, 1 if not.
1771 Returns 0 if matching heads are found, 1 if not.
1785 """
1772 """
1786
1773
1787 if opts.get('rev'):
1774 if opts.get('rev'):
1788 start = repo.lookup(opts['rev'])
1775 start = repo.lookup(opts['rev'])
1789 else:
1776 else:
1790 start = None
1777 start = None
1791
1778
1792 if opts.get('topo'):
1779 if opts.get('topo'):
1793 heads = [repo[h] for h in repo.heads(start)]
1780 heads = [repo[h] for h in repo.heads(start)]
1794 else:
1781 else:
1795 heads = []
1782 heads = []
1796 for b, ls in repo.branchmap().iteritems():
1783 for b, ls in repo.branchmap().iteritems():
1797 if start is None:
1784 if start is None:
1798 heads += [repo[h] for h in ls]
1785 heads += [repo[h] for h in ls]
1799 continue
1786 continue
1800 startrev = repo.changelog.rev(start)
1787 startrev = repo.changelog.rev(start)
1801 descendants = set(repo.changelog.descendants(startrev))
1788 descendants = set(repo.changelog.descendants(startrev))
1802 descendants.add(startrev)
1789 descendants.add(startrev)
1803 rev = repo.changelog.rev
1790 rev = repo.changelog.rev
1804 heads += [repo[h] for h in ls if rev(h) in descendants]
1791 heads += [repo[h] for h in ls if rev(h) in descendants]
1805
1792
1806 if branchrevs:
1793 if branchrevs:
1807 decode, encode = encoding.fromlocal, encoding.tolocal
1794 decode, encode = encoding.fromlocal, encoding.tolocal
1808 branches = set(repo[decode(br)].branch() for br in branchrevs)
1795 branches = set(repo[decode(br)].branch() for br in branchrevs)
1809 heads = [h for h in heads if h.branch() in branches]
1796 heads = [h for h in heads if h.branch() in branches]
1810
1797
1811 if not opts.get('closed'):
1798 if not opts.get('closed'):
1812 heads = [h for h in heads if not h.extra().get('close')]
1799 heads = [h for h in heads if not h.extra().get('close')]
1813
1800
1814 if opts.get('active') and branchrevs:
1801 if opts.get('active') and branchrevs:
1815 dagheads = repo.heads(start)
1802 dagheads = repo.heads(start)
1816 heads = [h for h in heads if h.node() in dagheads]
1803 heads = [h for h in heads if h.node() in dagheads]
1817
1804
1818 if branchrevs:
1805 if branchrevs:
1819 haveheads = set(h.branch() for h in heads)
1806 haveheads = set(h.branch() for h in heads)
1820 if branches - haveheads:
1807 if branches - haveheads:
1821 headless = ', '.join(encode(b) for b in branches - haveheads)
1808 headless = ', '.join(encode(b) for b in branches - haveheads)
1822 msg = _('no open branch heads found on branches %s')
1809 msg = _('no open branch heads found on branches %s')
1823 if opts.get('rev'):
1810 if opts.get('rev'):
1824 msg += _(' (started at %s)' % opts['rev'])
1811 msg += _(' (started at %s)' % opts['rev'])
1825 ui.warn((msg + '\n') % headless)
1812 ui.warn((msg + '\n') % headless)
1826
1813
1827 if not heads:
1814 if not heads:
1828 return 1
1815 return 1
1829
1816
1830 heads = sorted(heads, key=lambda x: -x.rev())
1817 heads = sorted(heads, key=lambda x: -x.rev())
1831 displayer = cmdutil.show_changeset(ui, repo, opts)
1818 displayer = cmdutil.show_changeset(ui, repo, opts)
1832 for ctx in heads:
1819 for ctx in heads:
1833 displayer.show(ctx)
1820 displayer.show(ctx)
1834 displayer.close()
1821 displayer.close()
1835
1822
1836 def help_(ui, name=None, with_version=False, unknowncmd=False):
1823 def help_(ui, name=None, with_version=False, unknowncmd=False):
1837 """show help for a given topic or a help overview
1824 """show help for a given topic or a help overview
1838
1825
1839 With no arguments, print a list of commands with short help messages.
1826 With no arguments, print a list of commands with short help messages.
1840
1827
1841 Given a topic, extension, or command name, print help for that
1828 Given a topic, extension, or command name, print help for that
1842 topic.
1829 topic.
1843
1830
1844 Returns 0 if successful.
1831 Returns 0 if successful.
1845 """
1832 """
1846 option_lists = []
1833 option_lists = []
1847 textwidth = util.termwidth() - 2
1834 textwidth = util.termwidth() - 2
1848
1835
1849 def addglobalopts(aliases):
1836 def addglobalopts(aliases):
1850 if ui.verbose:
1837 if ui.verbose:
1851 option_lists.append((_("global options:"), globalopts))
1838 option_lists.append((_("global options:"), globalopts))
1852 if name == 'shortlist':
1839 if name == 'shortlist':
1853 option_lists.append((_('use "hg help" for the full list '
1840 option_lists.append((_('use "hg help" for the full list '
1854 'of commands'), ()))
1841 'of commands'), ()))
1855 else:
1842 else:
1856 if name == 'shortlist':
1843 if name == 'shortlist':
1857 msg = _('use "hg help" for the full list of commands '
1844 msg = _('use "hg help" for the full list of commands '
1858 'or "hg -v" for details')
1845 'or "hg -v" for details')
1859 elif aliases:
1846 elif aliases:
1860 msg = _('use "hg -v help%s" to show aliases and '
1847 msg = _('use "hg -v help%s" to show aliases and '
1861 'global options') % (name and " " + name or "")
1848 'global options') % (name and " " + name or "")
1862 else:
1849 else:
1863 msg = _('use "hg -v help %s" to show global options') % name
1850 msg = _('use "hg -v help %s" to show global options') % name
1864 option_lists.append((msg, ()))
1851 option_lists.append((msg, ()))
1865
1852
1866 def helpcmd(name):
1853 def helpcmd(name):
1867 if with_version:
1854 if with_version:
1868 version_(ui)
1855 version_(ui)
1869 ui.write('\n')
1856 ui.write('\n')
1870
1857
1871 try:
1858 try:
1872 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1859 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1873 except error.AmbiguousCommand, inst:
1860 except error.AmbiguousCommand, inst:
1874 # py3k fix: except vars can't be used outside the scope of the
1861 # py3k fix: except vars can't be used outside the scope of the
1875 # except block, nor can be used inside a lambda. python issue4617
1862 # except block, nor can be used inside a lambda. python issue4617
1876 prefix = inst.args[0]
1863 prefix = inst.args[0]
1877 select = lambda c: c.lstrip('^').startswith(prefix)
1864 select = lambda c: c.lstrip('^').startswith(prefix)
1878 helplist(_('list of commands:\n\n'), select)
1865 helplist(_('list of commands:\n\n'), select)
1879 return
1866 return
1880
1867
1881 # check if it's an invalid alias and display its error if it is
1868 # check if it's an invalid alias and display its error if it is
1882 if getattr(entry[0], 'badalias', False):
1869 if getattr(entry[0], 'badalias', False):
1883 if not unknowncmd:
1870 if not unknowncmd:
1884 entry[0](ui)
1871 entry[0](ui)
1885 return
1872 return
1886
1873
1887 # synopsis
1874 # synopsis
1888 if len(entry) > 2:
1875 if len(entry) > 2:
1889 if entry[2].startswith('hg'):
1876 if entry[2].startswith('hg'):
1890 ui.write("%s\n" % entry[2])
1877 ui.write("%s\n" % entry[2])
1891 else:
1878 else:
1892 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1879 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1893 else:
1880 else:
1894 ui.write('hg %s\n' % aliases[0])
1881 ui.write('hg %s\n' % aliases[0])
1895
1882
1896 # aliases
1883 # aliases
1897 if not ui.quiet and len(aliases) > 1:
1884 if not ui.quiet and len(aliases) > 1:
1898 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1885 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1899
1886
1900 # description
1887 # description
1901 doc = gettext(entry[0].__doc__)
1888 doc = gettext(entry[0].__doc__)
1902 if not doc:
1889 if not doc:
1903 doc = _("(no help text available)")
1890 doc = _("(no help text available)")
1904 if hasattr(entry[0], 'definition'): # aliased command
1891 if hasattr(entry[0], 'definition'): # aliased command
1905 if entry[0].definition.startswith('!'): # shell alias
1892 if entry[0].definition.startswith('!'): # shell alias
1906 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1893 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1907 else:
1894 else:
1908 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1895 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1909 if ui.quiet:
1896 if ui.quiet:
1910 doc = doc.splitlines()[0]
1897 doc = doc.splitlines()[0]
1911 keep = ui.verbose and ['verbose'] or []
1898 keep = ui.verbose and ['verbose'] or []
1912 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1899 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1913 ui.write("\n%s\n" % formatted)
1900 ui.write("\n%s\n" % formatted)
1914 if pruned:
1901 if pruned:
1915 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1902 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1916
1903
1917 if not ui.quiet:
1904 if not ui.quiet:
1918 # options
1905 # options
1919 if entry[1]:
1906 if entry[1]:
1920 option_lists.append((_("options:\n"), entry[1]))
1907 option_lists.append((_("options:\n"), entry[1]))
1921
1908
1922 addglobalopts(False)
1909 addglobalopts(False)
1923
1910
1924 def helplist(header, select=None):
1911 def helplist(header, select=None):
1925 h = {}
1912 h = {}
1926 cmds = {}
1913 cmds = {}
1927 for c, e in table.iteritems():
1914 for c, e in table.iteritems():
1928 f = c.split("|", 1)[0]
1915 f = c.split("|", 1)[0]
1929 if select and not select(f):
1916 if select and not select(f):
1930 continue
1917 continue
1931 if (not select and name != 'shortlist' and
1918 if (not select and name != 'shortlist' and
1932 e[0].__module__ != __name__):
1919 e[0].__module__ != __name__):
1933 continue
1920 continue
1934 if name == "shortlist" and not f.startswith("^"):
1921 if name == "shortlist" and not f.startswith("^"):
1935 continue
1922 continue
1936 f = f.lstrip("^")
1923 f = f.lstrip("^")
1937 if not ui.debugflag and f.startswith("debug"):
1924 if not ui.debugflag and f.startswith("debug"):
1938 continue
1925 continue
1939 doc = e[0].__doc__
1926 doc = e[0].__doc__
1940 if doc and 'DEPRECATED' in doc and not ui.verbose:
1927 if doc and 'DEPRECATED' in doc and not ui.verbose:
1941 continue
1928 continue
1942 doc = gettext(doc)
1929 doc = gettext(doc)
1943 if not doc:
1930 if not doc:
1944 doc = _("(no help text available)")
1931 doc = _("(no help text available)")
1945 h[f] = doc.splitlines()[0].rstrip()
1932 h[f] = doc.splitlines()[0].rstrip()
1946 cmds[f] = c.lstrip("^")
1933 cmds[f] = c.lstrip("^")
1947
1934
1948 if not h:
1935 if not h:
1949 ui.status(_('no commands defined\n'))
1936 ui.status(_('no commands defined\n'))
1950 return
1937 return
1951
1938
1952 ui.status(header)
1939 ui.status(header)
1953 fns = sorted(h)
1940 fns = sorted(h)
1954 m = max(map(len, fns))
1941 m = max(map(len, fns))
1955 for f in fns:
1942 for f in fns:
1956 if ui.verbose:
1943 if ui.verbose:
1957 commands = cmds[f].replace("|",", ")
1944 commands = cmds[f].replace("|",", ")
1958 ui.write(" %s:\n %s\n"%(commands, h[f]))
1945 ui.write(" %s:\n %s\n"%(commands, h[f]))
1959 else:
1946 else:
1960 ui.write('%s\n' % (util.wrap(h[f],
1947 ui.write('%s\n' % (util.wrap(h[f],
1961 initindent=' %-*s ' % (m, f),
1948 initindent=' %-*s ' % (m, f),
1962 hangindent=' ' * (m + 4))))
1949 hangindent=' ' * (m + 4))))
1963
1950
1964 if not ui.quiet:
1951 if not ui.quiet:
1965 addglobalopts(True)
1952 addglobalopts(True)
1966
1953
1967 def helptopic(name):
1954 def helptopic(name):
1968 for names, header, doc in help.helptable:
1955 for names, header, doc in help.helptable:
1969 if name in names:
1956 if name in names:
1970 break
1957 break
1971 else:
1958 else:
1972 raise error.UnknownCommand(name)
1959 raise error.UnknownCommand(name)
1973
1960
1974 # description
1961 # description
1975 if not doc:
1962 if not doc:
1976 doc = _("(no help text available)")
1963 doc = _("(no help text available)")
1977 if hasattr(doc, '__call__'):
1964 if hasattr(doc, '__call__'):
1978 doc = doc()
1965 doc = doc()
1979
1966
1980 ui.write("%s\n\n" % header)
1967 ui.write("%s\n\n" % header)
1981 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1968 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1982
1969
1983 def helpext(name):
1970 def helpext(name):
1984 try:
1971 try:
1985 mod = extensions.find(name)
1972 mod = extensions.find(name)
1986 doc = gettext(mod.__doc__) or _('no help text available')
1973 doc = gettext(mod.__doc__) or _('no help text available')
1987 except KeyError:
1974 except KeyError:
1988 mod = None
1975 mod = None
1989 doc = extensions.disabledext(name)
1976 doc = extensions.disabledext(name)
1990 if not doc:
1977 if not doc:
1991 raise error.UnknownCommand(name)
1978 raise error.UnknownCommand(name)
1992
1979
1993 if '\n' not in doc:
1980 if '\n' not in doc:
1994 head, tail = doc, ""
1981 head, tail = doc, ""
1995 else:
1982 else:
1996 head, tail = doc.split('\n', 1)
1983 head, tail = doc.split('\n', 1)
1997 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1984 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1998 if tail:
1985 if tail:
1999 ui.write(minirst.format(tail, textwidth))
1986 ui.write(minirst.format(tail, textwidth))
2000 ui.status('\n\n')
1987 ui.status('\n\n')
2001
1988
2002 if mod:
1989 if mod:
2003 try:
1990 try:
2004 ct = mod.cmdtable
1991 ct = mod.cmdtable
2005 except AttributeError:
1992 except AttributeError:
2006 ct = {}
1993 ct = {}
2007 modcmds = set([c.split('|', 1)[0] for c in ct])
1994 modcmds = set([c.split('|', 1)[0] for c in ct])
2008 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1995 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2009 else:
1996 else:
2010 ui.write(_('use "hg help extensions" for information on enabling '
1997 ui.write(_('use "hg help extensions" for information on enabling '
2011 'extensions\n'))
1998 'extensions\n'))
2012
1999
2013 def helpextcmd(name):
2000 def helpextcmd(name):
2014 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2001 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2015 doc = gettext(mod.__doc__).splitlines()[0]
2002 doc = gettext(mod.__doc__).splitlines()[0]
2016
2003
2017 msg = help.listexts(_("'%s' is provided by the following "
2004 msg = help.listexts(_("'%s' is provided by the following "
2018 "extension:") % cmd, {ext: doc}, len(ext),
2005 "extension:") % cmd, {ext: doc}, len(ext),
2019 indent=4)
2006 indent=4)
2020 ui.write(minirst.format(msg, textwidth))
2007 ui.write(minirst.format(msg, textwidth))
2021 ui.write('\n\n')
2008 ui.write('\n\n')
2022 ui.write(_('use "hg help extensions" for information on enabling '
2009 ui.write(_('use "hg help extensions" for information on enabling '
2023 'extensions\n'))
2010 'extensions\n'))
2024
2011
2025 if name and name != 'shortlist':
2012 if name and name != 'shortlist':
2026 i = None
2013 i = None
2027 if unknowncmd:
2014 if unknowncmd:
2028 queries = (helpextcmd,)
2015 queries = (helpextcmd,)
2029 else:
2016 else:
2030 queries = (helptopic, helpcmd, helpext, helpextcmd)
2017 queries = (helptopic, helpcmd, helpext, helpextcmd)
2031 for f in queries:
2018 for f in queries:
2032 try:
2019 try:
2033 f(name)
2020 f(name)
2034 i = None
2021 i = None
2035 break
2022 break
2036 except error.UnknownCommand, inst:
2023 except error.UnknownCommand, inst:
2037 i = inst
2024 i = inst
2038 if i:
2025 if i:
2039 raise i
2026 raise i
2040
2027
2041 else:
2028 else:
2042 # program name
2029 # program name
2043 if ui.verbose or with_version:
2030 if ui.verbose or with_version:
2044 version_(ui)
2031 version_(ui)
2045 else:
2032 else:
2046 ui.status(_("Mercurial Distributed SCM\n"))
2033 ui.status(_("Mercurial Distributed SCM\n"))
2047 ui.status('\n')
2034 ui.status('\n')
2048
2035
2049 # list of commands
2036 # list of commands
2050 if name == "shortlist":
2037 if name == "shortlist":
2051 header = _('basic commands:\n\n')
2038 header = _('basic commands:\n\n')
2052 else:
2039 else:
2053 header = _('list of commands:\n\n')
2040 header = _('list of commands:\n\n')
2054
2041
2055 helplist(header)
2042 helplist(header)
2056 if name != 'shortlist':
2043 if name != 'shortlist':
2057 exts, maxlength = extensions.enabled()
2044 exts, maxlength = extensions.enabled()
2058 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2045 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2059 if text:
2046 if text:
2060 ui.write("\n%s\n" % minirst.format(text, textwidth))
2047 ui.write("\n%s\n" % minirst.format(text, textwidth))
2061
2048
2062 # list all option lists
2049 # list all option lists
2063 opt_output = []
2050 opt_output = []
2064 multioccur = False
2051 multioccur = False
2065 for title, options in option_lists:
2052 for title, options in option_lists:
2066 opt_output.append(("\n%s" % title, None))
2053 opt_output.append(("\n%s" % title, None))
2067 for option in options:
2054 for option in options:
2068 if len(option) == 5:
2055 if len(option) == 5:
2069 shortopt, longopt, default, desc, optlabel = option
2056 shortopt, longopt, default, desc, optlabel = option
2070 else:
2057 else:
2071 shortopt, longopt, default, desc = option
2058 shortopt, longopt, default, desc = option
2072 optlabel = _("VALUE") # default label
2059 optlabel = _("VALUE") # default label
2073
2060
2074 if _("DEPRECATED") in desc and not ui.verbose:
2061 if _("DEPRECATED") in desc and not ui.verbose:
2075 continue
2062 continue
2076 if isinstance(default, list):
2063 if isinstance(default, list):
2077 numqualifier = " %s [+]" % optlabel
2064 numqualifier = " %s [+]" % optlabel
2078 multioccur = True
2065 multioccur = True
2079 elif (default is not None) and not isinstance(default, bool):
2066 elif (default is not None) and not isinstance(default, bool):
2080 numqualifier = " %s" % optlabel
2067 numqualifier = " %s" % optlabel
2081 else:
2068 else:
2082 numqualifier = ""
2069 numqualifier = ""
2083 opt_output.append(("%2s%s" %
2070 opt_output.append(("%2s%s" %
2084 (shortopt and "-%s" % shortopt,
2071 (shortopt and "-%s" % shortopt,
2085 longopt and " --%s%s" %
2072 longopt and " --%s%s" %
2086 (longopt, numqualifier)),
2073 (longopt, numqualifier)),
2087 "%s%s" % (desc,
2074 "%s%s" % (desc,
2088 default
2075 default
2089 and _(" (default: %s)") % default
2076 and _(" (default: %s)") % default
2090 or "")))
2077 or "")))
2091 if multioccur:
2078 if multioccur:
2092 msg = _("\n[+] marked option can be specified multiple times")
2079 msg = _("\n[+] marked option can be specified multiple times")
2093 if ui.verbose and name != 'shortlist':
2080 if ui.verbose and name != 'shortlist':
2094 opt_output.append((msg, None))
2081 opt_output.append((msg, None))
2095 else:
2082 else:
2096 opt_output.insert(-1, (msg, None))
2083 opt_output.insert(-1, (msg, None))
2097
2084
2098 if not name:
2085 if not name:
2099 ui.write(_("\nadditional help topics:\n\n"))
2086 ui.write(_("\nadditional help topics:\n\n"))
2100 topics = []
2087 topics = []
2101 for names, header, doc in help.helptable:
2088 for names, header, doc in help.helptable:
2102 topics.append((sorted(names, key=len, reverse=True)[0], header))
2089 topics.append((sorted(names, key=len, reverse=True)[0], header))
2103 topics_len = max([len(s[0]) for s in topics])
2090 topics_len = max([len(s[0]) for s in topics])
2104 for t, desc in topics:
2091 for t, desc in topics:
2105 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2092 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2106
2093
2107 if opt_output:
2094 if opt_output:
2108 colwidth = encoding.colwidth
2095 colwidth = encoding.colwidth
2109 # normalize: (opt or message, desc or None, width of opt)
2096 # normalize: (opt or message, desc or None, width of opt)
2110 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2097 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2111 for opt, desc in opt_output]
2098 for opt, desc in opt_output]
2112 hanging = max([e[2] for e in entries])
2099 hanging = max([e[2] for e in entries])
2113 for opt, desc, width in entries:
2100 for opt, desc, width in entries:
2114 if desc:
2101 if desc:
2115 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2102 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2116 hangindent = ' ' * (hanging + 3)
2103 hangindent = ' ' * (hanging + 3)
2117 ui.write('%s\n' % (util.wrap(desc,
2104 ui.write('%s\n' % (util.wrap(desc,
2118 initindent=initindent,
2105 initindent=initindent,
2119 hangindent=hangindent)))
2106 hangindent=hangindent)))
2120 else:
2107 else:
2121 ui.write("%s\n" % opt)
2108 ui.write("%s\n" % opt)
2122
2109
2123 def identify(ui, repo, source=None,
2110 def identify(ui, repo, source=None,
2124 rev=None, num=None, id=None, branch=None, tags=None):
2111 rev=None, num=None, id=None, branch=None, tags=None):
2125 """identify the working copy or specified revision
2112 """identify the working copy or specified revision
2126
2113
2127 With no revision, print a summary of the current state of the
2114 With no revision, print a summary of the current state of the
2128 repository.
2115 repository.
2129
2116
2130 Specifying a path to a repository root or Mercurial bundle will
2117 Specifying a path to a repository root or Mercurial bundle will
2131 cause lookup to operate on that repository/bundle.
2118 cause lookup to operate on that repository/bundle.
2132
2119
2133 This summary identifies the repository state using one or two
2120 This summary identifies the repository state using one or two
2134 parent hash identifiers, followed by a "+" if there are
2121 parent hash identifiers, followed by a "+" if there are
2135 uncommitted changes in the working directory, a list of tags for
2122 uncommitted changes in the working directory, a list of tags for
2136 this revision and a branch name for non-default branches.
2123 this revision and a branch name for non-default branches.
2137
2124
2138 Returns 0 if successful.
2125 Returns 0 if successful.
2139 """
2126 """
2140
2127
2141 if not repo and not source:
2128 if not repo and not source:
2142 raise util.Abort(_("there is no Mercurial repository here "
2129 raise util.Abort(_("there is no Mercurial repository here "
2143 "(.hg not found)"))
2130 "(.hg not found)"))
2144
2131
2145 hexfunc = ui.debugflag and hex or short
2132 hexfunc = ui.debugflag and hex or short
2146 default = not (num or id or branch or tags)
2133 default = not (num or id or branch or tags)
2147 output = []
2134 output = []
2148
2135
2149 revs = []
2136 revs = []
2150 if source:
2137 if source:
2151 source, branches = hg.parseurl(ui.expandpath(source))
2138 source, branches = hg.parseurl(ui.expandpath(source))
2152 repo = hg.repository(ui, source)
2139 repo = hg.repository(ui, source)
2153 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2140 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2154
2141
2155 if not repo.local():
2142 if not repo.local():
2156 if not rev and revs:
2143 if not rev and revs:
2157 rev = revs[0]
2144 rev = revs[0]
2158 if not rev:
2145 if not rev:
2159 rev = "tip"
2146 rev = "tip"
2160 if num or branch or tags:
2147 if num or branch or tags:
2161 raise util.Abort(
2148 raise util.Abort(
2162 "can't query remote revision number, branch, or tags")
2149 "can't query remote revision number, branch, or tags")
2163 output = [hexfunc(repo.lookup(rev))]
2150 output = [hexfunc(repo.lookup(rev))]
2164 elif not rev:
2151 elif not rev:
2165 ctx = repo[None]
2152 ctx = repo[None]
2166 parents = ctx.parents()
2153 parents = ctx.parents()
2167 changed = False
2154 changed = False
2168 if default or id or num:
2155 if default or id or num:
2169 changed = util.any(repo.status())
2156 changed = util.any(repo.status())
2170 if default or id:
2157 if default or id:
2171 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2158 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2172 (changed) and "+" or "")]
2159 (changed) and "+" or "")]
2173 if num:
2160 if num:
2174 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2161 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2175 (changed) and "+" or ""))
2162 (changed) and "+" or ""))
2176 else:
2163 else:
2177 ctx = repo[rev]
2164 ctx = repo[rev]
2178 if default or id:
2165 if default or id:
2179 output = [hexfunc(ctx.node())]
2166 output = [hexfunc(ctx.node())]
2180 if num:
2167 if num:
2181 output.append(str(ctx.rev()))
2168 output.append(str(ctx.rev()))
2182
2169
2183 if repo.local() and default and not ui.quiet:
2170 if repo.local() and default and not ui.quiet:
2184 b = encoding.tolocal(ctx.branch())
2171 b = encoding.tolocal(ctx.branch())
2185 if b != 'default':
2172 if b != 'default':
2186 output.append("(%s)" % b)
2173 output.append("(%s)" % b)
2187
2174
2188 # multiple tags for a single parent separated by '/'
2175 # multiple tags for a single parent separated by '/'
2189 t = "/".join(ctx.tags())
2176 t = "/".join(ctx.tags())
2190 if t:
2177 if t:
2191 output.append(t)
2178 output.append(t)
2192
2179
2193 if branch:
2180 if branch:
2194 output.append(encoding.tolocal(ctx.branch()))
2181 output.append(encoding.tolocal(ctx.branch()))
2195
2182
2196 if tags:
2183 if tags:
2197 output.extend(ctx.tags())
2184 output.extend(ctx.tags())
2198
2185
2199 ui.write("%s\n" % ' '.join(output))
2186 ui.write("%s\n" % ' '.join(output))
2200
2187
2201 def import_(ui, repo, patch1, *patches, **opts):
2188 def import_(ui, repo, patch1, *patches, **opts):
2202 """import an ordered set of patches
2189 """import an ordered set of patches
2203
2190
2204 Import a list of patches and commit them individually (unless
2191 Import a list of patches and commit them individually (unless
2205 --no-commit is specified).
2192 --no-commit is specified).
2206
2193
2207 If there are outstanding changes in the working directory, import
2194 If there are outstanding changes in the working directory, import
2208 will abort unless given the -f/--force flag.
2195 will abort unless given the -f/--force flag.
2209
2196
2210 You can import a patch straight from a mail message. Even patches
2197 You can import a patch straight from a mail message. Even patches
2211 as attachments work (to use the body part, it must have type
2198 as attachments work (to use the body part, it must have type
2212 text/plain or text/x-patch). From and Subject headers of email
2199 text/plain or text/x-patch). From and Subject headers of email
2213 message are used as default committer and commit message. All
2200 message are used as default committer and commit message. All
2214 text/plain body parts before first diff are added to commit
2201 text/plain body parts before first diff are added to commit
2215 message.
2202 message.
2216
2203
2217 If the imported patch was generated by :hg:`export`, user and
2204 If the imported patch was generated by :hg:`export`, user and
2218 description from patch override values from message headers and
2205 description from patch override values from message headers and
2219 body. Values given on command line with -m/--message and -u/--user
2206 body. Values given on command line with -m/--message and -u/--user
2220 override these.
2207 override these.
2221
2208
2222 If --exact is specified, import will set the working directory to
2209 If --exact is specified, import will set the working directory to
2223 the parent of each patch before applying it, and will abort if the
2210 the parent of each patch before applying it, and will abort if the
2224 resulting changeset has a different ID than the one recorded in
2211 resulting changeset has a different ID than the one recorded in
2225 the patch. This may happen due to character set problems or other
2212 the patch. This may happen due to character set problems or other
2226 deficiencies in the text patch format.
2213 deficiencies in the text patch format.
2227
2214
2228 With -s/--similarity, hg will attempt to discover renames and
2215 With -s/--similarity, hg will attempt to discover renames and
2229 copies in the patch in the same way as 'addremove'.
2216 copies in the patch in the same way as 'addremove'.
2230
2217
2231 To read a patch from standard input, use "-" as the patch name. If
2218 To read a patch from standard input, use "-" as the patch name. If
2232 a URL is specified, the patch will be downloaded from it.
2219 a URL is specified, the patch will be downloaded from it.
2233 See :hg:`help dates` for a list of formats valid for -d/--date.
2220 See :hg:`help dates` for a list of formats valid for -d/--date.
2234
2221
2235 Returns 0 on success.
2222 Returns 0 on success.
2236 """
2223 """
2237 patches = (patch1,) + patches
2224 patches = (patch1,) + patches
2238
2225
2239 date = opts.get('date')
2226 date = opts.get('date')
2240 if date:
2227 if date:
2241 opts['date'] = util.parsedate(date)
2228 opts['date'] = util.parsedate(date)
2242
2229
2243 try:
2230 try:
2244 sim = float(opts.get('similarity') or 0)
2231 sim = float(opts.get('similarity') or 0)
2245 except ValueError:
2232 except ValueError:
2246 raise util.Abort(_('similarity must be a number'))
2233 raise util.Abort(_('similarity must be a number'))
2247 if sim < 0 or sim > 100:
2234 if sim < 0 or sim > 100:
2248 raise util.Abort(_('similarity must be between 0 and 100'))
2235 raise util.Abort(_('similarity must be between 0 and 100'))
2249
2236
2250 if opts.get('exact') or not opts.get('force'):
2237 if opts.get('exact') or not opts.get('force'):
2251 cmdutil.bail_if_changed(repo)
2238 cmdutil.bail_if_changed(repo)
2252
2239
2253 d = opts["base"]
2240 d = opts["base"]
2254 strip = opts["strip"]
2241 strip = opts["strip"]
2255 wlock = lock = None
2242 wlock = lock = None
2256
2243
2257 def tryone(ui, hunk):
2244 def tryone(ui, hunk):
2258 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2245 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2259 patch.extract(ui, hunk)
2246 patch.extract(ui, hunk)
2260
2247
2261 if not tmpname:
2248 if not tmpname:
2262 return None
2249 return None
2263 commitid = _('to working directory')
2250 commitid = _('to working directory')
2264
2251
2265 try:
2252 try:
2266 cmdline_message = cmdutil.logmessage(opts)
2253 cmdline_message = cmdutil.logmessage(opts)
2267 if cmdline_message:
2254 if cmdline_message:
2268 # pickup the cmdline msg
2255 # pickup the cmdline msg
2269 message = cmdline_message
2256 message = cmdline_message
2270 elif message:
2257 elif message:
2271 # pickup the patch msg
2258 # pickup the patch msg
2272 message = message.strip()
2259 message = message.strip()
2273 else:
2260 else:
2274 # launch the editor
2261 # launch the editor
2275 message = None
2262 message = None
2276 ui.debug('message:\n%s\n' % message)
2263 ui.debug('message:\n%s\n' % message)
2277
2264
2278 wp = repo.parents()
2265 wp = repo.parents()
2279 if opts.get('exact'):
2266 if opts.get('exact'):
2280 if not nodeid or not p1:
2267 if not nodeid or not p1:
2281 raise util.Abort(_('not a Mercurial patch'))
2268 raise util.Abort(_('not a Mercurial patch'))
2282 p1 = repo.lookup(p1)
2269 p1 = repo.lookup(p1)
2283 p2 = repo.lookup(p2 or hex(nullid))
2270 p2 = repo.lookup(p2 or hex(nullid))
2284
2271
2285 if p1 != wp[0].node():
2272 if p1 != wp[0].node():
2286 hg.clean(repo, p1)
2273 hg.clean(repo, p1)
2287 repo.dirstate.setparents(p1, p2)
2274 repo.dirstate.setparents(p1, p2)
2288 elif p2:
2275 elif p2:
2289 try:
2276 try:
2290 p1 = repo.lookup(p1)
2277 p1 = repo.lookup(p1)
2291 p2 = repo.lookup(p2)
2278 p2 = repo.lookup(p2)
2292 if p1 == wp[0].node():
2279 if p1 == wp[0].node():
2293 repo.dirstate.setparents(p1, p2)
2280 repo.dirstate.setparents(p1, p2)
2294 except error.RepoError:
2281 except error.RepoError:
2295 pass
2282 pass
2296 if opts.get('exact') or opts.get('import_branch'):
2283 if opts.get('exact') or opts.get('import_branch'):
2297 repo.dirstate.setbranch(branch or 'default')
2284 repo.dirstate.setbranch(branch or 'default')
2298
2285
2299 files = {}
2286 files = {}
2300 try:
2287 try:
2301 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2288 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2302 files=files, eolmode=None)
2289 files=files, eolmode=None)
2303 finally:
2290 finally:
2304 files = cmdutil.updatedir(ui, repo, files,
2291 files = cmdutil.updatedir(ui, repo, files,
2305 similarity=sim / 100.0)
2292 similarity=sim / 100.0)
2306 if not opts.get('no_commit'):
2293 if not opts.get('no_commit'):
2307 if opts.get('exact'):
2294 if opts.get('exact'):
2308 m = None
2295 m = None
2309 else:
2296 else:
2310 m = cmdutil.matchfiles(repo, files or [])
2297 m = cmdutil.matchfiles(repo, files or [])
2311 n = repo.commit(message, opts.get('user') or user,
2298 n = repo.commit(message, opts.get('user') or user,
2312 opts.get('date') or date, match=m,
2299 opts.get('date') or date, match=m,
2313 editor=cmdutil.commiteditor)
2300 editor=cmdutil.commiteditor)
2314 if opts.get('exact'):
2301 if opts.get('exact'):
2315 if hex(n) != nodeid:
2302 if hex(n) != nodeid:
2316 repo.rollback()
2303 repo.rollback()
2317 raise util.Abort(_('patch is damaged'
2304 raise util.Abort(_('patch is damaged'
2318 ' or loses information'))
2305 ' or loses information'))
2319 # Force a dirstate write so that the next transaction
2306 # Force a dirstate write so that the next transaction
2320 # backups an up-do-date file.
2307 # backups an up-do-date file.
2321 repo.dirstate.write()
2308 repo.dirstate.write()
2322 if n:
2309 if n:
2323 commitid = short(n)
2310 commitid = short(n)
2324
2311
2325 return commitid
2312 return commitid
2326 finally:
2313 finally:
2327 os.unlink(tmpname)
2314 os.unlink(tmpname)
2328
2315
2329 try:
2316 try:
2330 wlock = repo.wlock()
2317 wlock = repo.wlock()
2331 lock = repo.lock()
2318 lock = repo.lock()
2332 lastcommit = None
2319 lastcommit = None
2333 for p in patches:
2320 for p in patches:
2334 pf = os.path.join(d, p)
2321 pf = os.path.join(d, p)
2335
2322
2336 if pf == '-':
2323 if pf == '-':
2337 ui.status(_("applying patch from stdin\n"))
2324 ui.status(_("applying patch from stdin\n"))
2338 pf = sys.stdin
2325 pf = sys.stdin
2339 else:
2326 else:
2340 ui.status(_("applying %s\n") % p)
2327 ui.status(_("applying %s\n") % p)
2341 pf = url.open(ui, pf)
2328 pf = url.open(ui, pf)
2342
2329
2343 haspatch = False
2330 haspatch = False
2344 for hunk in patch.split(pf):
2331 for hunk in patch.split(pf):
2345 commitid = tryone(ui, hunk)
2332 commitid = tryone(ui, hunk)
2346 if commitid:
2333 if commitid:
2347 haspatch = True
2334 haspatch = True
2348 if lastcommit:
2335 if lastcommit:
2349 ui.status(_('applied %s\n') % lastcommit)
2336 ui.status(_('applied %s\n') % lastcommit)
2350 lastcommit = commitid
2337 lastcommit = commitid
2351
2338
2352 if not haspatch:
2339 if not haspatch:
2353 raise util.Abort(_('no diffs found'))
2340 raise util.Abort(_('no diffs found'))
2354
2341
2355 finally:
2342 finally:
2356 release(lock, wlock)
2343 release(lock, wlock)
2357
2344
2358 def incoming(ui, repo, source="default", **opts):
2345 def incoming(ui, repo, source="default", **opts):
2359 """show new changesets found in source
2346 """show new changesets found in source
2360
2347
2361 Show new changesets found in the specified path/URL or the default
2348 Show new changesets found in the specified path/URL or the default
2362 pull location. These are the changesets that would have been pulled
2349 pull location. These are the changesets that would have been pulled
2363 if a pull at the time you issued this command.
2350 if a pull at the time you issued this command.
2364
2351
2365 For remote repository, using --bundle avoids downloading the
2352 For remote repository, using --bundle avoids downloading the
2366 changesets twice if the incoming is followed by a pull.
2353 changesets twice if the incoming is followed by a pull.
2367
2354
2368 See pull for valid source format details.
2355 See pull for valid source format details.
2369
2356
2370 Returns 0 if there are incoming changes, 1 otherwise.
2357 Returns 0 if there are incoming changes, 1 otherwise.
2371 """
2358 """
2372 limit = cmdutil.loglimit(opts)
2359 limit = cmdutil.loglimit(opts)
2373 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2360 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2374 other = hg.repository(hg.remoteui(repo, opts), source)
2361 other = hg.repository(hg.remoteui(repo, opts), source)
2375 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2362 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2376 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2363 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2377 if revs:
2364 if revs:
2378 revs = [other.lookup(rev) for rev in revs]
2365 revs = [other.lookup(rev) for rev in revs]
2379
2366
2380 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2367 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2381 force=opts.get('force'))
2368 force=opts.get('force'))
2382 common, incoming, rheads = tmp
2369 common, incoming, rheads = tmp
2383 if not incoming:
2370 if not incoming:
2384 try:
2371 try:
2385 os.unlink(opts["bundle"])
2372 os.unlink(opts["bundle"])
2386 except:
2373 except:
2387 pass
2374 pass
2388 ui.status(_("no changes found\n"))
2375 ui.status(_("no changes found\n"))
2389 return 1
2376 return 1
2390
2377
2391 cleanup = None
2378 cleanup = None
2392 try:
2379 try:
2393 fname = opts["bundle"]
2380 fname = opts["bundle"]
2394 if fname or not other.local():
2381 if fname or not other.local():
2395 # create a bundle (uncompressed if other repo is not local)
2382 # create a bundle (uncompressed if other repo is not local)
2396
2383
2397 if revs is None and other.capable('changegroupsubset'):
2384 if revs is None and other.capable('changegroupsubset'):
2398 revs = rheads
2385 revs = rheads
2399
2386
2400 if revs is None:
2387 if revs is None:
2401 cg = other.changegroup(incoming, "incoming")
2388 cg = other.changegroup(incoming, "incoming")
2402 else:
2389 else:
2403 cg = other.changegroupsubset(incoming, revs, 'incoming')
2390 cg = other.changegroupsubset(incoming, revs, 'incoming')
2404 bundletype = other.local() and "HG10BZ" or "HG10UN"
2391 bundletype = other.local() and "HG10BZ" or "HG10UN"
2405 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2392 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2406 # keep written bundle?
2393 # keep written bundle?
2407 if opts["bundle"]:
2394 if opts["bundle"]:
2408 cleanup = None
2395 cleanup = None
2409 if not other.local():
2396 if not other.local():
2410 # use the created uncompressed bundlerepo
2397 # use the created uncompressed bundlerepo
2411 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2398 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2412
2399
2413 o = other.changelog.nodesbetween(incoming, revs)[0]
2400 o = other.changelog.nodesbetween(incoming, revs)[0]
2414 if opts.get('newest_first'):
2401 if opts.get('newest_first'):
2415 o.reverse()
2402 o.reverse()
2416 displayer = cmdutil.show_changeset(ui, other, opts)
2403 displayer = cmdutil.show_changeset(ui, other, opts)
2417 count = 0
2404 count = 0
2418 for n in o:
2405 for n in o:
2419 if limit is not None and count >= limit:
2406 if limit is not None and count >= limit:
2420 break
2407 break
2421 parents = [p for p in other.changelog.parents(n) if p != nullid]
2408 parents = [p for p in other.changelog.parents(n) if p != nullid]
2422 if opts.get('no_merges') and len(parents) == 2:
2409 if opts.get('no_merges') and len(parents) == 2:
2423 continue
2410 continue
2424 count += 1
2411 count += 1
2425 displayer.show(other[n])
2412 displayer.show(other[n])
2426 displayer.close()
2413 displayer.close()
2427 finally:
2414 finally:
2428 if hasattr(other, 'close'):
2415 if hasattr(other, 'close'):
2429 other.close()
2416 other.close()
2430 if cleanup:
2417 if cleanup:
2431 os.unlink(cleanup)
2418 os.unlink(cleanup)
2432
2419
2433 def init(ui, dest=".", **opts):
2420 def init(ui, dest=".", **opts):
2434 """create a new repository in the given directory
2421 """create a new repository in the given directory
2435
2422
2436 Initialize a new repository in the given directory. If the given
2423 Initialize a new repository in the given directory. If the given
2437 directory does not exist, it will be created.
2424 directory does not exist, it will be created.
2438
2425
2439 If no directory is given, the current directory is used.
2426 If no directory is given, the current directory is used.
2440
2427
2441 It is possible to specify an ``ssh://`` URL as the destination.
2428 It is possible to specify an ``ssh://`` URL as the destination.
2442 See :hg:`help urls` for more information.
2429 See :hg:`help urls` for more information.
2443
2430
2444 Returns 0 on success.
2431 Returns 0 on success.
2445 """
2432 """
2446 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2433 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2447
2434
2448 def locate(ui, repo, *pats, **opts):
2435 def locate(ui, repo, *pats, **opts):
2449 """locate files matching specific patterns
2436 """locate files matching specific patterns
2450
2437
2451 Print files under Mercurial control in the working directory whose
2438 Print files under Mercurial control in the working directory whose
2452 names match the given patterns.
2439 names match the given patterns.
2453
2440
2454 By default, this command searches all directories in the working
2441 By default, this command searches all directories in the working
2455 directory. To search just the current directory and its
2442 directory. To search just the current directory and its
2456 subdirectories, use "--include .".
2443 subdirectories, use "--include .".
2457
2444
2458 If no patterns are given to match, this command prints the names
2445 If no patterns are given to match, this command prints the names
2459 of all files under Mercurial control in the working directory.
2446 of all files under Mercurial control in the working directory.
2460
2447
2461 If you want to feed the output of this command into the "xargs"
2448 If you want to feed the output of this command into the "xargs"
2462 command, use the -0 option to both this command and "xargs". This
2449 command, use the -0 option to both this command and "xargs". This
2463 will avoid the problem of "xargs" treating single filenames that
2450 will avoid the problem of "xargs" treating single filenames that
2464 contain whitespace as multiple filenames.
2451 contain whitespace as multiple filenames.
2465
2452
2466 Returns 0 if a match is found, 1 otherwise.
2453 Returns 0 if a match is found, 1 otherwise.
2467 """
2454 """
2468 end = opts.get('print0') and '\0' or '\n'
2455 end = opts.get('print0') and '\0' or '\n'
2469 rev = opts.get('rev') or None
2456 rev = opts.get('rev') or None
2470
2457
2471 ret = 1
2458 ret = 1
2472 m = cmdutil.match(repo, pats, opts, default='relglob')
2459 m = cmdutil.match(repo, pats, opts, default='relglob')
2473 m.bad = lambda x, y: False
2460 m.bad = lambda x, y: False
2474 for abs in repo[rev].walk(m):
2461 for abs in repo[rev].walk(m):
2475 if not rev and abs not in repo.dirstate:
2462 if not rev and abs not in repo.dirstate:
2476 continue
2463 continue
2477 if opts.get('fullpath'):
2464 if opts.get('fullpath'):
2478 ui.write(repo.wjoin(abs), end)
2465 ui.write(repo.wjoin(abs), end)
2479 else:
2466 else:
2480 ui.write(((pats and m.rel(abs)) or abs), end)
2467 ui.write(((pats and m.rel(abs)) or abs), end)
2481 ret = 0
2468 ret = 0
2482
2469
2483 return ret
2470 return ret
2484
2471
2485 def log(ui, repo, *pats, **opts):
2472 def log(ui, repo, *pats, **opts):
2486 """show revision history of entire repository or files
2473 """show revision history of entire repository or files
2487
2474
2488 Print the revision history of the specified files or the entire
2475 Print the revision history of the specified files or the entire
2489 project.
2476 project.
2490
2477
2491 File history is shown without following rename or copy history of
2478 File history is shown without following rename or copy history of
2492 files. Use -f/--follow with a filename to follow history across
2479 files. Use -f/--follow with a filename to follow history across
2493 renames and copies. --follow without a filename will only show
2480 renames and copies. --follow without a filename will only show
2494 ancestors or descendants of the starting revision. --follow-first
2481 ancestors or descendants of the starting revision. --follow-first
2495 only follows the first parent of merge revisions.
2482 only follows the first parent of merge revisions.
2496
2483
2497 If no revision range is specified, the default is tip:0 unless
2484 If no revision range is specified, the default is tip:0 unless
2498 --follow is set, in which case the working directory parent is
2485 --follow is set, in which case the working directory parent is
2499 used as the starting revision. You can specify a revision set for
2486 used as the starting revision. You can specify a revision set for
2500 log, see :hg:`help revsets` for more information.
2487 log, see :hg:`help revsets` for more information.
2501
2488
2502 See :hg:`help dates` for a list of formats valid for -d/--date.
2489 See :hg:`help dates` for a list of formats valid for -d/--date.
2503
2490
2504 By default this command prints revision number and changeset id,
2491 By default this command prints revision number and changeset id,
2505 tags, non-trivial parents, user, date and time, and a summary for
2492 tags, non-trivial parents, user, date and time, and a summary for
2506 each commit. When the -v/--verbose switch is used, the list of
2493 each commit. When the -v/--verbose switch is used, the list of
2507 changed files and full commit message are shown.
2494 changed files and full commit message are shown.
2508
2495
2509 NOTE: log -p/--patch may generate unexpected diff output for merge
2496 NOTE: log -p/--patch may generate unexpected diff output for merge
2510 changesets, as it will only compare the merge changeset against
2497 changesets, as it will only compare the merge changeset against
2511 its first parent. Also, only files different from BOTH parents
2498 its first parent. Also, only files different from BOTH parents
2512 will appear in files:.
2499 will appear in files:.
2513
2500
2514 Returns 0 on success.
2501 Returns 0 on success.
2515 """
2502 """
2516
2503
2517 matchfn = cmdutil.match(repo, pats, opts)
2504 matchfn = cmdutil.match(repo, pats, opts)
2518 limit = cmdutil.loglimit(opts)
2505 limit = cmdutil.loglimit(opts)
2519 count = 0
2506 count = 0
2520
2507
2521 endrev = None
2508 endrev = None
2522 if opts.get('copies') and opts.get('rev'):
2509 if opts.get('copies') and opts.get('rev'):
2523 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2510 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2524
2511
2525 df = False
2512 df = False
2526 if opts["date"]:
2513 if opts["date"]:
2527 df = util.matchdate(opts["date"])
2514 df = util.matchdate(opts["date"])
2528
2515
2529 branches = opts.get('branch', []) + opts.get('only_branch', [])
2516 branches = opts.get('branch', []) + opts.get('only_branch', [])
2530 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2517 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2531
2518
2532 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2519 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2533 def prep(ctx, fns):
2520 def prep(ctx, fns):
2534 rev = ctx.rev()
2521 rev = ctx.rev()
2535 parents = [p for p in repo.changelog.parentrevs(rev)
2522 parents = [p for p in repo.changelog.parentrevs(rev)
2536 if p != nullrev]
2523 if p != nullrev]
2537 if opts.get('no_merges') and len(parents) == 2:
2524 if opts.get('no_merges') and len(parents) == 2:
2538 return
2525 return
2539 if opts.get('only_merges') and len(parents) != 2:
2526 if opts.get('only_merges') and len(parents) != 2:
2540 return
2527 return
2541 if opts.get('branch') and ctx.branch() not in opts['branch']:
2528 if opts.get('branch') and ctx.branch() not in opts['branch']:
2542 return
2529 return
2543 if df and not df(ctx.date()[0]):
2530 if df and not df(ctx.date()[0]):
2544 return
2531 return
2545 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2532 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2546 return
2533 return
2547 if opts.get('keyword'):
2534 if opts.get('keyword'):
2548 for k in [kw.lower() for kw in opts['keyword']]:
2535 for k in [kw.lower() for kw in opts['keyword']]:
2549 if (k in ctx.user().lower() or
2536 if (k in ctx.user().lower() or
2550 k in ctx.description().lower() or
2537 k in ctx.description().lower() or
2551 k in " ".join(ctx.files()).lower()):
2538 k in " ".join(ctx.files()).lower()):
2552 break
2539 break
2553 else:
2540 else:
2554 return
2541 return
2555
2542
2556 copies = None
2543 copies = None
2557 if opts.get('copies') and rev:
2544 if opts.get('copies') and rev:
2558 copies = []
2545 copies = []
2559 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2546 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2560 for fn in ctx.files():
2547 for fn in ctx.files():
2561 rename = getrenamed(fn, rev)
2548 rename = getrenamed(fn, rev)
2562 if rename:
2549 if rename:
2563 copies.append((fn, rename[0]))
2550 copies.append((fn, rename[0]))
2564
2551
2565 revmatchfn = None
2552 revmatchfn = None
2566 if opts.get('patch') or opts.get('stat'):
2553 if opts.get('patch') or opts.get('stat'):
2567 revmatchfn = cmdutil.match(repo, fns, default='path')
2554 revmatchfn = cmdutil.match(repo, fns, default='path')
2568
2555
2569 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2556 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2570
2557
2571 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2558 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2572 if count == limit:
2559 if count == limit:
2573 break
2560 break
2574 if displayer.flush(ctx.rev()):
2561 if displayer.flush(ctx.rev()):
2575 count += 1
2562 count += 1
2576 displayer.close()
2563 displayer.close()
2577
2564
2578 def manifest(ui, repo, node=None, rev=None):
2565 def manifest(ui, repo, node=None, rev=None):
2579 """output the current or given revision of the project manifest
2566 """output the current or given revision of the project manifest
2580
2567
2581 Print a list of version controlled files for the given revision.
2568 Print a list of version controlled files for the given revision.
2582 If no revision is given, the first parent of the working directory
2569 If no revision is given, the first parent of the working directory
2583 is used, or the null revision if no revision is checked out.
2570 is used, or the null revision if no revision is checked out.
2584
2571
2585 With -v, print file permissions, symlink and executable bits.
2572 With -v, print file permissions, symlink and executable bits.
2586 With --debug, print file revision hashes.
2573 With --debug, print file revision hashes.
2587
2574
2588 Returns 0 on success.
2575 Returns 0 on success.
2589 """
2576 """
2590
2577
2591 if rev and node:
2578 if rev and node:
2592 raise util.Abort(_("please specify just one revision"))
2579 raise util.Abort(_("please specify just one revision"))
2593
2580
2594 if not node:
2581 if not node:
2595 node = rev
2582 node = rev
2596
2583
2597 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2584 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2598 ctx = repo[node]
2585 ctx = repo[node]
2599 for f in ctx:
2586 for f in ctx:
2600 if ui.debugflag:
2587 if ui.debugflag:
2601 ui.write("%40s " % hex(ctx.manifest()[f]))
2588 ui.write("%40s " % hex(ctx.manifest()[f]))
2602 if ui.verbose:
2589 if ui.verbose:
2603 ui.write(decor[ctx.flags(f)])
2590 ui.write(decor[ctx.flags(f)])
2604 ui.write("%s\n" % f)
2591 ui.write("%s\n" % f)
2605
2592
2606 def merge(ui, repo, node=None, **opts):
2593 def merge(ui, repo, node=None, **opts):
2607 """merge working directory with another revision
2594 """merge working directory with another revision
2608
2595
2609 The current working directory is updated with all changes made in
2596 The current working directory is updated with all changes made in
2610 the requested revision since the last common predecessor revision.
2597 the requested revision since the last common predecessor revision.
2611
2598
2612 Files that changed between either parent are marked as changed for
2599 Files that changed between either parent are marked as changed for
2613 the next commit and a commit must be performed before any further
2600 the next commit and a commit must be performed before any further
2614 updates to the repository are allowed. The next commit will have
2601 updates to the repository are allowed. The next commit will have
2615 two parents.
2602 two parents.
2616
2603
2617 If no revision is specified, the working directory's parent is a
2604 If no revision is specified, the working directory's parent is a
2618 head revision, and the current branch contains exactly one other
2605 head revision, and the current branch contains exactly one other
2619 head, the other head is merged with by default. Otherwise, an
2606 head, the other head is merged with by default. Otherwise, an
2620 explicit revision with which to merge with must be provided.
2607 explicit revision with which to merge with must be provided.
2621
2608
2622 To undo an uncommitted merge, use :hg:`update --clean .` which
2609 To undo an uncommitted merge, use :hg:`update --clean .` which
2623 will check out a clean copy of the original merge parent, losing
2610 will check out a clean copy of the original merge parent, losing
2624 all changes.
2611 all changes.
2625
2612
2626 Returns 0 on success, 1 if there are unresolved files.
2613 Returns 0 on success, 1 if there are unresolved files.
2627 """
2614 """
2628
2615
2629 if opts.get('rev') and node:
2616 if opts.get('rev') and node:
2630 raise util.Abort(_("please specify just one revision"))
2617 raise util.Abort(_("please specify just one revision"))
2631 if not node:
2618 if not node:
2632 node = opts.get('rev')
2619 node = opts.get('rev')
2633
2620
2634 if not node:
2621 if not node:
2635 branch = repo.changectx(None).branch()
2622 branch = repo.changectx(None).branch()
2636 bheads = repo.branchheads(branch)
2623 bheads = repo.branchheads(branch)
2637 if len(bheads) > 2:
2624 if len(bheads) > 2:
2638 raise util.Abort(_(
2625 raise util.Abort(_(
2639 'branch \'%s\' has %d heads - '
2626 'branch \'%s\' has %d heads - '
2640 'please merge with an explicit rev\n'
2627 'please merge with an explicit rev\n'
2641 '(run \'hg heads .\' to see heads)')
2628 '(run \'hg heads .\' to see heads)')
2642 % (branch, len(bheads)))
2629 % (branch, len(bheads)))
2643
2630
2644 parent = repo.dirstate.parents()[0]
2631 parent = repo.dirstate.parents()[0]
2645 if len(bheads) == 1:
2632 if len(bheads) == 1:
2646 if len(repo.heads()) > 1:
2633 if len(repo.heads()) > 1:
2647 raise util.Abort(_(
2634 raise util.Abort(_(
2648 'branch \'%s\' has one head - '
2635 'branch \'%s\' has one head - '
2649 'please merge with an explicit rev\n'
2636 'please merge with an explicit rev\n'
2650 '(run \'hg heads\' to see all heads)')
2637 '(run \'hg heads\' to see all heads)')
2651 % branch)
2638 % branch)
2652 msg = _('there is nothing to merge')
2639 msg = _('there is nothing to merge')
2653 if parent != repo.lookup(repo[None].branch()):
2640 if parent != repo.lookup(repo[None].branch()):
2654 msg = _('%s - use "hg update" instead') % msg
2641 msg = _('%s - use "hg update" instead') % msg
2655 raise util.Abort(msg)
2642 raise util.Abort(msg)
2656
2643
2657 if parent not in bheads:
2644 if parent not in bheads:
2658 raise util.Abort(_('working dir not at a head rev - '
2645 raise util.Abort(_('working dir not at a head rev - '
2659 'use "hg update" or merge with an explicit rev'))
2646 'use "hg update" or merge with an explicit rev'))
2660 node = parent == bheads[0] and bheads[-1] or bheads[0]
2647 node = parent == bheads[0] and bheads[-1] or bheads[0]
2661
2648
2662 if opts.get('preview'):
2649 if opts.get('preview'):
2663 # find nodes that are ancestors of p2 but not of p1
2650 # find nodes that are ancestors of p2 but not of p1
2664 p1 = repo.lookup('.')
2651 p1 = repo.lookup('.')
2665 p2 = repo.lookup(node)
2652 p2 = repo.lookup(node)
2666 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2653 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2667
2654
2668 displayer = cmdutil.show_changeset(ui, repo, opts)
2655 displayer = cmdutil.show_changeset(ui, repo, opts)
2669 for node in nodes:
2656 for node in nodes:
2670 displayer.show(repo[node])
2657 displayer.show(repo[node])
2671 displayer.close()
2658 displayer.close()
2672 return 0
2659 return 0
2673
2660
2674 return hg.merge(repo, node, force=opts.get('force'))
2661 return hg.merge(repo, node, force=opts.get('force'))
2675
2662
2676 def outgoing(ui, repo, dest=None, **opts):
2663 def outgoing(ui, repo, dest=None, **opts):
2677 """show changesets not found in the destination
2664 """show changesets not found in the destination
2678
2665
2679 Show changesets not found in the specified destination repository
2666 Show changesets not found in the specified destination repository
2680 or the default push location. These are the changesets that would
2667 or the default push location. These are the changesets that would
2681 be pushed if a push was requested.
2668 be pushed if a push was requested.
2682
2669
2683 See pull for details of valid destination formats.
2670 See pull for details of valid destination formats.
2684
2671
2685 Returns 0 if there are outgoing changes, 1 otherwise.
2672 Returns 0 if there are outgoing changes, 1 otherwise.
2686 """
2673 """
2687 limit = cmdutil.loglimit(opts)
2674 limit = cmdutil.loglimit(opts)
2688 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2675 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2689 dest, branches = hg.parseurl(dest, opts.get('branch'))
2676 dest, branches = hg.parseurl(dest, opts.get('branch'))
2690 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2677 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2691 if revs:
2678 if revs:
2692 revs = [repo.lookup(rev) for rev in revs]
2679 revs = [repo.lookup(rev) for rev in revs]
2693
2680
2694 other = hg.repository(hg.remoteui(repo, opts), dest)
2681 other = hg.repository(hg.remoteui(repo, opts), dest)
2695 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2682 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2696 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2683 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2697 if not o:
2684 if not o:
2698 ui.status(_("no changes found\n"))
2685 ui.status(_("no changes found\n"))
2699 return 1
2686 return 1
2700 o = repo.changelog.nodesbetween(o, revs)[0]
2687 o = repo.changelog.nodesbetween(o, revs)[0]
2701 if opts.get('newest_first'):
2688 if opts.get('newest_first'):
2702 o.reverse()
2689 o.reverse()
2703 displayer = cmdutil.show_changeset(ui, repo, opts)
2690 displayer = cmdutil.show_changeset(ui, repo, opts)
2704 count = 0
2691 count = 0
2705 for n in o:
2692 for n in o:
2706 if limit is not None and count >= limit:
2693 if limit is not None and count >= limit:
2707 break
2694 break
2708 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2695 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2709 if opts.get('no_merges') and len(parents) == 2:
2696 if opts.get('no_merges') and len(parents) == 2:
2710 continue
2697 continue
2711 count += 1
2698 count += 1
2712 displayer.show(repo[n])
2699 displayer.show(repo[n])
2713 displayer.close()
2700 displayer.close()
2714
2701
2715 def parents(ui, repo, file_=None, **opts):
2702 def parents(ui, repo, file_=None, **opts):
2716 """show the parents of the working directory or revision
2703 """show the parents of the working directory or revision
2717
2704
2718 Print the working directory's parent revisions. If a revision is
2705 Print the working directory's parent revisions. If a revision is
2719 given via -r/--rev, the parent of that revision will be printed.
2706 given via -r/--rev, the parent of that revision will be printed.
2720 If a file argument is given, the revision in which the file was
2707 If a file argument is given, the revision in which the file was
2721 last changed (before the working directory revision or the
2708 last changed (before the working directory revision or the
2722 argument to --rev if given) is printed.
2709 argument to --rev if given) is printed.
2723
2710
2724 Returns 0 on success.
2711 Returns 0 on success.
2725 """
2712 """
2726 rev = opts.get('rev')
2713 rev = opts.get('rev')
2727 if rev:
2714 if rev:
2728 ctx = repo[rev]
2715 ctx = repo[rev]
2729 else:
2716 else:
2730 ctx = repo[None]
2717 ctx = repo[None]
2731
2718
2732 if file_:
2719 if file_:
2733 m = cmdutil.match(repo, (file_,), opts)
2720 m = cmdutil.match(repo, (file_,), opts)
2734 if m.anypats() or len(m.files()) != 1:
2721 if m.anypats() or len(m.files()) != 1:
2735 raise util.Abort(_('can only specify an explicit filename'))
2722 raise util.Abort(_('can only specify an explicit filename'))
2736 file_ = m.files()[0]
2723 file_ = m.files()[0]
2737 filenodes = []
2724 filenodes = []
2738 for cp in ctx.parents():
2725 for cp in ctx.parents():
2739 if not cp:
2726 if not cp:
2740 continue
2727 continue
2741 try:
2728 try:
2742 filenodes.append(cp.filenode(file_))
2729 filenodes.append(cp.filenode(file_))
2743 except error.LookupError:
2730 except error.LookupError:
2744 pass
2731 pass
2745 if not filenodes:
2732 if not filenodes:
2746 raise util.Abort(_("'%s' not found in manifest!") % file_)
2733 raise util.Abort(_("'%s' not found in manifest!") % file_)
2747 fl = repo.file(file_)
2734 fl = repo.file(file_)
2748 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2735 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2749 else:
2736 else:
2750 p = [cp.node() for cp in ctx.parents()]
2737 p = [cp.node() for cp in ctx.parents()]
2751
2738
2752 displayer = cmdutil.show_changeset(ui, repo, opts)
2739 displayer = cmdutil.show_changeset(ui, repo, opts)
2753 for n in p:
2740 for n in p:
2754 if n != nullid:
2741 if n != nullid:
2755 displayer.show(repo[n])
2742 displayer.show(repo[n])
2756 displayer.close()
2743 displayer.close()
2757
2744
2758 def paths(ui, repo, search=None):
2745 def paths(ui, repo, search=None):
2759 """show aliases for remote repositories
2746 """show aliases for remote repositories
2760
2747
2761 Show definition of symbolic path name NAME. If no name is given,
2748 Show definition of symbolic path name NAME. If no name is given,
2762 show definition of all available names.
2749 show definition of all available names.
2763
2750
2764 Path names are defined in the [paths] section of your
2751 Path names are defined in the [paths] section of your
2765 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2752 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2766 repository, ``.hg/hgrc`` is used, too.
2753 repository, ``.hg/hgrc`` is used, too.
2767
2754
2768 The path names ``default`` and ``default-push`` have a special
2755 The path names ``default`` and ``default-push`` have a special
2769 meaning. When performing a push or pull operation, they are used
2756 meaning. When performing a push or pull operation, they are used
2770 as fallbacks if no location is specified on the command-line.
2757 as fallbacks if no location is specified on the command-line.
2771 When ``default-push`` is set, it will be used for push and
2758 When ``default-push`` is set, it will be used for push and
2772 ``default`` will be used for pull; otherwise ``default`` is used
2759 ``default`` will be used for pull; otherwise ``default`` is used
2773 as the fallback for both. When cloning a repository, the clone
2760 as the fallback for both. When cloning a repository, the clone
2774 source is written as ``default`` in ``.hg/hgrc``. Note that
2761 source is written as ``default`` in ``.hg/hgrc``. Note that
2775 ``default`` and ``default-push`` apply to all inbound (e.g.
2762 ``default`` and ``default-push`` apply to all inbound (e.g.
2776 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2763 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2777 :hg:`bundle`) operations.
2764 :hg:`bundle`) operations.
2778
2765
2779 See :hg:`help urls` for more information.
2766 See :hg:`help urls` for more information.
2780
2767
2781 Returns 0 on success.
2768 Returns 0 on success.
2782 """
2769 """
2783 if search:
2770 if search:
2784 for name, path in ui.configitems("paths"):
2771 for name, path in ui.configitems("paths"):
2785 if name == search:
2772 if name == search:
2786 ui.write("%s\n" % url.hidepassword(path))
2773 ui.write("%s\n" % url.hidepassword(path))
2787 return
2774 return
2788 ui.warn(_("not found!\n"))
2775 ui.warn(_("not found!\n"))
2789 return 1
2776 return 1
2790 else:
2777 else:
2791 for name, path in ui.configitems("paths"):
2778 for name, path in ui.configitems("paths"):
2792 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2779 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2793
2780
2794 def postincoming(ui, repo, modheads, optupdate, checkout):
2781 def postincoming(ui, repo, modheads, optupdate, checkout):
2795 if modheads == 0:
2782 if modheads == 0:
2796 return
2783 return
2797 if optupdate:
2784 if optupdate:
2798 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2785 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2799 return hg.update(repo, checkout)
2786 return hg.update(repo, checkout)
2800 else:
2787 else:
2801 ui.status(_("not updating, since new heads added\n"))
2788 ui.status(_("not updating, since new heads added\n"))
2802 if modheads > 1:
2789 if modheads > 1:
2803 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2790 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2804 else:
2791 else:
2805 ui.status(_("(run 'hg update' to get a working copy)\n"))
2792 ui.status(_("(run 'hg update' to get a working copy)\n"))
2806
2793
2807 def pull(ui, repo, source="default", **opts):
2794 def pull(ui, repo, source="default", **opts):
2808 """pull changes from the specified source
2795 """pull changes from the specified source
2809
2796
2810 Pull changes from a remote repository to a local one.
2797 Pull changes from a remote repository to a local one.
2811
2798
2812 This finds all changes from the repository at the specified path
2799 This finds all changes from the repository at the specified path
2813 or URL and adds them to a local repository (the current one unless
2800 or URL and adds them to a local repository (the current one unless
2814 -R is specified). By default, this does not update the copy of the
2801 -R is specified). By default, this does not update the copy of the
2815 project in the working directory.
2802 project in the working directory.
2816
2803
2817 Use :hg:`incoming` if you want to see what would have been added
2804 Use :hg:`incoming` if you want to see what would have been added
2818 by a pull at the time you issued this command. If you then decide
2805 by a pull at the time you issued this command. If you then decide
2819 to add those changes to the repository, you should use :hg:`pull
2806 to add those changes to the repository, you should use :hg:`pull
2820 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2807 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2821
2808
2822 If SOURCE is omitted, the 'default' path will be used.
2809 If SOURCE is omitted, the 'default' path will be used.
2823 See :hg:`help urls` for more information.
2810 See :hg:`help urls` for more information.
2824
2811
2825 Returns 0 on success, 1 if an update had unresolved files.
2812 Returns 0 on success, 1 if an update had unresolved files.
2826 """
2813 """
2827 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2814 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2828 other = hg.repository(hg.remoteui(repo, opts), source)
2815 other = hg.repository(hg.remoteui(repo, opts), source)
2829 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2816 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2830 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2817 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2831 if revs:
2818 if revs:
2832 try:
2819 try:
2833 revs = [other.lookup(rev) for rev in revs]
2820 revs = [other.lookup(rev) for rev in revs]
2834 except error.CapabilityError:
2821 except error.CapabilityError:
2835 err = _("other repository doesn't support revision lookup, "
2822 err = _("other repository doesn't support revision lookup, "
2836 "so a rev cannot be specified.")
2823 "so a rev cannot be specified.")
2837 raise util.Abort(err)
2824 raise util.Abort(err)
2838
2825
2839 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2826 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2840 if checkout:
2827 if checkout:
2841 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2828 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2842 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2829 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2843
2830
2844 def push(ui, repo, dest=None, **opts):
2831 def push(ui, repo, dest=None, **opts):
2845 """push changes to the specified destination
2832 """push changes to the specified destination
2846
2833
2847 Push changesets from the local repository to the specified
2834 Push changesets from the local repository to the specified
2848 destination.
2835 destination.
2849
2836
2850 This operation is symmetrical to pull: it is identical to a pull
2837 This operation is symmetrical to pull: it is identical to a pull
2851 in the destination repository from the current one.
2838 in the destination repository from the current one.
2852
2839
2853 By default, push will not allow creation of new heads at the
2840 By default, push will not allow creation of new heads at the
2854 destination, since multiple heads would make it unclear which head
2841 destination, since multiple heads would make it unclear which head
2855 to use. In this situation, it is recommended to pull and merge
2842 to use. In this situation, it is recommended to pull and merge
2856 before pushing.
2843 before pushing.
2857
2844
2858 Use --new-branch if you want to allow push to create a new named
2845 Use --new-branch if you want to allow push to create a new named
2859 branch that is not present at the destination. This allows you to
2846 branch that is not present at the destination. This allows you to
2860 only create a new branch without forcing other changes.
2847 only create a new branch without forcing other changes.
2861
2848
2862 Use -f/--force to override the default behavior and push all
2849 Use -f/--force to override the default behavior and push all
2863 changesets on all branches.
2850 changesets on all branches.
2864
2851
2865 If -r/--rev is used, the specified revision and all its ancestors
2852 If -r/--rev is used, the specified revision and all its ancestors
2866 will be pushed to the remote repository.
2853 will be pushed to the remote repository.
2867
2854
2868 Please see :hg:`help urls` for important details about ``ssh://``
2855 Please see :hg:`help urls` for important details about ``ssh://``
2869 URLs. If DESTINATION is omitted, a default path will be used.
2856 URLs. If DESTINATION is omitted, a default path will be used.
2870
2857
2871 Returns 0 if push was successful, 1 if nothing to push.
2858 Returns 0 if push was successful, 1 if nothing to push.
2872 """
2859 """
2873 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2860 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2874 dest, branches = hg.parseurl(dest, opts.get('branch'))
2861 dest, branches = hg.parseurl(dest, opts.get('branch'))
2875 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2862 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2876 other = hg.repository(hg.remoteui(repo, opts), dest)
2863 other = hg.repository(hg.remoteui(repo, opts), dest)
2877 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2864 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2878 if revs:
2865 if revs:
2879 revs = [repo.lookup(rev) for rev in revs]
2866 revs = [repo.lookup(rev) for rev in revs]
2880
2867
2881 # push subrepos depth-first for coherent ordering
2868 # push subrepos depth-first for coherent ordering
2882 c = repo['']
2869 c = repo['']
2883 subs = c.substate # only repos that are committed
2870 subs = c.substate # only repos that are committed
2884 for s in sorted(subs):
2871 for s in sorted(subs):
2885 if not c.sub(s).push(opts.get('force')):
2872 if not c.sub(s).push(opts.get('force')):
2886 return False
2873 return False
2887
2874
2888 r = repo.push(other, opts.get('force'), revs=revs,
2875 r = repo.push(other, opts.get('force'), revs=revs,
2889 newbranch=opts.get('new_branch'))
2876 newbranch=opts.get('new_branch'))
2890 return r == 0
2877 return r == 0
2891
2878
2892 def recover(ui, repo):
2879 def recover(ui, repo):
2893 """roll back an interrupted transaction
2880 """roll back an interrupted transaction
2894
2881
2895 Recover from an interrupted commit or pull.
2882 Recover from an interrupted commit or pull.
2896
2883
2897 This command tries to fix the repository status after an
2884 This command tries to fix the repository status after an
2898 interrupted operation. It should only be necessary when Mercurial
2885 interrupted operation. It should only be necessary when Mercurial
2899 suggests it.
2886 suggests it.
2900
2887
2901 Returns 0 if successful, 1 if nothing to recover or verify fails.
2888 Returns 0 if successful, 1 if nothing to recover or verify fails.
2902 """
2889 """
2903 if repo.recover():
2890 if repo.recover():
2904 return hg.verify(repo)
2891 return hg.verify(repo)
2905 return 1
2892 return 1
2906
2893
2907 def remove(ui, repo, *pats, **opts):
2894 def remove(ui, repo, *pats, **opts):
2908 """remove the specified files on the next commit
2895 """remove the specified files on the next commit
2909
2896
2910 Schedule the indicated files for removal from the repository.
2897 Schedule the indicated files for removal from the repository.
2911
2898
2912 This only removes files from the current branch, not from the
2899 This only removes files from the current branch, not from the
2913 entire project history. -A/--after can be used to remove only
2900 entire project history. -A/--after can be used to remove only
2914 files that have already been deleted, -f/--force can be used to
2901 files that have already been deleted, -f/--force can be used to
2915 force deletion, and -Af can be used to remove files from the next
2902 force deletion, and -Af can be used to remove files from the next
2916 revision without deleting them from the working directory.
2903 revision without deleting them from the working directory.
2917
2904
2918 The following table details the behavior of remove for different
2905 The following table details the behavior of remove for different
2919 file states (columns) and option combinations (rows). The file
2906 file states (columns) and option combinations (rows). The file
2920 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2907 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2921 reported by :hg:`status`). The actions are Warn, Remove (from
2908 reported by :hg:`status`). The actions are Warn, Remove (from
2922 branch) and Delete (from disk)::
2909 branch) and Delete (from disk)::
2923
2910
2924 A C M !
2911 A C M !
2925 none W RD W R
2912 none W RD W R
2926 -f R RD RD R
2913 -f R RD RD R
2927 -A W W W R
2914 -A W W W R
2928 -Af R R R R
2915 -Af R R R R
2929
2916
2930 This command schedules the files to be removed at the next commit.
2917 This command schedules the files to be removed at the next commit.
2931 To undo a remove before that, see :hg:`revert`.
2918 To undo a remove before that, see :hg:`revert`.
2932
2919
2933 Returns 0 on success, 1 if any warnings encountered.
2920 Returns 0 on success, 1 if any warnings encountered.
2934 """
2921 """
2935
2922
2936 ret = 0
2923 ret = 0
2937 after, force = opts.get('after'), opts.get('force')
2924 after, force = opts.get('after'), opts.get('force')
2938 if not pats and not after:
2925 if not pats and not after:
2939 raise util.Abort(_('no files specified'))
2926 raise util.Abort(_('no files specified'))
2940
2927
2941 m = cmdutil.match(repo, pats, opts)
2928 m = cmdutil.match(repo, pats, opts)
2942 s = repo.status(match=m, clean=True)
2929 s = repo.status(match=m, clean=True)
2943 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2930 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2944
2931
2945 for f in m.files():
2932 for f in m.files():
2946 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2933 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2947 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2934 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2948 ret = 1
2935 ret = 1
2949
2936
2950 if force:
2937 if force:
2951 remove, forget = modified + deleted + clean, added
2938 remove, forget = modified + deleted + clean, added
2952 elif after:
2939 elif after:
2953 remove, forget = deleted, []
2940 remove, forget = deleted, []
2954 for f in modified + added + clean:
2941 for f in modified + added + clean:
2955 ui.warn(_('not removing %s: file still exists (use -f'
2942 ui.warn(_('not removing %s: file still exists (use -f'
2956 ' to force removal)\n') % m.rel(f))
2943 ' to force removal)\n') % m.rel(f))
2957 ret = 1
2944 ret = 1
2958 else:
2945 else:
2959 remove, forget = deleted + clean, []
2946 remove, forget = deleted + clean, []
2960 for f in modified:
2947 for f in modified:
2961 ui.warn(_('not removing %s: file is modified (use -f'
2948 ui.warn(_('not removing %s: file is modified (use -f'
2962 ' to force removal)\n') % m.rel(f))
2949 ' to force removal)\n') % m.rel(f))
2963 ret = 1
2950 ret = 1
2964 for f in added:
2951 for f in added:
2965 ui.warn(_('not removing %s: file has been marked for add (use -f'
2952 ui.warn(_('not removing %s: file has been marked for add (use -f'
2966 ' to force removal)\n') % m.rel(f))
2953 ' to force removal)\n') % m.rel(f))
2967 ret = 1
2954 ret = 1
2968
2955
2969 for f in sorted(remove + forget):
2956 for f in sorted(remove + forget):
2970 if ui.verbose or not m.exact(f):
2957 if ui.verbose or not m.exact(f):
2971 ui.status(_('removing %s\n') % m.rel(f))
2958 ui.status(_('removing %s\n') % m.rel(f))
2972
2959
2973 repo[None].forget(forget)
2960 repo[None].forget(forget)
2974 repo[None].remove(remove, unlink=not after)
2961 repo[None].remove(remove, unlink=not after)
2975 return ret
2962 return ret
2976
2963
2977 def rename(ui, repo, *pats, **opts):
2964 def rename(ui, repo, *pats, **opts):
2978 """rename files; equivalent of copy + remove
2965 """rename files; equivalent of copy + remove
2979
2966
2980 Mark dest as copies of sources; mark sources for deletion. If dest
2967 Mark dest as copies of sources; mark sources for deletion. If dest
2981 is a directory, copies are put in that directory. If dest is a
2968 is a directory, copies are put in that directory. If dest is a
2982 file, there can only be one source.
2969 file, there can only be one source.
2983
2970
2984 By default, this command copies the contents of files as they
2971 By default, this command copies the contents of files as they
2985 exist in the working directory. If invoked with -A/--after, the
2972 exist in the working directory. If invoked with -A/--after, the
2986 operation is recorded, but no copying is performed.
2973 operation is recorded, but no copying is performed.
2987
2974
2988 This command takes effect at the next commit. To undo a rename
2975 This command takes effect at the next commit. To undo a rename
2989 before that, see :hg:`revert`.
2976 before that, see :hg:`revert`.
2990
2977
2991 Returns 0 on success, 1 if errors are encountered.
2978 Returns 0 on success, 1 if errors are encountered.
2992 """
2979 """
2993 wlock = repo.wlock(False)
2980 wlock = repo.wlock(False)
2994 try:
2981 try:
2995 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2982 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2996 finally:
2983 finally:
2997 wlock.release()
2984 wlock.release()
2998
2985
2999 def resolve(ui, repo, *pats, **opts):
2986 def resolve(ui, repo, *pats, **opts):
3000 """redo merges or set/view the merge status of files
2987 """redo merges or set/view the merge status of files
3001
2988
3002 Merges with unresolved conflicts are often the result of
2989 Merges with unresolved conflicts are often the result of
3003 non-interactive merging using the ``internal:merge`` configuration
2990 non-interactive merging using the ``internal:merge`` configuration
3004 setting, or a command-line merge tool like ``diff3``. The resolve
2991 setting, or a command-line merge tool like ``diff3``. The resolve
3005 command is used to manage the files involved in a merge, after
2992 command is used to manage the files involved in a merge, after
3006 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2993 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3007 working directory must have two parents).
2994 working directory must have two parents).
3008
2995
3009 The resolve command can be used in the following ways:
2996 The resolve command can be used in the following ways:
3010
2997
3011 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
2998 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
3012 discarding any previous merge attempts. Re-merging is not
2999 discarding any previous merge attempts. Re-merging is not
3013 performed for files already marked as resolved. Use ``--all/-a``
3000 performed for files already marked as resolved. Use ``--all/-a``
3014 to selects all unresolved files.
3001 to selects all unresolved files.
3015
3002
3016 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3003 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3017 (e.g. after having manually fixed-up the files). The default is
3004 (e.g. after having manually fixed-up the files). The default is
3018 to mark all unresolved files.
3005 to mark all unresolved files.
3019
3006
3020 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3007 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3021 default is to mark all resolved files.
3008 default is to mark all resolved files.
3022
3009
3023 - :hg:`resolve -l`: list files which had or still have conflicts.
3010 - :hg:`resolve -l`: list files which had or still have conflicts.
3024 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3011 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3025
3012
3026 Note that Mercurial will not let you commit files with unresolved
3013 Note that Mercurial will not let you commit files with unresolved
3027 merge conflicts. You must use :hg:`resolve -m ...` before you can
3014 merge conflicts. You must use :hg:`resolve -m ...` before you can
3028 commit after a conflicting merge.
3015 commit after a conflicting merge.
3029
3016
3030 Returns 0 on success, 1 if any files fail a resolve attempt.
3017 Returns 0 on success, 1 if any files fail a resolve attempt.
3031 """
3018 """
3032
3019
3033 all, mark, unmark, show, nostatus = \
3020 all, mark, unmark, show, nostatus = \
3034 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3021 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3035
3022
3036 if (show and (mark or unmark)) or (mark and unmark):
3023 if (show and (mark or unmark)) or (mark and unmark):
3037 raise util.Abort(_("too many options specified"))
3024 raise util.Abort(_("too many options specified"))
3038 if pats and all:
3025 if pats and all:
3039 raise util.Abort(_("can't specify --all and patterns"))
3026 raise util.Abort(_("can't specify --all and patterns"))
3040 if not (all or pats or show or mark or unmark):
3027 if not (all or pats or show or mark or unmark):
3041 raise util.Abort(_('no files or directories specified; '
3028 raise util.Abort(_('no files or directories specified; '
3042 'use --all to remerge all files'))
3029 'use --all to remerge all files'))
3043
3030
3044 ms = mergemod.mergestate(repo)
3031 ms = mergemod.mergestate(repo)
3045 m = cmdutil.match(repo, pats, opts)
3032 m = cmdutil.match(repo, pats, opts)
3046 ret = 0
3033 ret = 0
3047
3034
3048 for f in ms:
3035 for f in ms:
3049 if m(f):
3036 if m(f):
3050 if show:
3037 if show:
3051 if nostatus:
3038 if nostatus:
3052 ui.write("%s\n" % f)
3039 ui.write("%s\n" % f)
3053 else:
3040 else:
3054 ui.write("%s %s\n" % (ms[f].upper(), f),
3041 ui.write("%s %s\n" % (ms[f].upper(), f),
3055 label='resolve.' +
3042 label='resolve.' +
3056 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3043 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3057 elif mark:
3044 elif mark:
3058 ms.mark(f, "r")
3045 ms.mark(f, "r")
3059 elif unmark:
3046 elif unmark:
3060 ms.mark(f, "u")
3047 ms.mark(f, "u")
3061 else:
3048 else:
3062 wctx = repo[None]
3049 wctx = repo[None]
3063 mctx = wctx.parents()[-1]
3050 mctx = wctx.parents()[-1]
3064
3051
3065 # backup pre-resolve (merge uses .orig for its own purposes)
3052 # backup pre-resolve (merge uses .orig for its own purposes)
3066 a = repo.wjoin(f)
3053 a = repo.wjoin(f)
3067 util.copyfile(a, a + ".resolve")
3054 util.copyfile(a, a + ".resolve")
3068
3055
3069 # resolve file
3056 # resolve file
3070 if ms.resolve(f, wctx, mctx):
3057 if ms.resolve(f, wctx, mctx):
3071 ret = 1
3058 ret = 1
3072
3059
3073 # replace filemerge's .orig file with our resolve file
3060 # replace filemerge's .orig file with our resolve file
3074 util.rename(a + ".resolve", a + ".orig")
3061 util.rename(a + ".resolve", a + ".orig")
3075 return ret
3062 return ret
3076
3063
3077 def revert(ui, repo, *pats, **opts):
3064 def revert(ui, repo, *pats, **opts):
3078 """restore individual files or directories to an earlier state
3065 """restore individual files or directories to an earlier state
3079
3066
3080 NOTE: This command is most likely not what you are looking for. revert
3067 NOTE: This command is most likely not what you are looking for. revert
3081 will partially overwrite content in the working directory without changing
3068 will partially overwrite content in the working directory without changing
3082 the working directory parents. Use :hg:`update -r rev` to check out earlier
3069 the working directory parents. Use :hg:`update -r rev` to check out earlier
3083 revisions, or :hg:`update --clean .` to undo a merge which has added
3070 revisions, or :hg:`update --clean .` to undo a merge which has added
3084 another parent.
3071 another parent.
3085
3072
3086 With no revision specified, revert the named files or directories
3073 With no revision specified, revert the named files or directories
3087 to the contents they had in the parent of the working directory.
3074 to the contents they had in the parent of the working directory.
3088 This restores the contents of the affected files to an unmodified
3075 This restores the contents of the affected files to an unmodified
3089 state and unschedules adds, removes, copies, and renames. If the
3076 state and unschedules adds, removes, copies, and renames. If the
3090 working directory has two parents, you must explicitly specify a
3077 working directory has two parents, you must explicitly specify a
3091 revision.
3078 revision.
3092
3079
3093 Using the -r/--rev option, revert the given files or directories
3080 Using the -r/--rev option, revert the given files or directories
3094 to their contents as of a specific revision. This can be helpful
3081 to their contents as of a specific revision. This can be helpful
3095 to "roll back" some or all of an earlier change. See :hg:`help
3082 to "roll back" some or all of an earlier change. See :hg:`help
3096 dates` for a list of formats valid for -d/--date.
3083 dates` for a list of formats valid for -d/--date.
3097
3084
3098 Revert modifies the working directory. It does not commit any
3085 Revert modifies the working directory. It does not commit any
3099 changes, or change the parent of the working directory. If you
3086 changes, or change the parent of the working directory. If you
3100 revert to a revision other than the parent of the working
3087 revert to a revision other than the parent of the working
3101 directory, the reverted files will thus appear modified
3088 directory, the reverted files will thus appear modified
3102 afterwards.
3089 afterwards.
3103
3090
3104 If a file has been deleted, it is restored. If the executable mode
3091 If a file has been deleted, it is restored. If the executable mode
3105 of a file was changed, it is reset.
3092 of a file was changed, it is reset.
3106
3093
3107 If names are given, all files matching the names are reverted.
3094 If names are given, all files matching the names are reverted.
3108 If no arguments are given, no files are reverted.
3095 If no arguments are given, no files are reverted.
3109
3096
3110 Modified files are saved with a .orig suffix before reverting.
3097 Modified files are saved with a .orig suffix before reverting.
3111 To disable these backups, use --no-backup.
3098 To disable these backups, use --no-backup.
3112
3099
3113 Returns 0 on success.
3100 Returns 0 on success.
3114 """
3101 """
3115
3102
3116 if opts.get("date"):
3103 if opts.get("date"):
3117 if opts.get("rev"):
3104 if opts.get("rev"):
3118 raise util.Abort(_("you can't specify a revision and a date"))
3105 raise util.Abort(_("you can't specify a revision and a date"))
3119 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3106 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3120
3107
3121 if not pats and not opts.get('all'):
3108 if not pats and not opts.get('all'):
3122 raise util.Abort(_('no files or directories specified; '
3109 raise util.Abort(_('no files or directories specified; '
3123 'use --all to revert the whole repo'))
3110 'use --all to revert the whole repo'))
3124
3111
3125 parent, p2 = repo.dirstate.parents()
3112 parent, p2 = repo.dirstate.parents()
3126 if not opts.get('rev') and p2 != nullid:
3113 if not opts.get('rev') and p2 != nullid:
3127 raise util.Abort(_('uncommitted merge - please provide a '
3114 raise util.Abort(_('uncommitted merge - please provide a '
3128 'specific revision'))
3115 'specific revision'))
3129 ctx = repo[opts.get('rev')]
3116 ctx = repo[opts.get('rev')]
3130 node = ctx.node()
3117 node = ctx.node()
3131 mf = ctx.manifest()
3118 mf = ctx.manifest()
3132 if node == parent:
3119 if node == parent:
3133 pmf = mf
3120 pmf = mf
3134 else:
3121 else:
3135 pmf = None
3122 pmf = None
3136
3123
3137 # need all matching names in dirstate and manifest of target rev,
3124 # need all matching names in dirstate and manifest of target rev,
3138 # so have to walk both. do not print errors if files exist in one
3125 # so have to walk both. do not print errors if files exist in one
3139 # but not other.
3126 # but not other.
3140
3127
3141 names = {}
3128 names = {}
3142
3129
3143 wlock = repo.wlock()
3130 wlock = repo.wlock()
3144 try:
3131 try:
3145 # walk dirstate.
3132 # walk dirstate.
3146
3133
3147 m = cmdutil.match(repo, pats, opts)
3134 m = cmdutil.match(repo, pats, opts)
3148 m.bad = lambda x, y: False
3135 m.bad = lambda x, y: False
3149 for abs in repo.walk(m):
3136 for abs in repo.walk(m):
3150 names[abs] = m.rel(abs), m.exact(abs)
3137 names[abs] = m.rel(abs), m.exact(abs)
3151
3138
3152 # walk target manifest.
3139 # walk target manifest.
3153
3140
3154 def badfn(path, msg):
3141 def badfn(path, msg):
3155 if path in names:
3142 if path in names:
3156 return
3143 return
3157 path_ = path + '/'
3144 path_ = path + '/'
3158 for f in names:
3145 for f in names:
3159 if f.startswith(path_):
3146 if f.startswith(path_):
3160 return
3147 return
3161 ui.warn("%s: %s\n" % (m.rel(path), msg))
3148 ui.warn("%s: %s\n" % (m.rel(path), msg))
3162
3149
3163 m = cmdutil.match(repo, pats, opts)
3150 m = cmdutil.match(repo, pats, opts)
3164 m.bad = badfn
3151 m.bad = badfn
3165 for abs in repo[node].walk(m):
3152 for abs in repo[node].walk(m):
3166 if abs not in names:
3153 if abs not in names:
3167 names[abs] = m.rel(abs), m.exact(abs)
3154 names[abs] = m.rel(abs), m.exact(abs)
3168
3155
3169 m = cmdutil.matchfiles(repo, names)
3156 m = cmdutil.matchfiles(repo, names)
3170 changes = repo.status(match=m)[:4]
3157 changes = repo.status(match=m)[:4]
3171 modified, added, removed, deleted = map(set, changes)
3158 modified, added, removed, deleted = map(set, changes)
3172
3159
3173 # if f is a rename, also revert the source
3160 # if f is a rename, also revert the source
3174 cwd = repo.getcwd()
3161 cwd = repo.getcwd()
3175 for f in added:
3162 for f in added:
3176 src = repo.dirstate.copied(f)
3163 src = repo.dirstate.copied(f)
3177 if src and src not in names and repo.dirstate[src] == 'r':
3164 if src and src not in names and repo.dirstate[src] == 'r':
3178 removed.add(src)
3165 removed.add(src)
3179 names[src] = (repo.pathto(src, cwd), True)
3166 names[src] = (repo.pathto(src, cwd), True)
3180
3167
3181 def removeforget(abs):
3168 def removeforget(abs):
3182 if repo.dirstate[abs] == 'a':
3169 if repo.dirstate[abs] == 'a':
3183 return _('forgetting %s\n')
3170 return _('forgetting %s\n')
3184 return _('removing %s\n')
3171 return _('removing %s\n')
3185
3172
3186 revert = ([], _('reverting %s\n'))
3173 revert = ([], _('reverting %s\n'))
3187 add = ([], _('adding %s\n'))
3174 add = ([], _('adding %s\n'))
3188 remove = ([], removeforget)
3175 remove = ([], removeforget)
3189 undelete = ([], _('undeleting %s\n'))
3176 undelete = ([], _('undeleting %s\n'))
3190
3177
3191 disptable = (
3178 disptable = (
3192 # dispatch table:
3179 # dispatch table:
3193 # file state
3180 # file state
3194 # action if in target manifest
3181 # action if in target manifest
3195 # action if not in target manifest
3182 # action if not in target manifest
3196 # make backup if in target manifest
3183 # make backup if in target manifest
3197 # make backup if not in target manifest
3184 # make backup if not in target manifest
3198 (modified, revert, remove, True, True),
3185 (modified, revert, remove, True, True),
3199 (added, revert, remove, True, False),
3186 (added, revert, remove, True, False),
3200 (removed, undelete, None, False, False),
3187 (removed, undelete, None, False, False),
3201 (deleted, revert, remove, False, False),
3188 (deleted, revert, remove, False, False),
3202 )
3189 )
3203
3190
3204 for abs, (rel, exact) in sorted(names.items()):
3191 for abs, (rel, exact) in sorted(names.items()):
3205 mfentry = mf.get(abs)
3192 mfentry = mf.get(abs)
3206 target = repo.wjoin(abs)
3193 target = repo.wjoin(abs)
3207 def handle(xlist, dobackup):
3194 def handle(xlist, dobackup):
3208 xlist[0].append(abs)
3195 xlist[0].append(abs)
3209 if (dobackup and not opts.get('no_backup') and
3196 if (dobackup and not opts.get('no_backup') and
3210 os.path.lexists(target)):
3197 os.path.lexists(target)):
3211 bakname = "%s.orig" % rel
3198 bakname = "%s.orig" % rel
3212 ui.note(_('saving current version of %s as %s\n') %
3199 ui.note(_('saving current version of %s as %s\n') %
3213 (rel, bakname))
3200 (rel, bakname))
3214 if not opts.get('dry_run'):
3201 if not opts.get('dry_run'):
3215 util.rename(target, bakname)
3202 util.rename(target, bakname)
3216 if ui.verbose or not exact:
3203 if ui.verbose or not exact:
3217 msg = xlist[1]
3204 msg = xlist[1]
3218 if not isinstance(msg, basestring):
3205 if not isinstance(msg, basestring):
3219 msg = msg(abs)
3206 msg = msg(abs)
3220 ui.status(msg % rel)
3207 ui.status(msg % rel)
3221 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3208 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3222 if abs not in table:
3209 if abs not in table:
3223 continue
3210 continue
3224 # file has changed in dirstate
3211 # file has changed in dirstate
3225 if mfentry:
3212 if mfentry:
3226 handle(hitlist, backuphit)
3213 handle(hitlist, backuphit)
3227 elif misslist is not None:
3214 elif misslist is not None:
3228 handle(misslist, backupmiss)
3215 handle(misslist, backupmiss)
3229 break
3216 break
3230 else:
3217 else:
3231 if abs not in repo.dirstate:
3218 if abs not in repo.dirstate:
3232 if mfentry:
3219 if mfentry:
3233 handle(add, True)
3220 handle(add, True)
3234 elif exact:
3221 elif exact:
3235 ui.warn(_('file not managed: %s\n') % rel)
3222 ui.warn(_('file not managed: %s\n') % rel)
3236 continue
3223 continue
3237 # file has not changed in dirstate
3224 # file has not changed in dirstate
3238 if node == parent:
3225 if node == parent:
3239 if exact:
3226 if exact:
3240 ui.warn(_('no changes needed to %s\n') % rel)
3227 ui.warn(_('no changes needed to %s\n') % rel)
3241 continue
3228 continue
3242 if pmf is None:
3229 if pmf is None:
3243 # only need parent manifest in this unlikely case,
3230 # only need parent manifest in this unlikely case,
3244 # so do not read by default
3231 # so do not read by default
3245 pmf = repo[parent].manifest()
3232 pmf = repo[parent].manifest()
3246 if abs in pmf:
3233 if abs in pmf:
3247 if mfentry:
3234 if mfentry:
3248 # if version of file is same in parent and target
3235 # if version of file is same in parent and target
3249 # manifests, do nothing
3236 # manifests, do nothing
3250 if (pmf[abs] != mfentry or
3237 if (pmf[abs] != mfentry or
3251 pmf.flags(abs) != mf.flags(abs)):
3238 pmf.flags(abs) != mf.flags(abs)):
3252 handle(revert, False)
3239 handle(revert, False)
3253 else:
3240 else:
3254 handle(remove, False)
3241 handle(remove, False)
3255
3242
3256 if not opts.get('dry_run'):
3243 if not opts.get('dry_run'):
3257 def checkout(f):
3244 def checkout(f):
3258 fc = ctx[f]
3245 fc = ctx[f]
3259 repo.wwrite(f, fc.data(), fc.flags())
3246 repo.wwrite(f, fc.data(), fc.flags())
3260
3247
3261 audit_path = util.path_auditor(repo.root)
3248 audit_path = util.path_auditor(repo.root)
3262 for f in remove[0]:
3249 for f in remove[0]:
3263 if repo.dirstate[f] == 'a':
3250 if repo.dirstate[f] == 'a':
3264 repo.dirstate.forget(f)
3251 repo.dirstate.forget(f)
3265 continue
3252 continue
3266 audit_path(f)
3253 audit_path(f)
3267 try:
3254 try:
3268 util.unlink(repo.wjoin(f))
3255 util.unlink(repo.wjoin(f))
3269 except OSError:
3256 except OSError:
3270 pass
3257 pass
3271 repo.dirstate.remove(f)
3258 repo.dirstate.remove(f)
3272
3259
3273 normal = None
3260 normal = None
3274 if node == parent:
3261 if node == parent:
3275 # We're reverting to our parent. If possible, we'd like status
3262 # We're reverting to our parent. If possible, we'd like status
3276 # to report the file as clean. We have to use normallookup for
3263 # to report the file as clean. We have to use normallookup for
3277 # merges to avoid losing information about merged/dirty files.
3264 # merges to avoid losing information about merged/dirty files.
3278 if p2 != nullid:
3265 if p2 != nullid:
3279 normal = repo.dirstate.normallookup
3266 normal = repo.dirstate.normallookup
3280 else:
3267 else:
3281 normal = repo.dirstate.normal
3268 normal = repo.dirstate.normal
3282 for f in revert[0]:
3269 for f in revert[0]:
3283 checkout(f)
3270 checkout(f)
3284 if normal:
3271 if normal:
3285 normal(f)
3272 normal(f)
3286
3273
3287 for f in add[0]:
3274 for f in add[0]:
3288 checkout(f)
3275 checkout(f)
3289 repo.dirstate.add(f)
3276 repo.dirstate.add(f)
3290
3277
3291 normal = repo.dirstate.normallookup
3278 normal = repo.dirstate.normallookup
3292 if node == parent and p2 == nullid:
3279 if node == parent and p2 == nullid:
3293 normal = repo.dirstate.normal
3280 normal = repo.dirstate.normal
3294 for f in undelete[0]:
3281 for f in undelete[0]:
3295 checkout(f)
3282 checkout(f)
3296 normal(f)
3283 normal(f)
3297
3284
3298 finally:
3285 finally:
3299 wlock.release()
3286 wlock.release()
3300
3287
3301 def rollback(ui, repo, **opts):
3288 def rollback(ui, repo, **opts):
3302 """roll back the last transaction (dangerous)
3289 """roll back the last transaction (dangerous)
3303
3290
3304 This command should be used with care. There is only one level of
3291 This command should be used with care. There is only one level of
3305 rollback, and there is no way to undo a rollback. It will also
3292 rollback, and there is no way to undo a rollback. It will also
3306 restore the dirstate at the time of the last transaction, losing
3293 restore the dirstate at the time of the last transaction, losing
3307 any dirstate changes since that time. This command does not alter
3294 any dirstate changes since that time. This command does not alter
3308 the working directory.
3295 the working directory.
3309
3296
3310 Transactions are used to encapsulate the effects of all commands
3297 Transactions are used to encapsulate the effects of all commands
3311 that create new changesets or propagate existing changesets into a
3298 that create new changesets or propagate existing changesets into a
3312 repository. For example, the following commands are transactional,
3299 repository. For example, the following commands are transactional,
3313 and their effects can be rolled back:
3300 and their effects can be rolled back:
3314
3301
3315 - commit
3302 - commit
3316 - import
3303 - import
3317 - pull
3304 - pull
3318 - push (with this repository as the destination)
3305 - push (with this repository as the destination)
3319 - unbundle
3306 - unbundle
3320
3307
3321 This command is not intended for use on public repositories. Once
3308 This command is not intended for use on public repositories. Once
3322 changes are visible for pull by other users, rolling a transaction
3309 changes are visible for pull by other users, rolling a transaction
3323 back locally is ineffective (someone else may already have pulled
3310 back locally is ineffective (someone else may already have pulled
3324 the changes). Furthermore, a race is possible with readers of the
3311 the changes). Furthermore, a race is possible with readers of the
3325 repository; for example an in-progress pull from the repository
3312 repository; for example an in-progress pull from the repository
3326 may fail if a rollback is performed.
3313 may fail if a rollback is performed.
3327
3314
3328 Returns 0 on success, 1 if no rollback data is available.
3315 Returns 0 on success, 1 if no rollback data is available.
3329 """
3316 """
3330 return repo.rollback(opts.get('dry_run'))
3317 return repo.rollback(opts.get('dry_run'))
3331
3318
3332 def root(ui, repo):
3319 def root(ui, repo):
3333 """print the root (top) of the current working directory
3320 """print the root (top) of the current working directory
3334
3321
3335 Print the root directory of the current repository.
3322 Print the root directory of the current repository.
3336
3323
3337 Returns 0 on success.
3324 Returns 0 on success.
3338 """
3325 """
3339 ui.write(repo.root + "\n")
3326 ui.write(repo.root + "\n")
3340
3327
3341 def serve(ui, repo, **opts):
3328 def serve(ui, repo, **opts):
3342 """start stand-alone webserver
3329 """start stand-alone webserver
3343
3330
3344 Start a local HTTP repository browser and pull server. You can use
3331 Start a local HTTP repository browser and pull server. You can use
3345 this for ad-hoc sharing and browing of repositories. It is
3332 this for ad-hoc sharing and browing of repositories. It is
3346 recommended to use a real web server to serve a repository for
3333 recommended to use a real web server to serve a repository for
3347 longer periods of time.
3334 longer periods of time.
3348
3335
3349 Please note that the server does not implement access control.
3336 Please note that the server does not implement access control.
3350 This means that, by default, anybody can read from the server and
3337 This means that, by default, anybody can read from the server and
3351 nobody can write to it by default. Set the ``web.allow_push``
3338 nobody can write to it by default. Set the ``web.allow_push``
3352 option to ``*`` to allow everybody to push to the server. You
3339 option to ``*`` to allow everybody to push to the server. You
3353 should use a real web server if you need to authenticate users.
3340 should use a real web server if you need to authenticate users.
3354
3341
3355 By default, the server logs accesses to stdout and errors to
3342 By default, the server logs accesses to stdout and errors to
3356 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3343 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3357 files.
3344 files.
3358
3345
3359 To have the server choose a free port number to listen on, specify
3346 To have the server choose a free port number to listen on, specify
3360 a port number of 0; in this case, the server will print the port
3347 a port number of 0; in this case, the server will print the port
3361 number it uses.
3348 number it uses.
3362
3349
3363 Returns 0 on success.
3350 Returns 0 on success.
3364 """
3351 """
3365
3352
3366 if opts["stdio"]:
3353 if opts["stdio"]:
3367 if repo is None:
3354 if repo is None:
3368 raise error.RepoError(_("There is no Mercurial repository here"
3355 raise error.RepoError(_("There is no Mercurial repository here"
3369 " (.hg not found)"))
3356 " (.hg not found)"))
3370 s = sshserver.sshserver(ui, repo)
3357 s = sshserver.sshserver(ui, repo)
3371 s.serve_forever()
3358 s.serve_forever()
3372
3359
3373 # this way we can check if something was given in the command-line
3360 # this way we can check if something was given in the command-line
3374 if opts.get('port'):
3361 if opts.get('port'):
3375 opts['port'] = util.getport(opts.get('port'))
3362 opts['port'] = util.getport(opts.get('port'))
3376
3363
3377 baseui = repo and repo.baseui or ui
3364 baseui = repo and repo.baseui or ui
3378 optlist = ("name templates style address port prefix ipv6"
3365 optlist = ("name templates style address port prefix ipv6"
3379 " accesslog errorlog certificate encoding")
3366 " accesslog errorlog certificate encoding")
3380 for o in optlist.split():
3367 for o in optlist.split():
3381 val = opts.get(o, '')
3368 val = opts.get(o, '')
3382 if val in (None, ''): # should check against default options instead
3369 if val in (None, ''): # should check against default options instead
3383 continue
3370 continue
3384 baseui.setconfig("web", o, val)
3371 baseui.setconfig("web", o, val)
3385 if repo and repo.ui != baseui:
3372 if repo and repo.ui != baseui:
3386 repo.ui.setconfig("web", o, val)
3373 repo.ui.setconfig("web", o, val)
3387
3374
3388 o = opts.get('web_conf') or opts.get('webdir_conf')
3375 o = opts.get('web_conf') or opts.get('webdir_conf')
3389 if not o:
3376 if not o:
3390 if not repo:
3377 if not repo:
3391 raise error.RepoError(_("There is no Mercurial repository"
3378 raise error.RepoError(_("There is no Mercurial repository"
3392 " here (.hg not found)"))
3379 " here (.hg not found)"))
3393 o = repo.root
3380 o = repo.root
3394
3381
3395 app = hgweb.hgweb(o, baseui=ui)
3382 app = hgweb.hgweb(o, baseui=ui)
3396
3383
3397 class service(object):
3384 class service(object):
3398 def init(self):
3385 def init(self):
3399 util.set_signal_handler()
3386 util.set_signal_handler()
3400 self.httpd = hgweb.server.create_server(ui, app)
3387 self.httpd = hgweb.server.create_server(ui, app)
3401
3388
3402 if opts['port'] and not ui.verbose:
3389 if opts['port'] and not ui.verbose:
3403 return
3390 return
3404
3391
3405 if self.httpd.prefix:
3392 if self.httpd.prefix:
3406 prefix = self.httpd.prefix.strip('/') + '/'
3393 prefix = self.httpd.prefix.strip('/') + '/'
3407 else:
3394 else:
3408 prefix = ''
3395 prefix = ''
3409
3396
3410 port = ':%d' % self.httpd.port
3397 port = ':%d' % self.httpd.port
3411 if port == ':80':
3398 if port == ':80':
3412 port = ''
3399 port = ''
3413
3400
3414 bindaddr = self.httpd.addr
3401 bindaddr = self.httpd.addr
3415 if bindaddr == '0.0.0.0':
3402 if bindaddr == '0.0.0.0':
3416 bindaddr = '*'
3403 bindaddr = '*'
3417 elif ':' in bindaddr: # IPv6
3404 elif ':' in bindaddr: # IPv6
3418 bindaddr = '[%s]' % bindaddr
3405 bindaddr = '[%s]' % bindaddr
3419
3406
3420 fqaddr = self.httpd.fqaddr
3407 fqaddr = self.httpd.fqaddr
3421 if ':' in fqaddr:
3408 if ':' in fqaddr:
3422 fqaddr = '[%s]' % fqaddr
3409 fqaddr = '[%s]' % fqaddr
3423 if opts['port']:
3410 if opts['port']:
3424 write = ui.status
3411 write = ui.status
3425 else:
3412 else:
3426 write = ui.write
3413 write = ui.write
3427 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3414 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3428 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3415 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3429
3416
3430 def run(self):
3417 def run(self):
3431 self.httpd.serve_forever()
3418 self.httpd.serve_forever()
3432
3419
3433 service = service()
3420 service = service()
3434
3421
3435 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3422 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3436
3423
3437 def status(ui, repo, *pats, **opts):
3424 def status(ui, repo, *pats, **opts):
3438 """show changed files in the working directory
3425 """show changed files in the working directory
3439
3426
3440 Show status of files in the repository. If names are given, only
3427 Show status of files in the repository. If names are given, only
3441 files that match are shown. Files that are clean or ignored or
3428 files that match are shown. Files that are clean or ignored or
3442 the source of a copy/move operation, are not listed unless
3429 the source of a copy/move operation, are not listed unless
3443 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3430 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3444 Unless options described with "show only ..." are given, the
3431 Unless options described with "show only ..." are given, the
3445 options -mardu are used.
3432 options -mardu are used.
3446
3433
3447 Option -q/--quiet hides untracked (unknown and ignored) files
3434 Option -q/--quiet hides untracked (unknown and ignored) files
3448 unless explicitly requested with -u/--unknown or -i/--ignored.
3435 unless explicitly requested with -u/--unknown or -i/--ignored.
3449
3436
3450 NOTE: status may appear to disagree with diff if permissions have
3437 NOTE: status may appear to disagree with diff if permissions have
3451 changed or a merge has occurred. The standard diff format does not
3438 changed or a merge has occurred. The standard diff format does not
3452 report permission changes and diff only reports changes relative
3439 report permission changes and diff only reports changes relative
3453 to one merge parent.
3440 to one merge parent.
3454
3441
3455 If one revision is given, it is used as the base revision.
3442 If one revision is given, it is used as the base revision.
3456 If two revisions are given, the differences between them are
3443 If two revisions are given, the differences between them are
3457 shown. The --change option can also be used as a shortcut to list
3444 shown. The --change option can also be used as a shortcut to list
3458 the changed files of a revision from its first parent.
3445 the changed files of a revision from its first parent.
3459
3446
3460 The codes used to show the status of files are::
3447 The codes used to show the status of files are::
3461
3448
3462 M = modified
3449 M = modified
3463 A = added
3450 A = added
3464 R = removed
3451 R = removed
3465 C = clean
3452 C = clean
3466 ! = missing (deleted by non-hg command, but still tracked)
3453 ! = missing (deleted by non-hg command, but still tracked)
3467 ? = not tracked
3454 ? = not tracked
3468 I = ignored
3455 I = ignored
3469 = origin of the previous file listed as A (added)
3456 = origin of the previous file listed as A (added)
3470
3457
3471 Returns 0 on success.
3458 Returns 0 on success.
3472 """
3459 """
3473
3460
3474 revs = opts.get('rev')
3461 revs = opts.get('rev')
3475 change = opts.get('change')
3462 change = opts.get('change')
3476
3463
3477 if revs and change:
3464 if revs and change:
3478 msg = _('cannot specify --rev and --change at the same time')
3465 msg = _('cannot specify --rev and --change at the same time')
3479 raise util.Abort(msg)
3466 raise util.Abort(msg)
3480 elif change:
3467 elif change:
3481 node2 = repo.lookup(change)
3468 node2 = repo.lookup(change)
3482 node1 = repo[node2].parents()[0].node()
3469 node1 = repo[node2].parents()[0].node()
3483 else:
3470 else:
3484 node1, node2 = cmdutil.revpair(repo, revs)
3471 node1, node2 = cmdutil.revpair(repo, revs)
3485
3472
3486 cwd = (pats and repo.getcwd()) or ''
3473 cwd = (pats and repo.getcwd()) or ''
3487 end = opts.get('print0') and '\0' or '\n'
3474 end = opts.get('print0') and '\0' or '\n'
3488 copy = {}
3475 copy = {}
3489 states = 'modified added removed deleted unknown ignored clean'.split()
3476 states = 'modified added removed deleted unknown ignored clean'.split()
3490 show = [k for k in states if opts.get(k)]
3477 show = [k for k in states if opts.get(k)]
3491 if opts.get('all'):
3478 if opts.get('all'):
3492 show += ui.quiet and (states[:4] + ['clean']) or states
3479 show += ui.quiet and (states[:4] + ['clean']) or states
3493 if not show:
3480 if not show:
3494 show = ui.quiet and states[:4] or states[:5]
3481 show = ui.quiet and states[:4] or states[:5]
3495
3482
3496 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3483 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3497 'ignored' in show, 'clean' in show, 'unknown' in show,
3484 'ignored' in show, 'clean' in show, 'unknown' in show,
3498 opts.get('subrepos'))
3485 opts.get('subrepos'))
3499 changestates = zip(states, 'MAR!?IC', stat)
3486 changestates = zip(states, 'MAR!?IC', stat)
3500
3487
3501 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3488 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3502 ctxn = repo[nullid]
3489 ctxn = repo[nullid]
3503 ctx1 = repo[node1]
3490 ctx1 = repo[node1]
3504 ctx2 = repo[node2]
3491 ctx2 = repo[node2]
3505 added = stat[1]
3492 added = stat[1]
3506 if node2 is None:
3493 if node2 is None:
3507 added = stat[0] + stat[1] # merged?
3494 added = stat[0] + stat[1] # merged?
3508
3495
3509 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3496 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3510 if k in added:
3497 if k in added:
3511 copy[k] = v
3498 copy[k] = v
3512 elif v in added:
3499 elif v in added:
3513 copy[v] = k
3500 copy[v] = k
3514
3501
3515 for state, char, files in changestates:
3502 for state, char, files in changestates:
3516 if state in show:
3503 if state in show:
3517 format = "%s %%s%s" % (char, end)
3504 format = "%s %%s%s" % (char, end)
3518 if opts.get('no_status'):
3505 if opts.get('no_status'):
3519 format = "%%s%s" % end
3506 format = "%%s%s" % end
3520
3507
3521 for f in files:
3508 for f in files:
3522 ui.write(format % repo.pathto(f, cwd),
3509 ui.write(format % repo.pathto(f, cwd),
3523 label='status.' + state)
3510 label='status.' + state)
3524 if f in copy:
3511 if f in copy:
3525 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3512 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3526 label='status.copied')
3513 label='status.copied')
3527
3514
3528 def summary(ui, repo, **opts):
3515 def summary(ui, repo, **opts):
3529 """summarize working directory state
3516 """summarize working directory state
3530
3517
3531 This generates a brief summary of the working directory state,
3518 This generates a brief summary of the working directory state,
3532 including parents, branch, commit status, and available updates.
3519 including parents, branch, commit status, and available updates.
3533
3520
3534 With the --remote option, this will check the default paths for
3521 With the --remote option, this will check the default paths for
3535 incoming and outgoing changes. This can be time-consuming.
3522 incoming and outgoing changes. This can be time-consuming.
3536
3523
3537 Returns 0 on success.
3524 Returns 0 on success.
3538 """
3525 """
3539
3526
3540 ctx = repo[None]
3527 ctx = repo[None]
3541 parents = ctx.parents()
3528 parents = ctx.parents()
3542 pnode = parents[0].node()
3529 pnode = parents[0].node()
3543
3530
3544 for p in parents:
3531 for p in parents:
3545 # label with log.changeset (instead of log.parent) since this
3532 # label with log.changeset (instead of log.parent) since this
3546 # shows a working directory parent *changeset*:
3533 # shows a working directory parent *changeset*:
3547 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3534 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3548 label='log.changeset')
3535 label='log.changeset')
3549 ui.write(' '.join(p.tags()), label='log.tag')
3536 ui.write(' '.join(p.tags()), label='log.tag')
3550 if p.rev() == -1:
3537 if p.rev() == -1:
3551 if not len(repo):
3538 if not len(repo):
3552 ui.write(_(' (empty repository)'))
3539 ui.write(_(' (empty repository)'))
3553 else:
3540 else:
3554 ui.write(_(' (no revision checked out)'))
3541 ui.write(_(' (no revision checked out)'))
3555 ui.write('\n')
3542 ui.write('\n')
3556 if p.description():
3543 if p.description():
3557 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3544 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3558 label='log.summary')
3545 label='log.summary')
3559
3546
3560 branch = ctx.branch()
3547 branch = ctx.branch()
3561 bheads = repo.branchheads(branch)
3548 bheads = repo.branchheads(branch)
3562 m = _('branch: %s\n') % branch
3549 m = _('branch: %s\n') % branch
3563 if branch != 'default':
3550 if branch != 'default':
3564 ui.write(m, label='log.branch')
3551 ui.write(m, label='log.branch')
3565 else:
3552 else:
3566 ui.status(m, label='log.branch')
3553 ui.status(m, label='log.branch')
3567
3554
3568 st = list(repo.status(unknown=True))[:6]
3555 st = list(repo.status(unknown=True))[:6]
3569
3556
3570 c = repo.dirstate.copies()
3557 c = repo.dirstate.copies()
3571 copied, renamed = [], []
3558 copied, renamed = [], []
3572 for d, s in c.iteritems():
3559 for d, s in c.iteritems():
3573 if s in st[2]:
3560 if s in st[2]:
3574 st[2].remove(s)
3561 st[2].remove(s)
3575 renamed.append(d)
3562 renamed.append(d)
3576 else:
3563 else:
3577 copied.append(d)
3564 copied.append(d)
3578 if d in st[1]:
3565 if d in st[1]:
3579 st[1].remove(d)
3566 st[1].remove(d)
3580 st.insert(3, renamed)
3567 st.insert(3, renamed)
3581 st.insert(4, copied)
3568 st.insert(4, copied)
3582
3569
3583 ms = mergemod.mergestate(repo)
3570 ms = mergemod.mergestate(repo)
3584 st.append([f for f in ms if ms[f] == 'u'])
3571 st.append([f for f in ms if ms[f] == 'u'])
3585
3572
3586 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3573 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3587 st.append(subs)
3574 st.append(subs)
3588
3575
3589 labels = [ui.label(_('%d modified'), 'status.modified'),
3576 labels = [ui.label(_('%d modified'), 'status.modified'),
3590 ui.label(_('%d added'), 'status.added'),
3577 ui.label(_('%d added'), 'status.added'),
3591 ui.label(_('%d removed'), 'status.removed'),
3578 ui.label(_('%d removed'), 'status.removed'),
3592 ui.label(_('%d renamed'), 'status.copied'),
3579 ui.label(_('%d renamed'), 'status.copied'),
3593 ui.label(_('%d copied'), 'status.copied'),
3580 ui.label(_('%d copied'), 'status.copied'),
3594 ui.label(_('%d deleted'), 'status.deleted'),
3581 ui.label(_('%d deleted'), 'status.deleted'),
3595 ui.label(_('%d unknown'), 'status.unknown'),
3582 ui.label(_('%d unknown'), 'status.unknown'),
3596 ui.label(_('%d ignored'), 'status.ignored'),
3583 ui.label(_('%d ignored'), 'status.ignored'),
3597 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3584 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3598 ui.label(_('%d subrepos'), 'status.modified')]
3585 ui.label(_('%d subrepos'), 'status.modified')]
3599 t = []
3586 t = []
3600 for s, l in zip(st, labels):
3587 for s, l in zip(st, labels):
3601 if s:
3588 if s:
3602 t.append(l % len(s))
3589 t.append(l % len(s))
3603
3590
3604 t = ', '.join(t)
3591 t = ', '.join(t)
3605 cleanworkdir = False
3592 cleanworkdir = False
3606
3593
3607 if len(parents) > 1:
3594 if len(parents) > 1:
3608 t += _(' (merge)')
3595 t += _(' (merge)')
3609 elif branch != parents[0].branch():
3596 elif branch != parents[0].branch():
3610 t += _(' (new branch)')
3597 t += _(' (new branch)')
3611 elif (parents[0].extra().get('close') and
3598 elif (parents[0].extra().get('close') and
3612 pnode in repo.branchheads(branch, closed=True)):
3599 pnode in repo.branchheads(branch, closed=True)):
3613 t += _(' (head closed)')
3600 t += _(' (head closed)')
3614 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3601 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3615 t += _(' (clean)')
3602 t += _(' (clean)')
3616 cleanworkdir = True
3603 cleanworkdir = True
3617 elif pnode not in bheads:
3604 elif pnode not in bheads:
3618 t += _(' (new branch head)')
3605 t += _(' (new branch head)')
3619
3606
3620 if cleanworkdir:
3607 if cleanworkdir:
3621 ui.status(_('commit: %s\n') % t.strip())
3608 ui.status(_('commit: %s\n') % t.strip())
3622 else:
3609 else:
3623 ui.write(_('commit: %s\n') % t.strip())
3610 ui.write(_('commit: %s\n') % t.strip())
3624
3611
3625 # all ancestors of branch heads - all ancestors of parent = new csets
3612 # all ancestors of branch heads - all ancestors of parent = new csets
3626 new = [0] * len(repo)
3613 new = [0] * len(repo)
3627 cl = repo.changelog
3614 cl = repo.changelog
3628 for a in [cl.rev(n) for n in bheads]:
3615 for a in [cl.rev(n) for n in bheads]:
3629 new[a] = 1
3616 new[a] = 1
3630 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3617 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3631 new[a] = 1
3618 new[a] = 1
3632 for a in [p.rev() for p in parents]:
3619 for a in [p.rev() for p in parents]:
3633 if a >= 0:
3620 if a >= 0:
3634 new[a] = 0
3621 new[a] = 0
3635 for a in cl.ancestors(*[p.rev() for p in parents]):
3622 for a in cl.ancestors(*[p.rev() for p in parents]):
3636 new[a] = 0
3623 new[a] = 0
3637 new = sum(new)
3624 new = sum(new)
3638
3625
3639 if new == 0:
3626 if new == 0:
3640 ui.status(_('update: (current)\n'))
3627 ui.status(_('update: (current)\n'))
3641 elif pnode not in bheads:
3628 elif pnode not in bheads:
3642 ui.write(_('update: %d new changesets (update)\n') % new)
3629 ui.write(_('update: %d new changesets (update)\n') % new)
3643 else:
3630 else:
3644 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3631 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3645 (new, len(bheads)))
3632 (new, len(bheads)))
3646
3633
3647 if opts.get('remote'):
3634 if opts.get('remote'):
3648 t = []
3635 t = []
3649 source, branches = hg.parseurl(ui.expandpath('default'))
3636 source, branches = hg.parseurl(ui.expandpath('default'))
3650 other = hg.repository(hg.remoteui(repo, {}), source)
3637 other = hg.repository(hg.remoteui(repo, {}), source)
3651 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3638 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3652 ui.debug('comparing with %s\n' % url.hidepassword(source))
3639 ui.debug('comparing with %s\n' % url.hidepassword(source))
3653 repo.ui.pushbuffer()
3640 repo.ui.pushbuffer()
3654 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3641 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3655 repo.ui.popbuffer()
3642 repo.ui.popbuffer()
3656 if incoming:
3643 if incoming:
3657 t.append(_('1 or more incoming'))
3644 t.append(_('1 or more incoming'))
3658
3645
3659 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3646 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3660 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3647 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3661 other = hg.repository(hg.remoteui(repo, {}), dest)
3648 other = hg.repository(hg.remoteui(repo, {}), dest)
3662 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3649 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3663 repo.ui.pushbuffer()
3650 repo.ui.pushbuffer()
3664 o = discovery.findoutgoing(repo, other)
3651 o = discovery.findoutgoing(repo, other)
3665 repo.ui.popbuffer()
3652 repo.ui.popbuffer()
3666 o = repo.changelog.nodesbetween(o, None)[0]
3653 o = repo.changelog.nodesbetween(o, None)[0]
3667 if o:
3654 if o:
3668 t.append(_('%d outgoing') % len(o))
3655 t.append(_('%d outgoing') % len(o))
3669
3656
3670 if t:
3657 if t:
3671 ui.write(_('remote: %s\n') % (', '.join(t)))
3658 ui.write(_('remote: %s\n') % (', '.join(t)))
3672 else:
3659 else:
3673 ui.status(_('remote: (synced)\n'))
3660 ui.status(_('remote: (synced)\n'))
3674
3661
3675 def tag(ui, repo, name1, *names, **opts):
3662 def tag(ui, repo, name1, *names, **opts):
3676 """add one or more tags for the current or given revision
3663 """add one or more tags for the current or given revision
3677
3664
3678 Name a particular revision using <name>.
3665 Name a particular revision using <name>.
3679
3666
3680 Tags are used to name particular revisions of the repository and are
3667 Tags are used to name particular revisions of the repository and are
3681 very useful to compare different revisions, to go back to significant
3668 very useful to compare different revisions, to go back to significant
3682 earlier versions or to mark branch points as releases, etc.
3669 earlier versions or to mark branch points as releases, etc.
3683
3670
3684 If no revision is given, the parent of the working directory is
3671 If no revision is given, the parent of the working directory is
3685 used, or tip if no revision is checked out.
3672 used, or tip if no revision is checked out.
3686
3673
3687 To facilitate version control, distribution, and merging of tags,
3674 To facilitate version control, distribution, and merging of tags,
3688 they are stored as a file named ".hgtags" which is managed
3675 they are stored as a file named ".hgtags" which is managed
3689 similarly to other project files and can be hand-edited if
3676 similarly to other project files and can be hand-edited if
3690 necessary. The file '.hg/localtags' is used for local tags (not
3677 necessary. The file '.hg/localtags' is used for local tags (not
3691 shared among repositories).
3678 shared among repositories).
3692
3679
3693 See :hg:`help dates` for a list of formats valid for -d/--date.
3680 See :hg:`help dates` for a list of formats valid for -d/--date.
3694
3681
3695 Since tag names have priority over branch names during revision
3682 Since tag names have priority over branch names during revision
3696 lookup, using an existing branch name as a tag name is discouraged.
3683 lookup, using an existing branch name as a tag name is discouraged.
3697
3684
3698 Returns 0 on success.
3685 Returns 0 on success.
3699 """
3686 """
3700
3687
3701 rev_ = "."
3688 rev_ = "."
3702 names = [t.strip() for t in (name1,) + names]
3689 names = [t.strip() for t in (name1,) + names]
3703 if len(names) != len(set(names)):
3690 if len(names) != len(set(names)):
3704 raise util.Abort(_('tag names must be unique'))
3691 raise util.Abort(_('tag names must be unique'))
3705 for n in names:
3692 for n in names:
3706 if n in ['tip', '.', 'null']:
3693 if n in ['tip', '.', 'null']:
3707 raise util.Abort(_('the name \'%s\' is reserved') % n)
3694 raise util.Abort(_('the name \'%s\' is reserved') % n)
3708 if not n:
3695 if not n:
3709 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3696 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3710 if opts.get('rev') and opts.get('remove'):
3697 if opts.get('rev') and opts.get('remove'):
3711 raise util.Abort(_("--rev and --remove are incompatible"))
3698 raise util.Abort(_("--rev and --remove are incompatible"))
3712 if opts.get('rev'):
3699 if opts.get('rev'):
3713 rev_ = opts['rev']
3700 rev_ = opts['rev']
3714 message = opts.get('message')
3701 message = opts.get('message')
3715 if opts.get('remove'):
3702 if opts.get('remove'):
3716 expectedtype = opts.get('local') and 'local' or 'global'
3703 expectedtype = opts.get('local') and 'local' or 'global'
3717 for n in names:
3704 for n in names:
3718 if not repo.tagtype(n):
3705 if not repo.tagtype(n):
3719 raise util.Abort(_('tag \'%s\' does not exist') % n)
3706 raise util.Abort(_('tag \'%s\' does not exist') % n)
3720 if repo.tagtype(n) != expectedtype:
3707 if repo.tagtype(n) != expectedtype:
3721 if expectedtype == 'global':
3708 if expectedtype == 'global':
3722 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3709 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3723 else:
3710 else:
3724 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3711 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3725 rev_ = nullid
3712 rev_ = nullid
3726 if not message:
3713 if not message:
3727 # we don't translate commit messages
3714 # we don't translate commit messages
3728 message = 'Removed tag %s' % ', '.join(names)
3715 message = 'Removed tag %s' % ', '.join(names)
3729 elif not opts.get('force'):
3716 elif not opts.get('force'):
3730 for n in names:
3717 for n in names:
3731 if n in repo.tags():
3718 if n in repo.tags():
3732 raise util.Abort(_('tag \'%s\' already exists '
3719 raise util.Abort(_('tag \'%s\' already exists '
3733 '(use -f to force)') % n)
3720 '(use -f to force)') % n)
3734 if not rev_ and repo.dirstate.parents()[1] != nullid:
3721 if not rev_ and repo.dirstate.parents()[1] != nullid:
3735 raise util.Abort(_('uncommitted merge - please provide a '
3722 raise util.Abort(_('uncommitted merge - please provide a '
3736 'specific revision'))
3723 'specific revision'))
3737 r = repo[rev_].node()
3724 r = repo[rev_].node()
3738
3725
3739 if not message:
3726 if not message:
3740 # we don't translate commit messages
3727 # we don't translate commit messages
3741 message = ('Added tag %s for changeset %s' %
3728 message = ('Added tag %s for changeset %s' %
3742 (', '.join(names), short(r)))
3729 (', '.join(names), short(r)))
3743
3730
3744 date = opts.get('date')
3731 date = opts.get('date')
3745 if date:
3732 if date:
3746 date = util.parsedate(date)
3733 date = util.parsedate(date)
3747
3734
3748 if opts.get('edit'):
3735 if opts.get('edit'):
3749 message = ui.edit(message, ui.username())
3736 message = ui.edit(message, ui.username())
3750
3737
3751 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3738 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3752
3739
3753 def tags(ui, repo):
3740 def tags(ui, repo):
3754 """list repository tags
3741 """list repository tags
3755
3742
3756 This lists both regular and local tags. When the -v/--verbose
3743 This lists both regular and local tags. When the -v/--verbose
3757 switch is used, a third column "local" is printed for local tags.
3744 switch is used, a third column "local" is printed for local tags.
3758
3745
3759 Returns 0 on success.
3746 Returns 0 on success.
3760 """
3747 """
3761
3748
3762 hexfunc = ui.debugflag and hex or short
3749 hexfunc = ui.debugflag and hex or short
3763 tagtype = ""
3750 tagtype = ""
3764
3751
3765 for t, n in reversed(repo.tagslist()):
3752 for t, n in reversed(repo.tagslist()):
3766 if ui.quiet:
3753 if ui.quiet:
3767 ui.write("%s\n" % t)
3754 ui.write("%s\n" % t)
3768 continue
3755 continue
3769
3756
3770 try:
3757 try:
3771 hn = hexfunc(n)
3758 hn = hexfunc(n)
3772 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3759 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3773 except error.LookupError:
3760 except error.LookupError:
3774 r = " ?:%s" % hn
3761 r = " ?:%s" % hn
3775 else:
3762 else:
3776 spaces = " " * (30 - encoding.colwidth(t))
3763 spaces = " " * (30 - encoding.colwidth(t))
3777 if ui.verbose:
3764 if ui.verbose:
3778 if repo.tagtype(t) == 'local':
3765 if repo.tagtype(t) == 'local':
3779 tagtype = " local"
3766 tagtype = " local"
3780 else:
3767 else:
3781 tagtype = ""
3768 tagtype = ""
3782 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3769 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3783
3770
3784 def tip(ui, repo, **opts):
3771 def tip(ui, repo, **opts):
3785 """show the tip revision
3772 """show the tip revision
3786
3773
3787 The tip revision (usually just called the tip) is the changeset
3774 The tip revision (usually just called the tip) is the changeset
3788 most recently added to the repository (and therefore the most
3775 most recently added to the repository (and therefore the most
3789 recently changed head).
3776 recently changed head).
3790
3777
3791 If you have just made a commit, that commit will be the tip. If
3778 If you have just made a commit, that commit will be the tip. If
3792 you have just pulled changes from another repository, the tip of
3779 you have just pulled changes from another repository, the tip of
3793 that repository becomes the current tip. The "tip" tag is special
3780 that repository becomes the current tip. The "tip" tag is special
3794 and cannot be renamed or assigned to a different changeset.
3781 and cannot be renamed or assigned to a different changeset.
3795
3782
3796 Returns 0 on success.
3783 Returns 0 on success.
3797 """
3784 """
3798 displayer = cmdutil.show_changeset(ui, repo, opts)
3785 displayer = cmdutil.show_changeset(ui, repo, opts)
3799 displayer.show(repo[len(repo) - 1])
3786 displayer.show(repo[len(repo) - 1])
3800 displayer.close()
3787 displayer.close()
3801
3788
3802 def unbundle(ui, repo, fname1, *fnames, **opts):
3789 def unbundle(ui, repo, fname1, *fnames, **opts):
3803 """apply one or more changegroup files
3790 """apply one or more changegroup files
3804
3791
3805 Apply one or more compressed changegroup files generated by the
3792 Apply one or more compressed changegroup files generated by the
3806 bundle command.
3793 bundle command.
3807
3794
3808 Returns 0 on success, 1 if an update has unresolved files.
3795 Returns 0 on success, 1 if an update has unresolved files.
3809 """
3796 """
3810 fnames = (fname1,) + fnames
3797 fnames = (fname1,) + fnames
3811
3798
3812 lock = repo.lock()
3799 lock = repo.lock()
3813 try:
3800 try:
3814 for fname in fnames:
3801 for fname in fnames:
3815 f = url.open(ui, fname)
3802 f = url.open(ui, fname)
3816 gen = changegroup.readbundle(f, fname)
3803 gen = changegroup.readbundle(f, fname)
3817 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3804 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3818 lock=lock)
3805 lock=lock)
3819 finally:
3806 finally:
3820 lock.release()
3807 lock.release()
3821
3808
3822 return postincoming(ui, repo, modheads, opts.get('update'), None)
3809 return postincoming(ui, repo, modheads, opts.get('update'), None)
3823
3810
3824 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3811 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3825 """update working directory (or switch revisions)
3812 """update working directory (or switch revisions)
3826
3813
3827 Update the repository's working directory to the specified
3814 Update the repository's working directory to the specified
3828 changeset.
3815 changeset.
3829
3816
3830 If no changeset is specified, attempt to update to the tip of the
3817 If no changeset is specified, attempt to update to the tip of the
3831 current branch. If this changeset is a descendant of the working
3818 current branch. If this changeset is a descendant of the working
3832 directory's parent, update to it, otherwise abort.
3819 directory's parent, update to it, otherwise abort.
3833
3820
3834 The following rules apply when the working directory contains
3821 The following rules apply when the working directory contains
3835 uncommitted changes:
3822 uncommitted changes:
3836
3823
3837 1. If neither -c/--check nor -C/--clean is specified, and if
3824 1. If neither -c/--check nor -C/--clean is specified, and if
3838 the requested changeset is an ancestor or descendant of
3825 the requested changeset is an ancestor or descendant of
3839 the working directory's parent, the uncommitted changes
3826 the working directory's parent, the uncommitted changes
3840 are merged into the requested changeset and the merged
3827 are merged into the requested changeset and the merged
3841 result is left uncommitted. If the requested changeset is
3828 result is left uncommitted. If the requested changeset is
3842 not an ancestor or descendant (that is, it is on another
3829 not an ancestor or descendant (that is, it is on another
3843 branch), the update is aborted and the uncommitted changes
3830 branch), the update is aborted and the uncommitted changes
3844 are preserved.
3831 are preserved.
3845
3832
3846 2. With the -c/--check option, the update is aborted and the
3833 2. With the -c/--check option, the update is aborted and the
3847 uncommitted changes are preserved.
3834 uncommitted changes are preserved.
3848
3835
3849 3. With the -C/--clean option, uncommitted changes are discarded and
3836 3. With the -C/--clean option, uncommitted changes are discarded and
3850 the working directory is updated to the requested changeset.
3837 the working directory is updated to the requested changeset.
3851
3838
3852 Use null as the changeset to remove the working directory (like
3839 Use null as the changeset to remove the working directory (like
3853 :hg:`clone -U`).
3840 :hg:`clone -U`).
3854
3841
3855 If you want to update just one file to an older changeset, use :hg:`revert`.
3842 If you want to update just one file to an older changeset, use :hg:`revert`.
3856
3843
3857 See :hg:`help dates` for a list of formats valid for -d/--date.
3844 See :hg:`help dates` for a list of formats valid for -d/--date.
3858
3845
3859 Returns 0 on success, 1 if there are unresolved files.
3846 Returns 0 on success, 1 if there are unresolved files.
3860 """
3847 """
3861 if rev and node:
3848 if rev and node:
3862 raise util.Abort(_("please specify just one revision"))
3849 raise util.Abort(_("please specify just one revision"))
3863
3850
3864 if not rev:
3851 if not rev:
3865 rev = node
3852 rev = node
3866
3853
3867 if check and clean:
3854 if check and clean:
3868 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3855 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3869
3856
3870 if check:
3857 if check:
3871 # we could use dirty() but we can ignore merge and branch trivia
3858 # we could use dirty() but we can ignore merge and branch trivia
3872 c = repo[None]
3859 c = repo[None]
3873 if c.modified() or c.added() or c.removed():
3860 if c.modified() or c.added() or c.removed():
3874 raise util.Abort(_("uncommitted local changes"))
3861 raise util.Abort(_("uncommitted local changes"))
3875
3862
3876 if date:
3863 if date:
3877 if rev:
3864 if rev:
3878 raise util.Abort(_("you can't specify a revision and a date"))
3865 raise util.Abort(_("you can't specify a revision and a date"))
3879 rev = cmdutil.finddate(ui, repo, date)
3866 rev = cmdutil.finddate(ui, repo, date)
3880
3867
3881 if clean or check:
3868 if clean or check:
3882 return hg.clean(repo, rev)
3869 return hg.clean(repo, rev)
3883 else:
3870 else:
3884 return hg.update(repo, rev)
3871 return hg.update(repo, rev)
3885
3872
3886 def verify(ui, repo):
3873 def verify(ui, repo):
3887 """verify the integrity of the repository
3874 """verify the integrity of the repository
3888
3875
3889 Verify the integrity of the current repository.
3876 Verify the integrity of the current repository.
3890
3877
3891 This will perform an extensive check of the repository's
3878 This will perform an extensive check of the repository's
3892 integrity, validating the hashes and checksums of each entry in
3879 integrity, validating the hashes and checksums of each entry in
3893 the changelog, manifest, and tracked files, as well as the
3880 the changelog, manifest, and tracked files, as well as the
3894 integrity of their crosslinks and indices.
3881 integrity of their crosslinks and indices.
3895
3882
3896 Returns 0 on success, 1 if errors are encountered.
3883 Returns 0 on success, 1 if errors are encountered.
3897 """
3884 """
3898 return hg.verify(repo)
3885 return hg.verify(repo)
3899
3886
3900 def version_(ui):
3887 def version_(ui):
3901 """output version and copyright information"""
3888 """output version and copyright information"""
3902 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3889 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3903 % util.version())
3890 % util.version())
3904 ui.status(_(
3891 ui.status(_(
3905 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3892 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3906 "This is free software; see the source for copying conditions. "
3893 "This is free software; see the source for copying conditions. "
3907 "There is NO\nwarranty; "
3894 "There is NO\nwarranty; "
3908 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3895 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3909 ))
3896 ))
3910
3897
3911 # Command options and aliases are listed here, alphabetically
3898 # Command options and aliases are listed here, alphabetically
3912
3899
3913 globalopts = [
3900 globalopts = [
3914 ('R', 'repository', '',
3901 ('R', 'repository', '',
3915 _('repository root directory or name of overlay bundle file'),
3902 _('repository root directory or name of overlay bundle file'),
3916 _('REPO')),
3903 _('REPO')),
3917 ('', 'cwd', '',
3904 ('', 'cwd', '',
3918 _('change working directory'), _('DIR')),
3905 _('change working directory'), _('DIR')),
3919 ('y', 'noninteractive', None,
3906 ('y', 'noninteractive', None,
3920 _('do not prompt, assume \'yes\' for any required answers')),
3907 _('do not prompt, assume \'yes\' for any required answers')),
3921 ('q', 'quiet', None, _('suppress output')),
3908 ('q', 'quiet', None, _('suppress output')),
3922 ('v', 'verbose', None, _('enable additional output')),
3909 ('v', 'verbose', None, _('enable additional output')),
3923 ('', 'config', [],
3910 ('', 'config', [],
3924 _('set/override config option (use \'section.name=value\')'),
3911 _('set/override config option (use \'section.name=value\')'),
3925 _('CONFIG')),
3912 _('CONFIG')),
3926 ('', 'debug', None, _('enable debugging output')),
3913 ('', 'debug', None, _('enable debugging output')),
3927 ('', 'debugger', None, _('start debugger')),
3914 ('', 'debugger', None, _('start debugger')),
3928 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3915 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3929 _('ENCODE')),
3916 _('ENCODE')),
3930 ('', 'encodingmode', encoding.encodingmode,
3917 ('', 'encodingmode', encoding.encodingmode,
3931 _('set the charset encoding mode'), _('MODE')),
3918 _('set the charset encoding mode'), _('MODE')),
3932 ('', 'traceback', None, _('always print a traceback on exception')),
3919 ('', 'traceback', None, _('always print a traceback on exception')),
3933 ('', 'time', None, _('time how long the command takes')),
3920 ('', 'time', None, _('time how long the command takes')),
3934 ('', 'profile', None, _('print command execution profile')),
3921 ('', 'profile', None, _('print command execution profile')),
3935 ('', 'version', None, _('output version information and exit')),
3922 ('', 'version', None, _('output version information and exit')),
3936 ('h', 'help', None, _('display help and exit')),
3923 ('h', 'help', None, _('display help and exit')),
3937 ]
3924 ]
3938
3925
3939 dryrunopts = [('n', 'dry-run', None,
3926 dryrunopts = [('n', 'dry-run', None,
3940 _('do not perform actions, just print output'))]
3927 _('do not perform actions, just print output'))]
3941
3928
3942 remoteopts = [
3929 remoteopts = [
3943 ('e', 'ssh', '',
3930 ('e', 'ssh', '',
3944 _('specify ssh command to use'), _('CMD')),
3931 _('specify ssh command to use'), _('CMD')),
3945 ('', 'remotecmd', '',
3932 ('', 'remotecmd', '',
3946 _('specify hg command to run on the remote side'), _('CMD')),
3933 _('specify hg command to run on the remote side'), _('CMD')),
3947 ]
3934 ]
3948
3935
3949 walkopts = [
3936 walkopts = [
3950 ('I', 'include', [],
3937 ('I', 'include', [],
3951 _('include names matching the given patterns'), _('PATTERN')),
3938 _('include names matching the given patterns'), _('PATTERN')),
3952 ('X', 'exclude', [],
3939 ('X', 'exclude', [],
3953 _('exclude names matching the given patterns'), _('PATTERN')),
3940 _('exclude names matching the given patterns'), _('PATTERN')),
3954 ]
3941 ]
3955
3942
3956 commitopts = [
3943 commitopts = [
3957 ('m', 'message', '',
3944 ('m', 'message', '',
3958 _('use text as commit message'), _('TEXT')),
3945 _('use text as commit message'), _('TEXT')),
3959 ('l', 'logfile', '',
3946 ('l', 'logfile', '',
3960 _('read commit message from file'), _('FILE')),
3947 _('read commit message from file'), _('FILE')),
3961 ]
3948 ]
3962
3949
3963 commitopts2 = [
3950 commitopts2 = [
3964 ('d', 'date', '',
3951 ('d', 'date', '',
3965 _('record datecode as commit date'), _('DATE')),
3952 _('record datecode as commit date'), _('DATE')),
3966 ('u', 'user', '',
3953 ('u', 'user', '',
3967 _('record the specified user as committer'), _('USER')),
3954 _('record the specified user as committer'), _('USER')),
3968 ]
3955 ]
3969
3956
3970 templateopts = [
3957 templateopts = [
3971 ('', 'style', '',
3958 ('', 'style', '',
3972 _('display using template map file'), _('STYLE')),
3959 _('display using template map file'), _('STYLE')),
3973 ('', 'template', '',
3960 ('', 'template', '',
3974 _('display with template'), _('TEMPLATE')),
3961 _('display with template'), _('TEMPLATE')),
3975 ]
3962 ]
3976
3963
3977 logopts = [
3964 logopts = [
3978 ('p', 'patch', None, _('show patch')),
3965 ('p', 'patch', None, _('show patch')),
3979 ('g', 'git', None, _('use git extended diff format')),
3966 ('g', 'git', None, _('use git extended diff format')),
3980 ('l', 'limit', '',
3967 ('l', 'limit', '',
3981 _('limit number of changes displayed'), _('NUM')),
3968 _('limit number of changes displayed'), _('NUM')),
3982 ('M', 'no-merges', None, _('do not show merges')),
3969 ('M', 'no-merges', None, _('do not show merges')),
3983 ('', 'stat', None, _('output diffstat-style summary of changes')),
3970 ('', 'stat', None, _('output diffstat-style summary of changes')),
3984 ] + templateopts
3971 ] + templateopts
3985
3972
3986 diffopts = [
3973 diffopts = [
3987 ('a', 'text', None, _('treat all files as text')),
3974 ('a', 'text', None, _('treat all files as text')),
3988 ('g', 'git', None, _('use git extended diff format')),
3975 ('g', 'git', None, _('use git extended diff format')),
3989 ('', 'nodates', None, _('omit dates from diff headers'))
3976 ('', 'nodates', None, _('omit dates from diff headers'))
3990 ]
3977 ]
3991
3978
3992 diffopts2 = [
3979 diffopts2 = [
3993 ('p', 'show-function', None, _('show which function each change is in')),
3980 ('p', 'show-function', None, _('show which function each change is in')),
3994 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3981 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3995 ('w', 'ignore-all-space', None,
3982 ('w', 'ignore-all-space', None,
3996 _('ignore white space when comparing lines')),
3983 _('ignore white space when comparing lines')),
3997 ('b', 'ignore-space-change', None,
3984 ('b', 'ignore-space-change', None,
3998 _('ignore changes in the amount of white space')),
3985 _('ignore changes in the amount of white space')),
3999 ('B', 'ignore-blank-lines', None,
3986 ('B', 'ignore-blank-lines', None,
4000 _('ignore changes whose lines are all blank')),
3987 _('ignore changes whose lines are all blank')),
4001 ('U', 'unified', '',
3988 ('U', 'unified', '',
4002 _('number of lines of context to show'), _('NUM')),
3989 _('number of lines of context to show'), _('NUM')),
4003 ('', 'stat', None, _('output diffstat-style summary of changes')),
3990 ('', 'stat', None, _('output diffstat-style summary of changes')),
4004 ]
3991 ]
4005
3992
4006 similarityopts = [
3993 similarityopts = [
4007 ('s', 'similarity', '',
3994 ('s', 'similarity', '',
4008 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3995 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4009 ]
3996 ]
4010
3997
4011 subrepoopts = [
3998 subrepoopts = [
4012 ('S', 'subrepos', None,
3999 ('S', 'subrepos', None,
4013 _('recurse into subrepositories'))
4000 _('recurse into subrepositories'))
4014 ]
4001 ]
4015
4002
4016 table = {
4003 table = {
4017 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
4004 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
4018 "addremove":
4005 "addremove":
4019 (addremove, similarityopts + walkopts + dryrunopts,
4006 (addremove, similarityopts + walkopts + dryrunopts,
4020 _('[OPTION]... [FILE]...')),
4007 _('[OPTION]... [FILE]...')),
4021 "^annotate|blame":
4008 "^annotate|blame":
4022 (annotate,
4009 (annotate,
4023 [('r', 'rev', '',
4010 [('r', 'rev', '',
4024 _('annotate the specified revision'), _('REV')),
4011 _('annotate the specified revision'), _('REV')),
4025 ('', 'follow', None,
4012 ('', 'follow', None,
4026 _('follow copies/renames and list the filename (DEPRECATED)')),
4013 _('follow copies/renames and list the filename (DEPRECATED)')),
4027 ('', 'no-follow', None, _("don't follow copies and renames")),
4014 ('', 'no-follow', None, _("don't follow copies and renames")),
4028 ('a', 'text', None, _('treat all files as text')),
4015 ('a', 'text', None, _('treat all files as text')),
4029 ('u', 'user', None, _('list the author (long with -v)')),
4016 ('u', 'user', None, _('list the author (long with -v)')),
4030 ('f', 'file', None, _('list the filename')),
4017 ('f', 'file', None, _('list the filename')),
4031 ('d', 'date', None, _('list the date (short with -q)')),
4018 ('d', 'date', None, _('list the date (short with -q)')),
4032 ('n', 'number', None, _('list the revision number (default)')),
4019 ('n', 'number', None, _('list the revision number (default)')),
4033 ('c', 'changeset', None, _('list the changeset')),
4020 ('c', 'changeset', None, _('list the changeset')),
4034 ('l', 'line-number', None,
4021 ('l', 'line-number', None,
4035 _('show line number at the first appearance'))
4022 _('show line number at the first appearance'))
4036 ] + walkopts,
4023 ] + walkopts,
4037 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4024 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4038 "archive":
4025 "archive":
4039 (archive,
4026 (archive,
4040 [('', 'no-decode', None, _('do not pass files through decoders')),
4027 [('', 'no-decode', None, _('do not pass files through decoders')),
4041 ('p', 'prefix', '',
4028 ('p', 'prefix', '',
4042 _('directory prefix for files in archive'), _('PREFIX')),
4029 _('directory prefix for files in archive'), _('PREFIX')),
4043 ('r', 'rev', '',
4030 ('r', 'rev', '',
4044 _('revision to distribute'), _('REV')),
4031 _('revision to distribute'), _('REV')),
4045 ('t', 'type', '',
4032 ('t', 'type', '',
4046 _('type of distribution to create'), _('TYPE')),
4033 _('type of distribution to create'), _('TYPE')),
4047 ] + walkopts,
4034 ] + walkopts,
4048 _('[OPTION]... DEST')),
4035 _('[OPTION]... DEST')),
4049 "backout":
4036 "backout":
4050 (backout,
4037 (backout,
4051 [('', 'merge', None,
4038 [('', 'merge', None,
4052 _('merge with old dirstate parent after backout')),
4039 _('merge with old dirstate parent after backout')),
4053 ('', 'parent', '',
4040 ('', 'parent', '',
4054 _('parent to choose when backing out merge'), _('REV')),
4041 _('parent to choose when backing out merge'), _('REV')),
4055 ('r', 'rev', '',
4042 ('r', 'rev', '',
4056 _('revision to backout'), _('REV')),
4043 _('revision to backout'), _('REV')),
4057 ] + walkopts + commitopts + commitopts2,
4044 ] + walkopts + commitopts + commitopts2,
4058 _('[OPTION]... [-r] REV')),
4045 _('[OPTION]... [-r] REV')),
4059 "bisect":
4046 "bisect":
4060 (bisect,
4047 (bisect,
4061 [('r', 'reset', False, _('reset bisect state')),
4048 [('r', 'reset', False, _('reset bisect state')),
4062 ('g', 'good', False, _('mark changeset good')),
4049 ('g', 'good', False, _('mark changeset good')),
4063 ('b', 'bad', False, _('mark changeset bad')),
4050 ('b', 'bad', False, _('mark changeset bad')),
4064 ('s', 'skip', False, _('skip testing changeset')),
4051 ('s', 'skip', False, _('skip testing changeset')),
4065 ('c', 'command', '',
4052 ('c', 'command', '',
4066 _('use command to check changeset state'), _('CMD')),
4053 _('use command to check changeset state'), _('CMD')),
4067 ('U', 'noupdate', False, _('do not update to target'))],
4054 ('U', 'noupdate', False, _('do not update to target'))],
4068 _("[-gbsr] [-U] [-c CMD] [REV]")),
4055 _("[-gbsr] [-U] [-c CMD] [REV]")),
4069 "branch":
4056 "branch":
4070 (branch,
4057 (branch,
4071 [('f', 'force', None,
4058 [('f', 'force', None,
4072 _('set branch name even if it shadows an existing branch')),
4059 _('set branch name even if it shadows an existing branch')),
4073 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4060 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4074 _('[-fC] [NAME]')),
4061 _('[-fC] [NAME]')),
4075 "branches":
4062 "branches":
4076 (branches,
4063 (branches,
4077 [('a', 'active', False,
4064 [('a', 'active', False,
4078 _('show only branches that have unmerged heads')),
4065 _('show only branches that have unmerged heads')),
4079 ('c', 'closed', False,
4066 ('c', 'closed', False,
4080 _('show normal and closed branches'))],
4067 _('show normal and closed branches'))],
4081 _('[-ac]')),
4068 _('[-ac]')),
4082 "bundle":
4069 "bundle":
4083 (bundle,
4070 (bundle,
4084 [('f', 'force', None,
4071 [('f', 'force', None,
4085 _('run even when the destination is unrelated')),
4072 _('run even when the destination is unrelated')),
4086 ('r', 'rev', [],
4073 ('r', 'rev', [],
4087 _('a changeset intended to be added to the destination'),
4074 _('a changeset intended to be added to the destination'),
4088 _('REV')),
4075 _('REV')),
4089 ('b', 'branch', [],
4076 ('b', 'branch', [],
4090 _('a specific branch you would like to bundle'),
4077 _('a specific branch you would like to bundle'),
4091 _('BRANCH')),
4078 _('BRANCH')),
4092 ('', 'base', [],
4079 ('', 'base', [],
4093 _('a base changeset assumed to be available at the destination'),
4080 _('a base changeset assumed to be available at the destination'),
4094 _('REV')),
4081 _('REV')),
4095 ('a', 'all', None, _('bundle all changesets in the repository')),
4082 ('a', 'all', None, _('bundle all changesets in the repository')),
4096 ('t', 'type', 'bzip2',
4083 ('t', 'type', 'bzip2',
4097 _('bundle compression type to use'), _('TYPE')),
4084 _('bundle compression type to use'), _('TYPE')),
4098 ] + remoteopts,
4085 ] + remoteopts,
4099 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4086 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4100 "cat":
4087 "cat":
4101 (cat,
4088 (cat,
4102 [('o', 'output', '',
4089 [('o', 'output', '',
4103 _('print output to file with formatted name'), _('FORMAT')),
4090 _('print output to file with formatted name'), _('FORMAT')),
4104 ('r', 'rev', '',
4091 ('r', 'rev', '',
4105 _('print the given revision'), _('REV')),
4092 _('print the given revision'), _('REV')),
4106 ('', 'decode', None, _('apply any matching decode filter')),
4093 ('', 'decode', None, _('apply any matching decode filter')),
4107 ] + walkopts,
4094 ] + walkopts,
4108 _('[OPTION]... FILE...')),
4095 _('[OPTION]... FILE...')),
4109 "^clone":
4096 "^clone":
4110 (clone,
4097 (clone,
4111 [('U', 'noupdate', None,
4098 [('U', 'noupdate', None,
4112 _('the clone will include an empty working copy (only a repository)')),
4099 _('the clone will include an empty working copy (only a repository)')),
4113 ('u', 'updaterev', '',
4100 ('u', 'updaterev', '',
4114 _('revision, tag or branch to check out'), _('REV')),
4101 _('revision, tag or branch to check out'), _('REV')),
4115 ('r', 'rev', [],
4102 ('r', 'rev', [],
4116 _('include the specified changeset'), _('REV')),
4103 _('include the specified changeset'), _('REV')),
4117 ('b', 'branch', [],
4104 ('b', 'branch', [],
4118 _('clone only the specified branch'), _('BRANCH')),
4105 _('clone only the specified branch'), _('BRANCH')),
4119 ('', 'pull', None, _('use pull protocol to copy metadata')),
4106 ('', 'pull', None, _('use pull protocol to copy metadata')),
4120 ('', 'uncompressed', None,
4107 ('', 'uncompressed', None,
4121 _('use uncompressed transfer (fast over LAN)')),
4108 _('use uncompressed transfer (fast over LAN)')),
4122 ] + remoteopts,
4109 ] + remoteopts,
4123 _('[OPTION]... SOURCE [DEST]')),
4110 _('[OPTION]... SOURCE [DEST]')),
4124 "^commit|ci":
4111 "^commit|ci":
4125 (commit,
4112 (commit,
4126 [('A', 'addremove', None,
4113 [('A', 'addremove', None,
4127 _('mark new/missing files as added/removed before committing')),
4114 _('mark new/missing files as added/removed before committing')),
4128 ('', 'close-branch', None,
4115 ('', 'close-branch', None,
4129 _('mark a branch as closed, hiding it from the branch list')),
4116 _('mark a branch as closed, hiding it from the branch list')),
4130 ] + walkopts + commitopts + commitopts2,
4117 ] + walkopts + commitopts + commitopts2,
4131 _('[OPTION]... [FILE]...')),
4118 _('[OPTION]... [FILE]...')),
4132 "copy|cp":
4119 "copy|cp":
4133 (copy,
4120 (copy,
4134 [('A', 'after', None, _('record a copy that has already occurred')),
4121 [('A', 'after', None, _('record a copy that has already occurred')),
4135 ('f', 'force', None,
4122 ('f', 'force', None,
4136 _('forcibly copy over an existing managed file')),
4123 _('forcibly copy over an existing managed file')),
4137 ] + walkopts + dryrunopts,
4124 ] + walkopts + dryrunopts,
4138 _('[OPTION]... [SOURCE]... DEST')),
4125 _('[OPTION]... [SOURCE]... DEST')),
4139 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4126 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4140 "debugbuilddag":
4127 "debugbuilddag":
4141 (debugbuilddag,
4128 (debugbuilddag,
4142 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4129 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4143 ('a', 'appended-file', None, _('add single file all revs append to')),
4130 ('a', 'appended-file', None, _('add single file all revs append to')),
4144 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4131 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4145 ('n', 'new-file', None, _('add new file at each rev')),
4132 ('n', 'new-file', None, _('add new file at each rev')),
4146 ],
4133 ],
4147 _('[OPTION]... TEXT')),
4134 _('[OPTION]... TEXT')),
4148 "debugcheckstate": (debugcheckstate, [], ''),
4135 "debugcheckstate": (debugcheckstate, [], ''),
4149 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4136 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4150 "debugcomplete":
4137 "debugcomplete":
4151 (debugcomplete,
4138 (debugcomplete,
4152 [('o', 'options', None, _('show the command options'))],
4139 [('o', 'options', None, _('show the command options'))],
4153 _('[-o] CMD')),
4140 _('[-o] CMD')),
4154 "debugdag":
4141 "debugdag":
4155 (debugdag,
4142 (debugdag,
4156 [('t', 'tags', None, _('use tags as labels')),
4143 [('t', 'tags', None, _('use tags as labels')),
4157 ('b', 'branches', None, _('annotate with branch names')),
4144 ('b', 'branches', None, _('annotate with branch names')),
4158 ('', 'dots', None, _('use dots for runs')),
4145 ('', 'dots', None, _('use dots for runs')),
4159 ('s', 'spaces', None, _('separate elements by spaces')),
4146 ('s', 'spaces', None, _('separate elements by spaces')),
4160 ],
4147 ],
4161 _('[OPTION]... [FILE [REV]...]')),
4148 _('[OPTION]... [FILE [REV]...]')),
4162 "debugdate":
4149 "debugdate":
4163 (debugdate,
4150 (debugdate,
4164 [('e', 'extended', None, _('try extended date formats'))],
4151 [('e', 'extended', None, _('try extended date formats'))],
4165 _('[-e] DATE [RANGE]')),
4152 _('[-e] DATE [RANGE]')),
4166 "debugdata": (debugdata, [], _('FILE REV')),
4153 "debugdata": (debugdata, [], _('FILE REV')),
4167 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4154 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4168 "debugindex": (debugindex, [], _('FILE')),
4155 "debugindex": (debugindex, [], _('FILE')),
4169 "debugindexdot": (debugindexdot, [], _('FILE')),
4156 "debugindexdot": (debugindexdot, [], _('FILE')),
4170 "debuginstall": (debuginstall, [], ''),
4157 "debuginstall": (debuginstall, [], ''),
4171 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4158 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4172 "debugrebuildstate":
4159 "debugrebuildstate":
4173 (debugrebuildstate,
4160 (debugrebuildstate,
4174 [('r', 'rev', '',
4161 [('r', 'rev', '',
4175 _('revision to rebuild to'), _('REV'))],
4162 _('revision to rebuild to'), _('REV'))],
4176 _('[-r REV] [REV]')),
4163 _('[-r REV] [REV]')),
4177 "debugrename":
4164 "debugrename":
4178 (debugrename,
4165 (debugrename,
4179 [('r', 'rev', '',
4166 [('r', 'rev', '',
4180 _('revision to debug'), _('REV'))],
4167 _('revision to debug'), _('REV'))],
4181 _('[-r REV] FILE')),
4168 _('[-r REV] FILE')),
4182 "debugrevspec":
4169 "debugrevspec":
4183 (debugrevspec, [], ('REVSPEC')),
4170 (debugrevspec, [], ('REVSPEC')),
4184 "debugsetparents":
4171 "debugsetparents":
4185 (debugsetparents, [], _('REV1 [REV2]')),
4172 (debugsetparents, [], _('REV1 [REV2]')),
4186 "debugstate":
4173 "debugstate":
4187 (debugstate,
4174 (debugstate,
4188 [('', 'nodates', None, _('do not display the saved mtime'))],
4175 [('', 'nodates', None, _('do not display the saved mtime'))],
4189 _('[OPTION]...')),
4176 _('[OPTION]...')),
4190 "debugsub":
4177 "debugsub":
4191 (debugsub,
4178 (debugsub,
4192 [('r', 'rev', '',
4179 [('r', 'rev', '',
4193 _('revision to check'), _('REV'))],
4180 _('revision to check'), _('REV'))],
4194 _('[-r REV] [REV]')),
4181 _('[-r REV] [REV]')),
4195 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4182 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4196 "^diff":
4183 "^diff":
4197 (diff,
4184 (diff,
4198 [('r', 'rev', [],
4185 [('r', 'rev', [],
4199 _('revision'), _('REV')),
4186 _('revision'), _('REV')),
4200 ('c', 'change', '',
4187 ('c', 'change', '',
4201 _('change made by revision'), _('REV'))
4188 _('change made by revision'), _('REV'))
4202 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4189 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4203 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4190 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4204 "^export":
4191 "^export":
4205 (export,
4192 (export,
4206 [('o', 'output', '',
4193 [('o', 'output', '',
4207 _('print output to file with formatted name'), _('FORMAT')),
4194 _('print output to file with formatted name'), _('FORMAT')),
4208 ('', 'switch-parent', None, _('diff against the second parent')),
4195 ('', 'switch-parent', None, _('diff against the second parent')),
4209 ('r', 'rev', [],
4196 ('r', 'rev', [],
4210 _('revisions to export'), _('REV')),
4197 _('revisions to export'), _('REV')),
4211 ] + diffopts,
4198 ] + diffopts,
4212 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4199 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4213 "^forget":
4200 "^forget":
4214 (forget,
4201 (forget,
4215 [] + walkopts,
4202 [] + walkopts,
4216 _('[OPTION]... FILE...')),
4203 _('[OPTION]... FILE...')),
4217 "grep":
4204 "grep":
4218 (grep,
4205 (grep,
4219 [('0', 'print0', None, _('end fields with NUL')),
4206 [('0', 'print0', None, _('end fields with NUL')),
4220 ('', 'all', None, _('print all revisions that match')),
4207 ('', 'all', None, _('print all revisions that match')),
4221 ('f', 'follow', None,
4208 ('f', 'follow', None,
4222 _('follow changeset history,'
4209 _('follow changeset history,'
4223 ' or file history across copies and renames')),
4210 ' or file history across copies and renames')),
4224 ('i', 'ignore-case', None, _('ignore case when matching')),
4211 ('i', 'ignore-case', None, _('ignore case when matching')),
4225 ('l', 'files-with-matches', None,
4212 ('l', 'files-with-matches', None,
4226 _('print only filenames and revisions that match')),
4213 _('print only filenames and revisions that match')),
4227 ('n', 'line-number', None, _('print matching line numbers')),
4214 ('n', 'line-number', None, _('print matching line numbers')),
4228 ('r', 'rev', [],
4215 ('r', 'rev', [],
4229 _('only search files changed within revision range'), _('REV')),
4216 _('only search files changed within revision range'), _('REV')),
4230 ('u', 'user', None, _('list the author (long with -v)')),
4217 ('u', 'user', None, _('list the author (long with -v)')),
4231 ('d', 'date', None, _('list the date (short with -q)')),
4218 ('d', 'date', None, _('list the date (short with -q)')),
4232 ] + walkopts,
4219 ] + walkopts,
4233 _('[OPTION]... PATTERN [FILE]...')),
4220 _('[OPTION]... PATTERN [FILE]...')),
4234 "heads":
4221 "heads":
4235 (heads,
4222 (heads,
4236 [('r', 'rev', '',
4223 [('r', 'rev', '',
4237 _('show only heads which are descendants of REV'), _('REV')),
4224 _('show only heads which are descendants of REV'), _('REV')),
4238 ('t', 'topo', False, _('show topological heads only')),
4225 ('t', 'topo', False, _('show topological heads only')),
4239 ('a', 'active', False,
4226 ('a', 'active', False,
4240 _('show active branchheads only (DEPRECATED)')),
4227 _('show active branchheads only (DEPRECATED)')),
4241 ('c', 'closed', False,
4228 ('c', 'closed', False,
4242 _('show normal and closed branch heads')),
4229 _('show normal and closed branch heads')),
4243 ] + templateopts,
4230 ] + templateopts,
4244 _('[-ac] [-r REV] [REV]...')),
4231 _('[-ac] [-r REV] [REV]...')),
4245 "help": (help_, [], _('[TOPIC]')),
4232 "help": (help_, [], _('[TOPIC]')),
4246 "identify|id":
4233 "identify|id":
4247 (identify,
4234 (identify,
4248 [('r', 'rev', '',
4235 [('r', 'rev', '',
4249 _('identify the specified revision'), _('REV')),
4236 _('identify the specified revision'), _('REV')),
4250 ('n', 'num', None, _('show local revision number')),
4237 ('n', 'num', None, _('show local revision number')),
4251 ('i', 'id', None, _('show global revision id')),
4238 ('i', 'id', None, _('show global revision id')),
4252 ('b', 'branch', None, _('show branch')),
4239 ('b', 'branch', None, _('show branch')),
4253 ('t', 'tags', None, _('show tags'))],
4240 ('t', 'tags', None, _('show tags'))],
4254 _('[-nibt] [-r REV] [SOURCE]')),
4241 _('[-nibt] [-r REV] [SOURCE]')),
4255 "import|patch":
4242 "import|patch":
4256 (import_,
4243 (import_,
4257 [('p', 'strip', 1,
4244 [('p', 'strip', 1,
4258 _('directory strip option for patch. This has the same '
4245 _('directory strip option for patch. This has the same '
4259 'meaning as the corresponding patch option'),
4246 'meaning as the corresponding patch option'),
4260 _('NUM')),
4247 _('NUM')),
4261 ('b', 'base', '',
4248 ('b', 'base', '',
4262 _('base path'), _('PATH')),
4249 _('base path'), _('PATH')),
4263 ('f', 'force', None,
4250 ('f', 'force', None,
4264 _('skip check for outstanding uncommitted changes')),
4251 _('skip check for outstanding uncommitted changes')),
4265 ('', 'no-commit', None,
4252 ('', 'no-commit', None,
4266 _("don't commit, just update the working directory")),
4253 _("don't commit, just update the working directory")),
4267 ('', 'exact', None,
4254 ('', 'exact', None,
4268 _('apply patch to the nodes from which it was generated')),
4255 _('apply patch to the nodes from which it was generated')),
4269 ('', 'import-branch', None,
4256 ('', 'import-branch', None,
4270 _('use any branch information in patch (implied by --exact)'))] +
4257 _('use any branch information in patch (implied by --exact)'))] +
4271 commitopts + commitopts2 + similarityopts,
4258 commitopts + commitopts2 + similarityopts,
4272 _('[OPTION]... PATCH...')),
4259 _('[OPTION]... PATCH...')),
4273 "incoming|in":
4260 "incoming|in":
4274 (incoming,
4261 (incoming,
4275 [('f', 'force', None,
4262 [('f', 'force', None,
4276 _('run even if remote repository is unrelated')),
4263 _('run even if remote repository is unrelated')),
4277 ('n', 'newest-first', None, _('show newest record first')),
4264 ('n', 'newest-first', None, _('show newest record first')),
4278 ('', 'bundle', '',
4265 ('', 'bundle', '',
4279 _('file to store the bundles into'), _('FILE')),
4266 _('file to store the bundles into'), _('FILE')),
4280 ('r', 'rev', [],
4267 ('r', 'rev', [],
4281 _('a remote changeset intended to be added'), _('REV')),
4268 _('a remote changeset intended to be added'), _('REV')),
4282 ('b', 'branch', [],
4269 ('b', 'branch', [],
4283 _('a specific branch you would like to pull'), _('BRANCH')),
4270 _('a specific branch you would like to pull'), _('BRANCH')),
4284 ] + logopts + remoteopts,
4271 ] + logopts + remoteopts,
4285 _('[-p] [-n] [-M] [-f] [-r REV]...'
4272 _('[-p] [-n] [-M] [-f] [-r REV]...'
4286 ' [--bundle FILENAME] [SOURCE]')),
4273 ' [--bundle FILENAME] [SOURCE]')),
4287 "^init":
4274 "^init":
4288 (init,
4275 (init,
4289 remoteopts,
4276 remoteopts,
4290 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4277 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4291 "locate":
4278 "locate":
4292 (locate,
4279 (locate,
4293 [('r', 'rev', '',
4280 [('r', 'rev', '',
4294 _('search the repository as it is in REV'), _('REV')),
4281 _('search the repository as it is in REV'), _('REV')),
4295 ('0', 'print0', None,
4282 ('0', 'print0', None,
4296 _('end filenames with NUL, for use with xargs')),
4283 _('end filenames with NUL, for use with xargs')),
4297 ('f', 'fullpath', None,
4284 ('f', 'fullpath', None,
4298 _('print complete paths from the filesystem root')),
4285 _('print complete paths from the filesystem root')),
4299 ] + walkopts,
4286 ] + walkopts,
4300 _('[OPTION]... [PATTERN]...')),
4287 _('[OPTION]... [PATTERN]...')),
4301 "^log|history":
4288 "^log|history":
4302 (log,
4289 (log,
4303 [('f', 'follow', None,
4290 [('f', 'follow', None,
4304 _('follow changeset history,'
4291 _('follow changeset history,'
4305 ' or file history across copies and renames')),
4292 ' or file history across copies and renames')),
4306 ('', 'follow-first', None,
4293 ('', 'follow-first', None,
4307 _('only follow the first parent of merge changesets')),
4294 _('only follow the first parent of merge changesets')),
4308 ('d', 'date', '',
4295 ('d', 'date', '',
4309 _('show revisions matching date spec'), _('DATE')),
4296 _('show revisions matching date spec'), _('DATE')),
4310 ('C', 'copies', None, _('show copied files')),
4297 ('C', 'copies', None, _('show copied files')),
4311 ('k', 'keyword', [],
4298 ('k', 'keyword', [],
4312 _('do case-insensitive search for a given text'), _('TEXT')),
4299 _('do case-insensitive search for a given text'), _('TEXT')),
4313 ('r', 'rev', [],
4300 ('r', 'rev', [],
4314 _('show the specified revision or range'), _('REV')),
4301 _('show the specified revision or range'), _('REV')),
4315 ('', 'removed', None, _('include revisions where files were removed')),
4302 ('', 'removed', None, _('include revisions where files were removed')),
4316 ('m', 'only-merges', None, _('show only merges')),
4303 ('m', 'only-merges', None, _('show only merges')),
4317 ('u', 'user', [],
4304 ('u', 'user', [],
4318 _('revisions committed by user'), _('USER')),
4305 _('revisions committed by user'), _('USER')),
4319 ('', 'only-branch', [],
4306 ('', 'only-branch', [],
4320 _('show only changesets within the given named branch (DEPRECATED)'),
4307 _('show only changesets within the given named branch (DEPRECATED)'),
4321 _('BRANCH')),
4308 _('BRANCH')),
4322 ('b', 'branch', [],
4309 ('b', 'branch', [],
4323 _('show changesets within the given named branch'), _('BRANCH')),
4310 _('show changesets within the given named branch'), _('BRANCH')),
4324 ('P', 'prune', [],
4311 ('P', 'prune', [],
4325 _('do not display revision or any of its ancestors'), _('REV')),
4312 _('do not display revision or any of its ancestors'), _('REV')),
4326 ] + logopts + walkopts,
4313 ] + logopts + walkopts,
4327 _('[OPTION]... [FILE]')),
4314 _('[OPTION]... [FILE]')),
4328 "manifest":
4315 "manifest":
4329 (manifest,
4316 (manifest,
4330 [('r', 'rev', '',
4317 [('r', 'rev', '',
4331 _('revision to display'), _('REV'))],
4318 _('revision to display'), _('REV'))],
4332 _('[-r REV]')),
4319 _('[-r REV]')),
4333 "^merge":
4320 "^merge":
4334 (merge,
4321 (merge,
4335 [('f', 'force', None, _('force a merge with outstanding changes')),
4322 [('f', 'force', None, _('force a merge with outstanding changes')),
4336 ('r', 'rev', '',
4323 ('r', 'rev', '',
4337 _('revision to merge'), _('REV')),
4324 _('revision to merge'), _('REV')),
4338 ('P', 'preview', None,
4325 ('P', 'preview', None,
4339 _('review revisions to merge (no merge is performed)'))],
4326 _('review revisions to merge (no merge is performed)'))],
4340 _('[-P] [-f] [[-r] REV]')),
4327 _('[-P] [-f] [[-r] REV]')),
4341 "outgoing|out":
4328 "outgoing|out":
4342 (outgoing,
4329 (outgoing,
4343 [('f', 'force', None,
4330 [('f', 'force', None,
4344 _('run even when the destination is unrelated')),
4331 _('run even when the destination is unrelated')),
4345 ('r', 'rev', [],
4332 ('r', 'rev', [],
4346 _('a changeset intended to be included in the destination'),
4333 _('a changeset intended to be included in the destination'),
4347 _('REV')),
4334 _('REV')),
4348 ('n', 'newest-first', None, _('show newest record first')),
4335 ('n', 'newest-first', None, _('show newest record first')),
4349 ('b', 'branch', [],
4336 ('b', 'branch', [],
4350 _('a specific branch you would like to push'), _('BRANCH')),
4337 _('a specific branch you would like to push'), _('BRANCH')),
4351 ] + logopts + remoteopts,
4338 ] + logopts + remoteopts,
4352 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4339 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4353 "parents":
4340 "parents":
4354 (parents,
4341 (parents,
4355 [('r', 'rev', '',
4342 [('r', 'rev', '',
4356 _('show parents of the specified revision'), _('REV')),
4343 _('show parents of the specified revision'), _('REV')),
4357 ] + templateopts,
4344 ] + templateopts,
4358 _('[-r REV] [FILE]')),
4345 _('[-r REV] [FILE]')),
4359 "paths": (paths, [], _('[NAME]')),
4346 "paths": (paths, [], _('[NAME]')),
4360 "^pull":
4347 "^pull":
4361 (pull,
4348 (pull,
4362 [('u', 'update', None,
4349 [('u', 'update', None,
4363 _('update to new branch head if changesets were pulled')),
4350 _('update to new branch head if changesets were pulled')),
4364 ('f', 'force', None,
4351 ('f', 'force', None,
4365 _('run even when remote repository is unrelated')),
4352 _('run even when remote repository is unrelated')),
4366 ('r', 'rev', [],
4353 ('r', 'rev', [],
4367 _('a remote changeset intended to be added'), _('REV')),
4354 _('a remote changeset intended to be added'), _('REV')),
4368 ('b', 'branch', [],
4355 ('b', 'branch', [],
4369 _('a specific branch you would like to pull'), _('BRANCH')),
4356 _('a specific branch you would like to pull'), _('BRANCH')),
4370 ] + remoteopts,
4357 ] + remoteopts,
4371 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4358 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4372 "^push":
4359 "^push":
4373 (push,
4360 (push,
4374 [('f', 'force', None, _('force push')),
4361 [('f', 'force', None, _('force push')),
4375 ('r', 'rev', [],
4362 ('r', 'rev', [],
4376 _('a changeset intended to be included in the destination'),
4363 _('a changeset intended to be included in the destination'),
4377 _('REV')),
4364 _('REV')),
4378 ('b', 'branch', [],
4365 ('b', 'branch', [],
4379 _('a specific branch you would like to push'), _('BRANCH')),
4366 _('a specific branch you would like to push'), _('BRANCH')),
4380 ('', 'new-branch', False, _('allow pushing a new branch')),
4367 ('', 'new-branch', False, _('allow pushing a new branch')),
4381 ] + remoteopts,
4368 ] + remoteopts,
4382 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4369 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4383 "recover": (recover, []),
4370 "recover": (recover, []),
4384 "^remove|rm":
4371 "^remove|rm":
4385 (remove,
4372 (remove,
4386 [('A', 'after', None, _('record delete for missing files')),
4373 [('A', 'after', None, _('record delete for missing files')),
4387 ('f', 'force', None,
4374 ('f', 'force', None,
4388 _('remove (and delete) file even if added or modified')),
4375 _('remove (and delete) file even if added or modified')),
4389 ] + walkopts,
4376 ] + walkopts,
4390 _('[OPTION]... FILE...')),
4377 _('[OPTION]... FILE...')),
4391 "rename|mv":
4378 "rename|mv":
4392 (rename,
4379 (rename,
4393 [('A', 'after', None, _('record a rename that has already occurred')),
4380 [('A', 'after', None, _('record a rename that has already occurred')),
4394 ('f', 'force', None,
4381 ('f', 'force', None,
4395 _('forcibly copy over an existing managed file')),
4382 _('forcibly copy over an existing managed file')),
4396 ] + walkopts + dryrunopts,
4383 ] + walkopts + dryrunopts,
4397 _('[OPTION]... SOURCE... DEST')),
4384 _('[OPTION]... SOURCE... DEST')),
4398 "resolve":
4385 "resolve":
4399 (resolve,
4386 (resolve,
4400 [('a', 'all', None, _('select all unresolved files')),
4387 [('a', 'all', None, _('select all unresolved files')),
4401 ('l', 'list', None, _('list state of files needing merge')),
4388 ('l', 'list', None, _('list state of files needing merge')),
4402 ('m', 'mark', None, _('mark files as resolved')),
4389 ('m', 'mark', None, _('mark files as resolved')),
4403 ('u', 'unmark', None, _('mark files as unresolved')),
4390 ('u', 'unmark', None, _('mark files as unresolved')),
4404 ('n', 'no-status', None, _('hide status prefix'))]
4391 ('n', 'no-status', None, _('hide status prefix'))]
4405 + walkopts,
4392 + walkopts,
4406 _('[OPTION]... [FILE]...')),
4393 _('[OPTION]... [FILE]...')),
4407 "revert":
4394 "revert":
4408 (revert,
4395 (revert,
4409 [('a', 'all', None, _('revert all changes when no arguments given')),
4396 [('a', 'all', None, _('revert all changes when no arguments given')),
4410 ('d', 'date', '',
4397 ('d', 'date', '',
4411 _('tipmost revision matching date'), _('DATE')),
4398 _('tipmost revision matching date'), _('DATE')),
4412 ('r', 'rev', '',
4399 ('r', 'rev', '',
4413 _('revert to the specified revision'), _('REV')),
4400 _('revert to the specified revision'), _('REV')),
4414 ('', 'no-backup', None, _('do not save backup copies of files')),
4401 ('', 'no-backup', None, _('do not save backup copies of files')),
4415 ] + walkopts + dryrunopts,
4402 ] + walkopts + dryrunopts,
4416 _('[OPTION]... [-r REV] [NAME]...')),
4403 _('[OPTION]... [-r REV] [NAME]...')),
4417 "rollback": (rollback, dryrunopts),
4404 "rollback": (rollback, dryrunopts),
4418 "root": (root, []),
4405 "root": (root, []),
4419 "^serve":
4406 "^serve":
4420 (serve,
4407 (serve,
4421 [('A', 'accesslog', '',
4408 [('A', 'accesslog', '',
4422 _('name of access log file to write to'), _('FILE')),
4409 _('name of access log file to write to'), _('FILE')),
4423 ('d', 'daemon', None, _('run server in background')),
4410 ('d', 'daemon', None, _('run server in background')),
4424 ('', 'daemon-pipefds', '',
4411 ('', 'daemon-pipefds', '',
4425 _('used internally by daemon mode'), _('NUM')),
4412 _('used internally by daemon mode'), _('NUM')),
4426 ('E', 'errorlog', '',
4413 ('E', 'errorlog', '',
4427 _('name of error log file to write to'), _('FILE')),
4414 _('name of error log file to write to'), _('FILE')),
4428 # use string type, then we can check if something was passed
4415 # use string type, then we can check if something was passed
4429 ('p', 'port', '',
4416 ('p', 'port', '',
4430 _('port to listen on (default: 8000)'), _('PORT')),
4417 _('port to listen on (default: 8000)'), _('PORT')),
4431 ('a', 'address', '',
4418 ('a', 'address', '',
4432 _('address to listen on (default: all interfaces)'), _('ADDR')),
4419 _('address to listen on (default: all interfaces)'), _('ADDR')),
4433 ('', 'prefix', '',
4420 ('', 'prefix', '',
4434 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4421 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4435 ('n', 'name', '',
4422 ('n', 'name', '',
4436 _('name to show in web pages (default: working directory)'),
4423 _('name to show in web pages (default: working directory)'),
4437 _('NAME')),
4424 _('NAME')),
4438 ('', 'web-conf', '',
4425 ('', 'web-conf', '',
4439 _('name of the hgweb config file (serve more than one repository)'),
4426 _('name of the hgweb config file (serve more than one repository)'),
4440 _('FILE')),
4427 _('FILE')),
4441 ('', 'webdir-conf', '',
4428 ('', 'webdir-conf', '',
4442 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4429 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4443 ('', 'pid-file', '',
4430 ('', 'pid-file', '',
4444 _('name of file to write process ID to'), _('FILE')),
4431 _('name of file to write process ID to'), _('FILE')),
4445 ('', 'stdio', None, _('for remote clients')),
4432 ('', 'stdio', None, _('for remote clients')),
4446 ('t', 'templates', '',
4433 ('t', 'templates', '',
4447 _('web templates to use'), _('TEMPLATE')),
4434 _('web templates to use'), _('TEMPLATE')),
4448 ('', 'style', '',
4435 ('', 'style', '',
4449 _('template style to use'), _('STYLE')),
4436 _('template style to use'), _('STYLE')),
4450 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4437 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4451 ('', 'certificate', '',
4438 ('', 'certificate', '',
4452 _('SSL certificate file'), _('FILE'))],
4439 _('SSL certificate file'), _('FILE'))],
4453 _('[OPTION]...')),
4440 _('[OPTION]...')),
4454 "showconfig|debugconfig":
4441 "showconfig|debugconfig":
4455 (showconfig,
4442 (showconfig,
4456 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4443 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4457 _('[-u] [NAME]...')),
4444 _('[-u] [NAME]...')),
4458 "^summary|sum":
4445 "^summary|sum":
4459 (summary,
4446 (summary,
4460 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4447 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4461 "^status|st":
4448 "^status|st":
4462 (status,
4449 (status,
4463 [('A', 'all', None, _('show status of all files')),
4450 [('A', 'all', None, _('show status of all files')),
4464 ('m', 'modified', None, _('show only modified files')),
4451 ('m', 'modified', None, _('show only modified files')),
4465 ('a', 'added', None, _('show only added files')),
4452 ('a', 'added', None, _('show only added files')),
4466 ('r', 'removed', None, _('show only removed files')),
4453 ('r', 'removed', None, _('show only removed files')),
4467 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4454 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4468 ('c', 'clean', None, _('show only files without changes')),
4455 ('c', 'clean', None, _('show only files without changes')),
4469 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4456 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4470 ('i', 'ignored', None, _('show only ignored files')),
4457 ('i', 'ignored', None, _('show only ignored files')),
4471 ('n', 'no-status', None, _('hide status prefix')),
4458 ('n', 'no-status', None, _('hide status prefix')),
4472 ('C', 'copies', None, _('show source of copied files')),
4459 ('C', 'copies', None, _('show source of copied files')),
4473 ('0', 'print0', None,
4460 ('0', 'print0', None,
4474 _('end filenames with NUL, for use with xargs')),
4461 _('end filenames with NUL, for use with xargs')),
4475 ('', 'rev', [],
4462 ('', 'rev', [],
4476 _('show difference from revision'), _('REV')),
4463 _('show difference from revision'), _('REV')),
4477 ('', 'change', '',
4464 ('', 'change', '',
4478 _('list the changed files of a revision'), _('REV')),
4465 _('list the changed files of a revision'), _('REV')),
4479 ] + walkopts + subrepoopts,
4466 ] + walkopts + subrepoopts,
4480 _('[OPTION]... [FILE]...')),
4467 _('[OPTION]... [FILE]...')),
4481 "tag":
4468 "tag":
4482 (tag,
4469 (tag,
4483 [('f', 'force', None, _('replace existing tag')),
4470 [('f', 'force', None, _('replace existing tag')),
4484 ('l', 'local', None, _('make the tag local')),
4471 ('l', 'local', None, _('make the tag local')),
4485 ('r', 'rev', '',
4472 ('r', 'rev', '',
4486 _('revision to tag'), _('REV')),
4473 _('revision to tag'), _('REV')),
4487 ('', 'remove', None, _('remove a tag')),
4474 ('', 'remove', None, _('remove a tag')),
4488 # -l/--local is already there, commitopts cannot be used
4475 # -l/--local is already there, commitopts cannot be used
4489 ('e', 'edit', None, _('edit commit message')),
4476 ('e', 'edit', None, _('edit commit message')),
4490 ('m', 'message', '',
4477 ('m', 'message', '',
4491 _('use <text> as commit message'), _('TEXT')),
4478 _('use <text> as commit message'), _('TEXT')),
4492 ] + commitopts2,
4479 ] + commitopts2,
4493 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4480 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4494 "tags": (tags, [], ''),
4481 "tags": (tags, [], ''),
4495 "tip":
4482 "tip":
4496 (tip,
4483 (tip,
4497 [('p', 'patch', None, _('show patch')),
4484 [('p', 'patch', None, _('show patch')),
4498 ('g', 'git', None, _('use git extended diff format')),
4485 ('g', 'git', None, _('use git extended diff format')),
4499 ] + templateopts,
4486 ] + templateopts,
4500 _('[-p] [-g]')),
4487 _('[-p] [-g]')),
4501 "unbundle":
4488 "unbundle":
4502 (unbundle,
4489 (unbundle,
4503 [('u', 'update', None,
4490 [('u', 'update', None,
4504 _('update to new branch head if changesets were unbundled'))],
4491 _('update to new branch head if changesets were unbundled'))],
4505 _('[-u] FILE...')),
4492 _('[-u] FILE...')),
4506 "^update|up|checkout|co":
4493 "^update|up|checkout|co":
4507 (update,
4494 (update,
4508 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4495 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4509 ('c', 'check', None, _('check for uncommitted changes')),
4496 ('c', 'check', None, _('check for uncommitted changes')),
4510 ('d', 'date', '',
4497 ('d', 'date', '',
4511 _('tipmost revision matching date'), _('DATE')),
4498 _('tipmost revision matching date'), _('DATE')),
4512 ('r', 'rev', '',
4499 ('r', 'rev', '',
4513 _('revision'), _('REV'))],
4500 _('revision'), _('REV'))],
4514 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4501 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4515 "verify": (verify, []),
4502 "verify": (verify, []),
4516 "version": (version_, []),
4503 "version": (version_, []),
4517 }
4504 }
4518
4505
4519 norepo = ("clone init version help debugcommands debugcomplete"
4506 norepo = ("clone init version help debugcommands debugcomplete"
4520 " debugdate debuginstall debugfsinfo debugpushkey")
4507 " debugdate debuginstall debugfsinfo debugpushkey")
4521 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4508 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4522 " debugdata debugindex debugindexdot")
4509 " debugdata debugindex debugindexdot")
General Comments 0
You need to be logged in to leave comments. Login now