##// END OF EJS Templates
commands: use a decorator to build table incrementally...
Adrian Buehlmann -
r14297:2daa5179 default
parent child Browse files
Show More
@@ -1,1253 +1,1268
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, tempfile
10 import os, sys, errno, re, tempfile
11 import util, scmutil, templater, patch, error, templatekw, wdutil
11 import util, scmutil, templater, patch, error, templatekw, wdutil
12 import match as matchmod
12 import match as matchmod
13 import revset, subrepo
13 import revset, subrepo
14
14
15 expandpats = wdutil.expandpats
15 expandpats = wdutil.expandpats
16 match = wdutil.match
16 match = wdutil.match
17 matchall = wdutil.matchall
17 matchall = wdutil.matchall
18 matchfiles = wdutil.matchfiles
18 matchfiles = wdutil.matchfiles
19 addremove = wdutil.addremove
19 addremove = wdutil.addremove
20 dirstatecopy = wdutil.dirstatecopy
20 dirstatecopy = wdutil.dirstatecopy
21
21
22 revrangesep = ':'
22 revrangesep = ':'
23
23
24 def parsealiases(cmd):
24 def parsealiases(cmd):
25 return cmd.lstrip("^").split("|")
25 return cmd.lstrip("^").split("|")
26
26
27 def findpossible(cmd, table, strict=False):
27 def findpossible(cmd, table, strict=False):
28 """
28 """
29 Return cmd -> (aliases, command table entry)
29 Return cmd -> (aliases, command table entry)
30 for each matching command.
30 for each matching command.
31 Return debug commands (or their aliases) only if no normal command matches.
31 Return debug commands (or their aliases) only if no normal command matches.
32 """
32 """
33 choice = {}
33 choice = {}
34 debugchoice = {}
34 debugchoice = {}
35 for e in table.keys():
35 for e in table.keys():
36 aliases = parsealiases(e)
36 aliases = parsealiases(e)
37 found = None
37 found = None
38 if cmd in aliases:
38 if cmd in aliases:
39 found = cmd
39 found = cmd
40 elif not strict:
40 elif not strict:
41 for a in aliases:
41 for a in aliases:
42 if a.startswith(cmd):
42 if a.startswith(cmd):
43 found = a
43 found = a
44 break
44 break
45 if found is not None:
45 if found is not None:
46 if aliases[0].startswith("debug") or found.startswith("debug"):
46 if aliases[0].startswith("debug") or found.startswith("debug"):
47 debugchoice[found] = (aliases, table[e])
47 debugchoice[found] = (aliases, table[e])
48 else:
48 else:
49 choice[found] = (aliases, table[e])
49 choice[found] = (aliases, table[e])
50
50
51 if not choice and debugchoice:
51 if not choice and debugchoice:
52 choice = debugchoice
52 choice = debugchoice
53
53
54 return choice
54 return choice
55
55
56 def findcmd(cmd, table, strict=True):
56 def findcmd(cmd, table, strict=True):
57 """Return (aliases, command table entry) for command string."""
57 """Return (aliases, command table entry) for command string."""
58 choice = findpossible(cmd, table, strict)
58 choice = findpossible(cmd, table, strict)
59
59
60 if cmd in choice:
60 if cmd in choice:
61 return choice[cmd]
61 return choice[cmd]
62
62
63 if len(choice) > 1:
63 if len(choice) > 1:
64 clist = choice.keys()
64 clist = choice.keys()
65 clist.sort()
65 clist.sort()
66 raise error.AmbiguousCommand(cmd, clist)
66 raise error.AmbiguousCommand(cmd, clist)
67
67
68 if choice:
68 if choice:
69 return choice.values()[0]
69 return choice.values()[0]
70
70
71 raise error.UnknownCommand(cmd)
71 raise error.UnknownCommand(cmd)
72
72
73 def findrepo(p):
73 def findrepo(p):
74 while not os.path.isdir(os.path.join(p, ".hg")):
74 while not os.path.isdir(os.path.join(p, ".hg")):
75 oldp, p = p, os.path.dirname(p)
75 oldp, p = p, os.path.dirname(p)
76 if p == oldp:
76 if p == oldp:
77 return None
77 return None
78
78
79 return p
79 return p
80
80
81 def bailifchanged(repo):
81 def bailifchanged(repo):
82 if repo.dirstate.p2() != nullid:
82 if repo.dirstate.p2() != nullid:
83 raise util.Abort(_('outstanding uncommitted merge'))
83 raise util.Abort(_('outstanding uncommitted merge'))
84 modified, added, removed, deleted = repo.status()[:4]
84 modified, added, removed, deleted = repo.status()[:4]
85 if modified or added or removed or deleted:
85 if modified or added or removed or deleted:
86 raise util.Abort(_("outstanding uncommitted changes"))
86 raise util.Abort(_("outstanding uncommitted changes"))
87
87
88 def logmessage(opts):
88 def logmessage(opts):
89 """ get the log message according to -m and -l option """
89 """ get the log message according to -m and -l option """
90 message = opts.get('message')
90 message = opts.get('message')
91 logfile = opts.get('logfile')
91 logfile = opts.get('logfile')
92
92
93 if message and logfile:
93 if message and logfile:
94 raise util.Abort(_('options --message and --logfile are mutually '
94 raise util.Abort(_('options --message and --logfile are mutually '
95 'exclusive'))
95 'exclusive'))
96 if not message and logfile:
96 if not message and logfile:
97 try:
97 try:
98 if logfile == '-':
98 if logfile == '-':
99 message = sys.stdin.read()
99 message = sys.stdin.read()
100 else:
100 else:
101 message = '\n'.join(util.readfile(logfile).splitlines())
101 message = '\n'.join(util.readfile(logfile).splitlines())
102 except IOError, inst:
102 except IOError, inst:
103 raise util.Abort(_("can't read commit message '%s': %s") %
103 raise util.Abort(_("can't read commit message '%s': %s") %
104 (logfile, inst.strerror))
104 (logfile, inst.strerror))
105 return message
105 return message
106
106
107 def loglimit(opts):
107 def loglimit(opts):
108 """get the log limit according to option -l/--limit"""
108 """get the log limit according to option -l/--limit"""
109 limit = opts.get('limit')
109 limit = opts.get('limit')
110 if limit:
110 if limit:
111 try:
111 try:
112 limit = int(limit)
112 limit = int(limit)
113 except ValueError:
113 except ValueError:
114 raise util.Abort(_('limit must be a positive integer'))
114 raise util.Abort(_('limit must be a positive integer'))
115 if limit <= 0:
115 if limit <= 0:
116 raise util.Abort(_('limit must be positive'))
116 raise util.Abort(_('limit must be positive'))
117 else:
117 else:
118 limit = None
118 limit = None
119 return limit
119 return limit
120
120
121 def revsingle(repo, revspec, default='.'):
121 def revsingle(repo, revspec, default='.'):
122 if not revspec:
122 if not revspec:
123 return repo[default]
123 return repo[default]
124
124
125 l = revrange(repo, [revspec])
125 l = revrange(repo, [revspec])
126 if len(l) < 1:
126 if len(l) < 1:
127 raise util.Abort(_('empty revision set'))
127 raise util.Abort(_('empty revision set'))
128 return repo[l[-1]]
128 return repo[l[-1]]
129
129
130 def revpair(repo, revs):
130 def revpair(repo, revs):
131 if not revs:
131 if not revs:
132 return repo.dirstate.p1(), None
132 return repo.dirstate.p1(), None
133
133
134 l = revrange(repo, revs)
134 l = revrange(repo, revs)
135
135
136 if len(l) == 0:
136 if len(l) == 0:
137 return repo.dirstate.p1(), None
137 return repo.dirstate.p1(), None
138
138
139 if len(l) == 1:
139 if len(l) == 1:
140 return repo.lookup(l[0]), None
140 return repo.lookup(l[0]), None
141
141
142 return repo.lookup(l[0]), repo.lookup(l[-1])
142 return repo.lookup(l[0]), repo.lookup(l[-1])
143
143
144 def revrange(repo, revs):
144 def revrange(repo, revs):
145 """Yield revision as strings from a list of revision specifications."""
145 """Yield revision as strings from a list of revision specifications."""
146
146
147 def revfix(repo, val, defval):
147 def revfix(repo, val, defval):
148 if not val and val != 0 and defval is not None:
148 if not val and val != 0 and defval is not None:
149 return defval
149 return defval
150 return repo.changelog.rev(repo.lookup(val))
150 return repo.changelog.rev(repo.lookup(val))
151
151
152 seen, l = set(), []
152 seen, l = set(), []
153 for spec in revs:
153 for spec in revs:
154 # attempt to parse old-style ranges first to deal with
154 # attempt to parse old-style ranges first to deal with
155 # things like old-tag which contain query metacharacters
155 # things like old-tag which contain query metacharacters
156 try:
156 try:
157 if isinstance(spec, int):
157 if isinstance(spec, int):
158 seen.add(spec)
158 seen.add(spec)
159 l.append(spec)
159 l.append(spec)
160 continue
160 continue
161
161
162 if revrangesep in spec:
162 if revrangesep in spec:
163 start, end = spec.split(revrangesep, 1)
163 start, end = spec.split(revrangesep, 1)
164 start = revfix(repo, start, 0)
164 start = revfix(repo, start, 0)
165 end = revfix(repo, end, len(repo) - 1)
165 end = revfix(repo, end, len(repo) - 1)
166 step = start > end and -1 or 1
166 step = start > end and -1 or 1
167 for rev in xrange(start, end + step, step):
167 for rev in xrange(start, end + step, step):
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 elif spec and spec in repo: # single unquoted rev
173 elif spec and spec in repo: # single unquoted rev
174 rev = revfix(repo, spec, None)
174 rev = revfix(repo, spec, None)
175 if rev in seen:
175 if rev in seen:
176 continue
176 continue
177 seen.add(rev)
177 seen.add(rev)
178 l.append(rev)
178 l.append(rev)
179 continue
179 continue
180 except error.RepoLookupError:
180 except error.RepoLookupError:
181 pass
181 pass
182
182
183 # fall through to new-style queries if old-style fails
183 # fall through to new-style queries if old-style fails
184 m = revset.match(repo.ui, spec)
184 m = revset.match(repo.ui, spec)
185 for r in m(repo, range(len(repo))):
185 for r in m(repo, range(len(repo))):
186 if r not in seen:
186 if r not in seen:
187 l.append(r)
187 l.append(r)
188 seen.update(l)
188 seen.update(l)
189
189
190 return l
190 return l
191
191
192 def makefilename(repo, pat, node,
192 def makefilename(repo, pat, node,
193 total=None, seqno=None, revwidth=None, pathname=None):
193 total=None, seqno=None, revwidth=None, pathname=None):
194 node_expander = {
194 node_expander = {
195 'H': lambda: hex(node),
195 'H': lambda: hex(node),
196 'R': lambda: str(repo.changelog.rev(node)),
196 'R': lambda: str(repo.changelog.rev(node)),
197 'h': lambda: short(node),
197 'h': lambda: short(node),
198 }
198 }
199 expander = {
199 expander = {
200 '%': lambda: '%',
200 '%': lambda: '%',
201 'b': lambda: os.path.basename(repo.root),
201 'b': lambda: os.path.basename(repo.root),
202 }
202 }
203
203
204 try:
204 try:
205 if node:
205 if node:
206 expander.update(node_expander)
206 expander.update(node_expander)
207 if node:
207 if node:
208 expander['r'] = (lambda:
208 expander['r'] = (lambda:
209 str(repo.changelog.rev(node)).zfill(revwidth or 0))
209 str(repo.changelog.rev(node)).zfill(revwidth or 0))
210 if total is not None:
210 if total is not None:
211 expander['N'] = lambda: str(total)
211 expander['N'] = lambda: str(total)
212 if seqno is not None:
212 if seqno is not None:
213 expander['n'] = lambda: str(seqno)
213 expander['n'] = lambda: str(seqno)
214 if total is not None and seqno is not None:
214 if total is not None and seqno is not None:
215 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
215 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
216 if pathname is not None:
216 if pathname is not None:
217 expander['s'] = lambda: os.path.basename(pathname)
217 expander['s'] = lambda: os.path.basename(pathname)
218 expander['d'] = lambda: os.path.dirname(pathname) or '.'
218 expander['d'] = lambda: os.path.dirname(pathname) or '.'
219 expander['p'] = lambda: pathname
219 expander['p'] = lambda: pathname
220
220
221 newname = []
221 newname = []
222 patlen = len(pat)
222 patlen = len(pat)
223 i = 0
223 i = 0
224 while i < patlen:
224 while i < patlen:
225 c = pat[i]
225 c = pat[i]
226 if c == '%':
226 if c == '%':
227 i += 1
227 i += 1
228 c = pat[i]
228 c = pat[i]
229 c = expander[c]()
229 c = expander[c]()
230 newname.append(c)
230 newname.append(c)
231 i += 1
231 i += 1
232 return ''.join(newname)
232 return ''.join(newname)
233 except KeyError, inst:
233 except KeyError, inst:
234 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
234 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
235 inst.args[0])
235 inst.args[0])
236
236
237 def makefileobj(repo, pat, node=None, total=None,
237 def makefileobj(repo, pat, node=None, total=None,
238 seqno=None, revwidth=None, mode='wb', pathname=None):
238 seqno=None, revwidth=None, mode='wb', pathname=None):
239
239
240 writable = mode not in ('r', 'rb')
240 writable = mode not in ('r', 'rb')
241
241
242 if not pat or pat == '-':
242 if not pat or pat == '-':
243 fp = writable and sys.stdout or sys.stdin
243 fp = writable and sys.stdout or sys.stdin
244 return os.fdopen(os.dup(fp.fileno()), mode)
244 return os.fdopen(os.dup(fp.fileno()), mode)
245 if hasattr(pat, 'write') and writable:
245 if hasattr(pat, 'write') and writable:
246 return pat
246 return pat
247 if hasattr(pat, 'read') and 'r' in mode:
247 if hasattr(pat, 'read') and 'r' in mode:
248 return pat
248 return pat
249 return open(makefilename(repo, pat, node, total, seqno, revwidth,
249 return open(makefilename(repo, pat, node, total, seqno, revwidth,
250 pathname),
250 pathname),
251 mode)
251 mode)
252
252
253 def copy(ui, repo, pats, opts, rename=False):
253 def copy(ui, repo, pats, opts, rename=False):
254 # called with the repo lock held
254 # called with the repo lock held
255 #
255 #
256 # hgsep => pathname that uses "/" to separate directories
256 # hgsep => pathname that uses "/" to separate directories
257 # ossep => pathname that uses os.sep to separate directories
257 # ossep => pathname that uses os.sep to separate directories
258 cwd = repo.getcwd()
258 cwd = repo.getcwd()
259 targets = {}
259 targets = {}
260 after = opts.get("after")
260 after = opts.get("after")
261 dryrun = opts.get("dry_run")
261 dryrun = opts.get("dry_run")
262 wctx = repo[None]
262 wctx = repo[None]
263
263
264 def walkpat(pat):
264 def walkpat(pat):
265 srcs = []
265 srcs = []
266 badstates = after and '?' or '?r'
266 badstates = after and '?' or '?r'
267 m = match(repo, [pat], opts, globbed=True)
267 m = match(repo, [pat], opts, globbed=True)
268 for abs in repo.walk(m):
268 for abs in repo.walk(m):
269 state = repo.dirstate[abs]
269 state = repo.dirstate[abs]
270 rel = m.rel(abs)
270 rel = m.rel(abs)
271 exact = m.exact(abs)
271 exact = m.exact(abs)
272 if state in badstates:
272 if state in badstates:
273 if exact and state == '?':
273 if exact and state == '?':
274 ui.warn(_('%s: not copying - file is not managed\n') % rel)
274 ui.warn(_('%s: not copying - file is not managed\n') % rel)
275 if exact and state == 'r':
275 if exact and state == 'r':
276 ui.warn(_('%s: not copying - file has been marked for'
276 ui.warn(_('%s: not copying - file has been marked for'
277 ' remove\n') % rel)
277 ' remove\n') % rel)
278 continue
278 continue
279 # abs: hgsep
279 # abs: hgsep
280 # rel: ossep
280 # rel: ossep
281 srcs.append((abs, rel, exact))
281 srcs.append((abs, rel, exact))
282 return srcs
282 return srcs
283
283
284 # abssrc: hgsep
284 # abssrc: hgsep
285 # relsrc: ossep
285 # relsrc: ossep
286 # otarget: ossep
286 # otarget: ossep
287 def copyfile(abssrc, relsrc, otarget, exact):
287 def copyfile(abssrc, relsrc, otarget, exact):
288 abstarget = scmutil.canonpath(repo.root, cwd, otarget)
288 abstarget = scmutil.canonpath(repo.root, cwd, otarget)
289 reltarget = repo.pathto(abstarget, cwd)
289 reltarget = repo.pathto(abstarget, cwd)
290 target = repo.wjoin(abstarget)
290 target = repo.wjoin(abstarget)
291 src = repo.wjoin(abssrc)
291 src = repo.wjoin(abssrc)
292 state = repo.dirstate[abstarget]
292 state = repo.dirstate[abstarget]
293
293
294 scmutil.checkportable(ui, abstarget)
294 scmutil.checkportable(ui, abstarget)
295
295
296 # check for collisions
296 # check for collisions
297 prevsrc = targets.get(abstarget)
297 prevsrc = targets.get(abstarget)
298 if prevsrc is not None:
298 if prevsrc is not None:
299 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
299 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
300 (reltarget, repo.pathto(abssrc, cwd),
300 (reltarget, repo.pathto(abssrc, cwd),
301 repo.pathto(prevsrc, cwd)))
301 repo.pathto(prevsrc, cwd)))
302 return
302 return
303
303
304 # check for overwrites
304 # check for overwrites
305 exists = os.path.lexists(target)
305 exists = os.path.lexists(target)
306 if not after and exists or after and state in 'mn':
306 if not after and exists or after and state in 'mn':
307 if not opts['force']:
307 if not opts['force']:
308 ui.warn(_('%s: not overwriting - file exists\n') %
308 ui.warn(_('%s: not overwriting - file exists\n') %
309 reltarget)
309 reltarget)
310 return
310 return
311
311
312 if after:
312 if after:
313 if not exists:
313 if not exists:
314 if rename:
314 if rename:
315 ui.warn(_('%s: not recording move - %s does not exist\n') %
315 ui.warn(_('%s: not recording move - %s does not exist\n') %
316 (relsrc, reltarget))
316 (relsrc, reltarget))
317 else:
317 else:
318 ui.warn(_('%s: not recording copy - %s does not exist\n') %
318 ui.warn(_('%s: not recording copy - %s does not exist\n') %
319 (relsrc, reltarget))
319 (relsrc, reltarget))
320 return
320 return
321 elif not dryrun:
321 elif not dryrun:
322 try:
322 try:
323 if exists:
323 if exists:
324 os.unlink(target)
324 os.unlink(target)
325 targetdir = os.path.dirname(target) or '.'
325 targetdir = os.path.dirname(target) or '.'
326 if not os.path.isdir(targetdir):
326 if not os.path.isdir(targetdir):
327 os.makedirs(targetdir)
327 os.makedirs(targetdir)
328 util.copyfile(src, target)
328 util.copyfile(src, target)
329 except IOError, inst:
329 except IOError, inst:
330 if inst.errno == errno.ENOENT:
330 if inst.errno == errno.ENOENT:
331 ui.warn(_('%s: deleted in working copy\n') % relsrc)
331 ui.warn(_('%s: deleted in working copy\n') % relsrc)
332 else:
332 else:
333 ui.warn(_('%s: cannot copy - %s\n') %
333 ui.warn(_('%s: cannot copy - %s\n') %
334 (relsrc, inst.strerror))
334 (relsrc, inst.strerror))
335 return True # report a failure
335 return True # report a failure
336
336
337 if ui.verbose or not exact:
337 if ui.verbose or not exact:
338 if rename:
338 if rename:
339 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
339 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
340 else:
340 else:
341 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
341 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
342
342
343 targets[abstarget] = abssrc
343 targets[abstarget] = abssrc
344
344
345 # fix up dirstate
345 # fix up dirstate
346 dirstatecopy(ui, repo, wctx, abssrc, abstarget, dryrun=dryrun, cwd=cwd)
346 dirstatecopy(ui, repo, wctx, abssrc, abstarget, dryrun=dryrun, cwd=cwd)
347 if rename and not dryrun:
347 if rename and not dryrun:
348 wctx.remove([abssrc], not after)
348 wctx.remove([abssrc], not after)
349
349
350 # pat: ossep
350 # pat: ossep
351 # dest ossep
351 # dest ossep
352 # srcs: list of (hgsep, hgsep, ossep, bool)
352 # srcs: list of (hgsep, hgsep, ossep, bool)
353 # return: function that takes hgsep and returns ossep
353 # return: function that takes hgsep and returns ossep
354 def targetpathfn(pat, dest, srcs):
354 def targetpathfn(pat, dest, srcs):
355 if os.path.isdir(pat):
355 if os.path.isdir(pat):
356 abspfx = scmutil.canonpath(repo.root, cwd, pat)
356 abspfx = scmutil.canonpath(repo.root, cwd, pat)
357 abspfx = util.localpath(abspfx)
357 abspfx = util.localpath(abspfx)
358 if destdirexists:
358 if destdirexists:
359 striplen = len(os.path.split(abspfx)[0])
359 striplen = len(os.path.split(abspfx)[0])
360 else:
360 else:
361 striplen = len(abspfx)
361 striplen = len(abspfx)
362 if striplen:
362 if striplen:
363 striplen += len(os.sep)
363 striplen += len(os.sep)
364 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
364 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
365 elif destdirexists:
365 elif destdirexists:
366 res = lambda p: os.path.join(dest,
366 res = lambda p: os.path.join(dest,
367 os.path.basename(util.localpath(p)))
367 os.path.basename(util.localpath(p)))
368 else:
368 else:
369 res = lambda p: dest
369 res = lambda p: dest
370 return res
370 return res
371
371
372 # pat: ossep
372 # pat: ossep
373 # dest ossep
373 # dest ossep
374 # srcs: list of (hgsep, hgsep, ossep, bool)
374 # srcs: list of (hgsep, hgsep, ossep, bool)
375 # return: function that takes hgsep and returns ossep
375 # return: function that takes hgsep and returns ossep
376 def targetpathafterfn(pat, dest, srcs):
376 def targetpathafterfn(pat, dest, srcs):
377 if matchmod.patkind(pat):
377 if matchmod.patkind(pat):
378 # a mercurial pattern
378 # a mercurial pattern
379 res = lambda p: os.path.join(dest,
379 res = lambda p: os.path.join(dest,
380 os.path.basename(util.localpath(p)))
380 os.path.basename(util.localpath(p)))
381 else:
381 else:
382 abspfx = scmutil.canonpath(repo.root, cwd, pat)
382 abspfx = scmutil.canonpath(repo.root, cwd, pat)
383 if len(abspfx) < len(srcs[0][0]):
383 if len(abspfx) < len(srcs[0][0]):
384 # A directory. Either the target path contains the last
384 # A directory. Either the target path contains the last
385 # component of the source path or it does not.
385 # component of the source path or it does not.
386 def evalpath(striplen):
386 def evalpath(striplen):
387 score = 0
387 score = 0
388 for s in srcs:
388 for s in srcs:
389 t = os.path.join(dest, util.localpath(s[0])[striplen:])
389 t = os.path.join(dest, util.localpath(s[0])[striplen:])
390 if os.path.lexists(t):
390 if os.path.lexists(t):
391 score += 1
391 score += 1
392 return score
392 return score
393
393
394 abspfx = util.localpath(abspfx)
394 abspfx = util.localpath(abspfx)
395 striplen = len(abspfx)
395 striplen = len(abspfx)
396 if striplen:
396 if striplen:
397 striplen += len(os.sep)
397 striplen += len(os.sep)
398 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
398 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
399 score = evalpath(striplen)
399 score = evalpath(striplen)
400 striplen1 = len(os.path.split(abspfx)[0])
400 striplen1 = len(os.path.split(abspfx)[0])
401 if striplen1:
401 if striplen1:
402 striplen1 += len(os.sep)
402 striplen1 += len(os.sep)
403 if evalpath(striplen1) > score:
403 if evalpath(striplen1) > score:
404 striplen = striplen1
404 striplen = striplen1
405 res = lambda p: os.path.join(dest,
405 res = lambda p: os.path.join(dest,
406 util.localpath(p)[striplen:])
406 util.localpath(p)[striplen:])
407 else:
407 else:
408 # a file
408 # a file
409 if destdirexists:
409 if destdirexists:
410 res = lambda p: os.path.join(dest,
410 res = lambda p: os.path.join(dest,
411 os.path.basename(util.localpath(p)))
411 os.path.basename(util.localpath(p)))
412 else:
412 else:
413 res = lambda p: dest
413 res = lambda p: dest
414 return res
414 return res
415
415
416
416
417 pats = expandpats(pats)
417 pats = expandpats(pats)
418 if not pats:
418 if not pats:
419 raise util.Abort(_('no source or destination specified'))
419 raise util.Abort(_('no source or destination specified'))
420 if len(pats) == 1:
420 if len(pats) == 1:
421 raise util.Abort(_('no destination specified'))
421 raise util.Abort(_('no destination specified'))
422 dest = pats.pop()
422 dest = pats.pop()
423 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
423 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
424 if not destdirexists:
424 if not destdirexists:
425 if len(pats) > 1 or matchmod.patkind(pats[0]):
425 if len(pats) > 1 or matchmod.patkind(pats[0]):
426 raise util.Abort(_('with multiple sources, destination must be an '
426 raise util.Abort(_('with multiple sources, destination must be an '
427 'existing directory'))
427 'existing directory'))
428 if util.endswithsep(dest):
428 if util.endswithsep(dest):
429 raise util.Abort(_('destination %s is not a directory') % dest)
429 raise util.Abort(_('destination %s is not a directory') % dest)
430
430
431 tfn = targetpathfn
431 tfn = targetpathfn
432 if after:
432 if after:
433 tfn = targetpathafterfn
433 tfn = targetpathafterfn
434 copylist = []
434 copylist = []
435 for pat in pats:
435 for pat in pats:
436 srcs = walkpat(pat)
436 srcs = walkpat(pat)
437 if not srcs:
437 if not srcs:
438 continue
438 continue
439 copylist.append((tfn(pat, dest, srcs), srcs))
439 copylist.append((tfn(pat, dest, srcs), srcs))
440 if not copylist:
440 if not copylist:
441 raise util.Abort(_('no files to copy'))
441 raise util.Abort(_('no files to copy'))
442
442
443 errors = 0
443 errors = 0
444 for targetpath, srcs in copylist:
444 for targetpath, srcs in copylist:
445 for abssrc, relsrc, exact in srcs:
445 for abssrc, relsrc, exact in srcs:
446 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
446 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
447 errors += 1
447 errors += 1
448
448
449 if errors:
449 if errors:
450 ui.warn(_('(consider using --after)\n'))
450 ui.warn(_('(consider using --after)\n'))
451
451
452 return errors != 0
452 return errors != 0
453
453
454 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
454 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
455 runargs=None, appendpid=False):
455 runargs=None, appendpid=False):
456 '''Run a command as a service.'''
456 '''Run a command as a service.'''
457
457
458 if opts['daemon'] and not opts['daemon_pipefds']:
458 if opts['daemon'] and not opts['daemon_pipefds']:
459 # Signal child process startup with file removal
459 # Signal child process startup with file removal
460 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
460 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
461 os.close(lockfd)
461 os.close(lockfd)
462 try:
462 try:
463 if not runargs:
463 if not runargs:
464 runargs = util.hgcmd() + sys.argv[1:]
464 runargs = util.hgcmd() + sys.argv[1:]
465 runargs.append('--daemon-pipefds=%s' % lockpath)
465 runargs.append('--daemon-pipefds=%s' % lockpath)
466 # Don't pass --cwd to the child process, because we've already
466 # Don't pass --cwd to the child process, because we've already
467 # changed directory.
467 # changed directory.
468 for i in xrange(1, len(runargs)):
468 for i in xrange(1, len(runargs)):
469 if runargs[i].startswith('--cwd='):
469 if runargs[i].startswith('--cwd='):
470 del runargs[i]
470 del runargs[i]
471 break
471 break
472 elif runargs[i].startswith('--cwd'):
472 elif runargs[i].startswith('--cwd'):
473 del runargs[i:i + 2]
473 del runargs[i:i + 2]
474 break
474 break
475 def condfn():
475 def condfn():
476 return not os.path.exists(lockpath)
476 return not os.path.exists(lockpath)
477 pid = util.rundetached(runargs, condfn)
477 pid = util.rundetached(runargs, condfn)
478 if pid < 0:
478 if pid < 0:
479 raise util.Abort(_('child process failed to start'))
479 raise util.Abort(_('child process failed to start'))
480 finally:
480 finally:
481 try:
481 try:
482 os.unlink(lockpath)
482 os.unlink(lockpath)
483 except OSError, e:
483 except OSError, e:
484 if e.errno != errno.ENOENT:
484 if e.errno != errno.ENOENT:
485 raise
485 raise
486 if parentfn:
486 if parentfn:
487 return parentfn(pid)
487 return parentfn(pid)
488 else:
488 else:
489 return
489 return
490
490
491 if initfn:
491 if initfn:
492 initfn()
492 initfn()
493
493
494 if opts['pid_file']:
494 if opts['pid_file']:
495 mode = appendpid and 'a' or 'w'
495 mode = appendpid and 'a' or 'w'
496 fp = open(opts['pid_file'], mode)
496 fp = open(opts['pid_file'], mode)
497 fp.write(str(os.getpid()) + '\n')
497 fp.write(str(os.getpid()) + '\n')
498 fp.close()
498 fp.close()
499
499
500 if opts['daemon_pipefds']:
500 if opts['daemon_pipefds']:
501 lockpath = opts['daemon_pipefds']
501 lockpath = opts['daemon_pipefds']
502 try:
502 try:
503 os.setsid()
503 os.setsid()
504 except AttributeError:
504 except AttributeError:
505 pass
505 pass
506 os.unlink(lockpath)
506 os.unlink(lockpath)
507 util.hidewindow()
507 util.hidewindow()
508 sys.stdout.flush()
508 sys.stdout.flush()
509 sys.stderr.flush()
509 sys.stderr.flush()
510
510
511 nullfd = os.open(util.nulldev, os.O_RDWR)
511 nullfd = os.open(util.nulldev, os.O_RDWR)
512 logfilefd = nullfd
512 logfilefd = nullfd
513 if logfile:
513 if logfile:
514 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
514 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
515 os.dup2(nullfd, 0)
515 os.dup2(nullfd, 0)
516 os.dup2(logfilefd, 1)
516 os.dup2(logfilefd, 1)
517 os.dup2(logfilefd, 2)
517 os.dup2(logfilefd, 2)
518 if nullfd not in (0, 1, 2):
518 if nullfd not in (0, 1, 2):
519 os.close(nullfd)
519 os.close(nullfd)
520 if logfile and logfilefd not in (0, 1, 2):
520 if logfile and logfilefd not in (0, 1, 2):
521 os.close(logfilefd)
521 os.close(logfilefd)
522
522
523 if runfn:
523 if runfn:
524 return runfn()
524 return runfn()
525
525
526 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
526 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
527 opts=None):
527 opts=None):
528 '''export changesets as hg patches.'''
528 '''export changesets as hg patches.'''
529
529
530 total = len(revs)
530 total = len(revs)
531 revwidth = max([len(str(rev)) for rev in revs])
531 revwidth = max([len(str(rev)) for rev in revs])
532
532
533 def single(rev, seqno, fp):
533 def single(rev, seqno, fp):
534 ctx = repo[rev]
534 ctx = repo[rev]
535 node = ctx.node()
535 node = ctx.node()
536 parents = [p.node() for p in ctx.parents() if p]
536 parents = [p.node() for p in ctx.parents() if p]
537 branch = ctx.branch()
537 branch = ctx.branch()
538 if switch_parent:
538 if switch_parent:
539 parents.reverse()
539 parents.reverse()
540 prev = (parents and parents[0]) or nullid
540 prev = (parents and parents[0]) or nullid
541
541
542 shouldclose = False
542 shouldclose = False
543 if not fp:
543 if not fp:
544 fp = makefileobj(repo, template, node, total=total, seqno=seqno,
544 fp = makefileobj(repo, template, node, total=total, seqno=seqno,
545 revwidth=revwidth, mode='ab')
545 revwidth=revwidth, mode='ab')
546 if fp != template:
546 if fp != template:
547 shouldclose = True
547 shouldclose = True
548 if fp != sys.stdout and hasattr(fp, 'name'):
548 if fp != sys.stdout and hasattr(fp, 'name'):
549 repo.ui.note("%s\n" % fp.name)
549 repo.ui.note("%s\n" % fp.name)
550
550
551 fp.write("# HG changeset patch\n")
551 fp.write("# HG changeset patch\n")
552 fp.write("# User %s\n" % ctx.user())
552 fp.write("# User %s\n" % ctx.user())
553 fp.write("# Date %d %d\n" % ctx.date())
553 fp.write("# Date %d %d\n" % ctx.date())
554 if branch and branch != 'default':
554 if branch and branch != 'default':
555 fp.write("# Branch %s\n" % branch)
555 fp.write("# Branch %s\n" % branch)
556 fp.write("# Node ID %s\n" % hex(node))
556 fp.write("# Node ID %s\n" % hex(node))
557 fp.write("# Parent %s\n" % hex(prev))
557 fp.write("# Parent %s\n" % hex(prev))
558 if len(parents) > 1:
558 if len(parents) > 1:
559 fp.write("# Parent %s\n" % hex(parents[1]))
559 fp.write("# Parent %s\n" % hex(parents[1]))
560 fp.write(ctx.description().rstrip())
560 fp.write(ctx.description().rstrip())
561 fp.write("\n\n")
561 fp.write("\n\n")
562
562
563 for chunk in patch.diff(repo, prev, node, opts=opts):
563 for chunk in patch.diff(repo, prev, node, opts=opts):
564 fp.write(chunk)
564 fp.write(chunk)
565
565
566 if shouldclose:
566 if shouldclose:
567 fp.close()
567 fp.close()
568
568
569 for seqno, rev in enumerate(revs):
569 for seqno, rev in enumerate(revs):
570 single(rev, seqno + 1, fp)
570 single(rev, seqno + 1, fp)
571
571
572 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
572 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
573 changes=None, stat=False, fp=None, prefix='',
573 changes=None, stat=False, fp=None, prefix='',
574 listsubrepos=False):
574 listsubrepos=False):
575 '''show diff or diffstat.'''
575 '''show diff or diffstat.'''
576 if fp is None:
576 if fp is None:
577 write = ui.write
577 write = ui.write
578 else:
578 else:
579 def write(s, **kw):
579 def write(s, **kw):
580 fp.write(s)
580 fp.write(s)
581
581
582 if stat:
582 if stat:
583 diffopts = diffopts.copy(context=0)
583 diffopts = diffopts.copy(context=0)
584 width = 80
584 width = 80
585 if not ui.plain():
585 if not ui.plain():
586 width = ui.termwidth()
586 width = ui.termwidth()
587 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
587 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
588 prefix=prefix)
588 prefix=prefix)
589 for chunk, label in patch.diffstatui(util.iterlines(chunks),
589 for chunk, label in patch.diffstatui(util.iterlines(chunks),
590 width=width,
590 width=width,
591 git=diffopts.git):
591 git=diffopts.git):
592 write(chunk, label=label)
592 write(chunk, label=label)
593 else:
593 else:
594 for chunk, label in patch.diffui(repo, node1, node2, match,
594 for chunk, label in patch.diffui(repo, node1, node2, match,
595 changes, diffopts, prefix=prefix):
595 changes, diffopts, prefix=prefix):
596 write(chunk, label=label)
596 write(chunk, label=label)
597
597
598 if listsubrepos:
598 if listsubrepos:
599 ctx1 = repo[node1]
599 ctx1 = repo[node1]
600 ctx2 = repo[node2]
600 ctx2 = repo[node2]
601 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
601 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
602 if node2 is not None:
602 if node2 is not None:
603 node2 = ctx2.substate[subpath][1]
603 node2 = ctx2.substate[subpath][1]
604 submatch = matchmod.narrowmatcher(subpath, match)
604 submatch = matchmod.narrowmatcher(subpath, match)
605 sub.diff(diffopts, node2, submatch, changes=changes,
605 sub.diff(diffopts, node2, submatch, changes=changes,
606 stat=stat, fp=fp, prefix=prefix)
606 stat=stat, fp=fp, prefix=prefix)
607
607
608 class changeset_printer(object):
608 class changeset_printer(object):
609 '''show changeset information when templating not requested.'''
609 '''show changeset information when templating not requested.'''
610
610
611 def __init__(self, ui, repo, patch, diffopts, buffered):
611 def __init__(self, ui, repo, patch, diffopts, buffered):
612 self.ui = ui
612 self.ui = ui
613 self.repo = repo
613 self.repo = repo
614 self.buffered = buffered
614 self.buffered = buffered
615 self.patch = patch
615 self.patch = patch
616 self.diffopts = diffopts
616 self.diffopts = diffopts
617 self.header = {}
617 self.header = {}
618 self.hunk = {}
618 self.hunk = {}
619 self.lastheader = None
619 self.lastheader = None
620 self.footer = None
620 self.footer = None
621
621
622 def flush(self, rev):
622 def flush(self, rev):
623 if rev in self.header:
623 if rev in self.header:
624 h = self.header[rev]
624 h = self.header[rev]
625 if h != self.lastheader:
625 if h != self.lastheader:
626 self.lastheader = h
626 self.lastheader = h
627 self.ui.write(h)
627 self.ui.write(h)
628 del self.header[rev]
628 del self.header[rev]
629 if rev in self.hunk:
629 if rev in self.hunk:
630 self.ui.write(self.hunk[rev])
630 self.ui.write(self.hunk[rev])
631 del self.hunk[rev]
631 del self.hunk[rev]
632 return 1
632 return 1
633 return 0
633 return 0
634
634
635 def close(self):
635 def close(self):
636 if self.footer:
636 if self.footer:
637 self.ui.write(self.footer)
637 self.ui.write(self.footer)
638
638
639 def show(self, ctx, copies=None, matchfn=None, **props):
639 def show(self, ctx, copies=None, matchfn=None, **props):
640 if self.buffered:
640 if self.buffered:
641 self.ui.pushbuffer()
641 self.ui.pushbuffer()
642 self._show(ctx, copies, matchfn, props)
642 self._show(ctx, copies, matchfn, props)
643 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
643 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
644 else:
644 else:
645 self._show(ctx, copies, matchfn, props)
645 self._show(ctx, copies, matchfn, props)
646
646
647 def _show(self, ctx, copies, matchfn, props):
647 def _show(self, ctx, copies, matchfn, props):
648 '''show a single changeset or file revision'''
648 '''show a single changeset or file revision'''
649 changenode = ctx.node()
649 changenode = ctx.node()
650 rev = ctx.rev()
650 rev = ctx.rev()
651
651
652 if self.ui.quiet:
652 if self.ui.quiet:
653 self.ui.write("%d:%s\n" % (rev, short(changenode)),
653 self.ui.write("%d:%s\n" % (rev, short(changenode)),
654 label='log.node')
654 label='log.node')
655 return
655 return
656
656
657 log = self.repo.changelog
657 log = self.repo.changelog
658 date = util.datestr(ctx.date())
658 date = util.datestr(ctx.date())
659
659
660 hexfunc = self.ui.debugflag and hex or short
660 hexfunc = self.ui.debugflag and hex or short
661
661
662 parents = [(p, hexfunc(log.node(p)))
662 parents = [(p, hexfunc(log.node(p)))
663 for p in self._meaningful_parentrevs(log, rev)]
663 for p in self._meaningful_parentrevs(log, rev)]
664
664
665 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
665 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
666 label='log.changeset')
666 label='log.changeset')
667
667
668 branch = ctx.branch()
668 branch = ctx.branch()
669 # don't show the default branch name
669 # don't show the default branch name
670 if branch != 'default':
670 if branch != 'default':
671 self.ui.write(_("branch: %s\n") % branch,
671 self.ui.write(_("branch: %s\n") % branch,
672 label='log.branch')
672 label='log.branch')
673 for bookmark in self.repo.nodebookmarks(changenode):
673 for bookmark in self.repo.nodebookmarks(changenode):
674 self.ui.write(_("bookmark: %s\n") % bookmark,
674 self.ui.write(_("bookmark: %s\n") % bookmark,
675 label='log.bookmark')
675 label='log.bookmark')
676 for tag in self.repo.nodetags(changenode):
676 for tag in self.repo.nodetags(changenode):
677 self.ui.write(_("tag: %s\n") % tag,
677 self.ui.write(_("tag: %s\n") % tag,
678 label='log.tag')
678 label='log.tag')
679 for parent in parents:
679 for parent in parents:
680 self.ui.write(_("parent: %d:%s\n") % parent,
680 self.ui.write(_("parent: %d:%s\n") % parent,
681 label='log.parent')
681 label='log.parent')
682
682
683 if self.ui.debugflag:
683 if self.ui.debugflag:
684 mnode = ctx.manifestnode()
684 mnode = ctx.manifestnode()
685 self.ui.write(_("manifest: %d:%s\n") %
685 self.ui.write(_("manifest: %d:%s\n") %
686 (self.repo.manifest.rev(mnode), hex(mnode)),
686 (self.repo.manifest.rev(mnode), hex(mnode)),
687 label='ui.debug log.manifest')
687 label='ui.debug log.manifest')
688 self.ui.write(_("user: %s\n") % ctx.user(),
688 self.ui.write(_("user: %s\n") % ctx.user(),
689 label='log.user')
689 label='log.user')
690 self.ui.write(_("date: %s\n") % date,
690 self.ui.write(_("date: %s\n") % date,
691 label='log.date')
691 label='log.date')
692
692
693 if self.ui.debugflag:
693 if self.ui.debugflag:
694 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
694 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
695 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
695 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
696 files):
696 files):
697 if value:
697 if value:
698 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
698 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
699 label='ui.debug log.files')
699 label='ui.debug log.files')
700 elif ctx.files() and self.ui.verbose:
700 elif ctx.files() and self.ui.verbose:
701 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
701 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
702 label='ui.note log.files')
702 label='ui.note log.files')
703 if copies and self.ui.verbose:
703 if copies and self.ui.verbose:
704 copies = ['%s (%s)' % c for c in copies]
704 copies = ['%s (%s)' % c for c in copies]
705 self.ui.write(_("copies: %s\n") % ' '.join(copies),
705 self.ui.write(_("copies: %s\n") % ' '.join(copies),
706 label='ui.note log.copies')
706 label='ui.note log.copies')
707
707
708 extra = ctx.extra()
708 extra = ctx.extra()
709 if extra and self.ui.debugflag:
709 if extra and self.ui.debugflag:
710 for key, value in sorted(extra.items()):
710 for key, value in sorted(extra.items()):
711 self.ui.write(_("extra: %s=%s\n")
711 self.ui.write(_("extra: %s=%s\n")
712 % (key, value.encode('string_escape')),
712 % (key, value.encode('string_escape')),
713 label='ui.debug log.extra')
713 label='ui.debug log.extra')
714
714
715 description = ctx.description().strip()
715 description = ctx.description().strip()
716 if description:
716 if description:
717 if self.ui.verbose:
717 if self.ui.verbose:
718 self.ui.write(_("description:\n"),
718 self.ui.write(_("description:\n"),
719 label='ui.note log.description')
719 label='ui.note log.description')
720 self.ui.write(description,
720 self.ui.write(description,
721 label='ui.note log.description')
721 label='ui.note log.description')
722 self.ui.write("\n\n")
722 self.ui.write("\n\n")
723 else:
723 else:
724 self.ui.write(_("summary: %s\n") %
724 self.ui.write(_("summary: %s\n") %
725 description.splitlines()[0],
725 description.splitlines()[0],
726 label='log.summary')
726 label='log.summary')
727 self.ui.write("\n")
727 self.ui.write("\n")
728
728
729 self.showpatch(changenode, matchfn)
729 self.showpatch(changenode, matchfn)
730
730
731 def showpatch(self, node, matchfn):
731 def showpatch(self, node, matchfn):
732 if not matchfn:
732 if not matchfn:
733 matchfn = self.patch
733 matchfn = self.patch
734 if matchfn:
734 if matchfn:
735 stat = self.diffopts.get('stat')
735 stat = self.diffopts.get('stat')
736 diff = self.diffopts.get('patch')
736 diff = self.diffopts.get('patch')
737 diffopts = patch.diffopts(self.ui, self.diffopts)
737 diffopts = patch.diffopts(self.ui, self.diffopts)
738 prev = self.repo.changelog.parents(node)[0]
738 prev = self.repo.changelog.parents(node)[0]
739 if stat:
739 if stat:
740 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
740 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
741 match=matchfn, stat=True)
741 match=matchfn, stat=True)
742 if diff:
742 if diff:
743 if stat:
743 if stat:
744 self.ui.write("\n")
744 self.ui.write("\n")
745 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
745 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
746 match=matchfn, stat=False)
746 match=matchfn, stat=False)
747 self.ui.write("\n")
747 self.ui.write("\n")
748
748
749 def _meaningful_parentrevs(self, log, rev):
749 def _meaningful_parentrevs(self, log, rev):
750 """Return list of meaningful (or all if debug) parentrevs for rev.
750 """Return list of meaningful (or all if debug) parentrevs for rev.
751
751
752 For merges (two non-nullrev revisions) both parents are meaningful.
752 For merges (two non-nullrev revisions) both parents are meaningful.
753 Otherwise the first parent revision is considered meaningful if it
753 Otherwise the first parent revision is considered meaningful if it
754 is not the preceding revision.
754 is not the preceding revision.
755 """
755 """
756 parents = log.parentrevs(rev)
756 parents = log.parentrevs(rev)
757 if not self.ui.debugflag and parents[1] == nullrev:
757 if not self.ui.debugflag and parents[1] == nullrev:
758 if parents[0] >= rev - 1:
758 if parents[0] >= rev - 1:
759 parents = []
759 parents = []
760 else:
760 else:
761 parents = [parents[0]]
761 parents = [parents[0]]
762 return parents
762 return parents
763
763
764
764
765 class changeset_templater(changeset_printer):
765 class changeset_templater(changeset_printer):
766 '''format changeset information.'''
766 '''format changeset information.'''
767
767
768 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
768 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
769 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
769 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
770 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
770 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
771 defaulttempl = {
771 defaulttempl = {
772 'parent': '{rev}:{node|formatnode} ',
772 'parent': '{rev}:{node|formatnode} ',
773 'manifest': '{rev}:{node|formatnode}',
773 'manifest': '{rev}:{node|formatnode}',
774 'file_copy': '{name} ({source})',
774 'file_copy': '{name} ({source})',
775 'extra': '{key}={value|stringescape}'
775 'extra': '{key}={value|stringescape}'
776 }
776 }
777 # filecopy is preserved for compatibility reasons
777 # filecopy is preserved for compatibility reasons
778 defaulttempl['filecopy'] = defaulttempl['file_copy']
778 defaulttempl['filecopy'] = defaulttempl['file_copy']
779 self.t = templater.templater(mapfile, {'formatnode': formatnode},
779 self.t = templater.templater(mapfile, {'formatnode': formatnode},
780 cache=defaulttempl)
780 cache=defaulttempl)
781 self.cache = {}
781 self.cache = {}
782
782
783 def use_template(self, t):
783 def use_template(self, t):
784 '''set template string to use'''
784 '''set template string to use'''
785 self.t.cache['changeset'] = t
785 self.t.cache['changeset'] = t
786
786
787 def _meaningful_parentrevs(self, ctx):
787 def _meaningful_parentrevs(self, ctx):
788 """Return list of meaningful (or all if debug) parentrevs for rev.
788 """Return list of meaningful (or all if debug) parentrevs for rev.
789 """
789 """
790 parents = ctx.parents()
790 parents = ctx.parents()
791 if len(parents) > 1:
791 if len(parents) > 1:
792 return parents
792 return parents
793 if self.ui.debugflag:
793 if self.ui.debugflag:
794 return [parents[0], self.repo['null']]
794 return [parents[0], self.repo['null']]
795 if parents[0].rev() >= ctx.rev() - 1:
795 if parents[0].rev() >= ctx.rev() - 1:
796 return []
796 return []
797 return parents
797 return parents
798
798
799 def _show(self, ctx, copies, matchfn, props):
799 def _show(self, ctx, copies, matchfn, props):
800 '''show a single changeset or file revision'''
800 '''show a single changeset or file revision'''
801
801
802 showlist = templatekw.showlist
802 showlist = templatekw.showlist
803
803
804 # showparents() behaviour depends on ui trace level which
804 # showparents() behaviour depends on ui trace level which
805 # causes unexpected behaviours at templating level and makes
805 # causes unexpected behaviours at templating level and makes
806 # it harder to extract it in a standalone function. Its
806 # it harder to extract it in a standalone function. Its
807 # behaviour cannot be changed so leave it here for now.
807 # behaviour cannot be changed so leave it here for now.
808 def showparents(**args):
808 def showparents(**args):
809 ctx = args['ctx']
809 ctx = args['ctx']
810 parents = [[('rev', p.rev()), ('node', p.hex())]
810 parents = [[('rev', p.rev()), ('node', p.hex())]
811 for p in self._meaningful_parentrevs(ctx)]
811 for p in self._meaningful_parentrevs(ctx)]
812 return showlist('parent', parents, **args)
812 return showlist('parent', parents, **args)
813
813
814 props = props.copy()
814 props = props.copy()
815 props.update(templatekw.keywords)
815 props.update(templatekw.keywords)
816 props['parents'] = showparents
816 props['parents'] = showparents
817 props['templ'] = self.t
817 props['templ'] = self.t
818 props['ctx'] = ctx
818 props['ctx'] = ctx
819 props['repo'] = self.repo
819 props['repo'] = self.repo
820 props['revcache'] = {'copies': copies}
820 props['revcache'] = {'copies': copies}
821 props['cache'] = self.cache
821 props['cache'] = self.cache
822
822
823 # find correct templates for current mode
823 # find correct templates for current mode
824
824
825 tmplmodes = [
825 tmplmodes = [
826 (True, None),
826 (True, None),
827 (self.ui.verbose, 'verbose'),
827 (self.ui.verbose, 'verbose'),
828 (self.ui.quiet, 'quiet'),
828 (self.ui.quiet, 'quiet'),
829 (self.ui.debugflag, 'debug'),
829 (self.ui.debugflag, 'debug'),
830 ]
830 ]
831
831
832 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
832 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
833 for mode, postfix in tmplmodes:
833 for mode, postfix in tmplmodes:
834 for type in types:
834 for type in types:
835 cur = postfix and ('%s_%s' % (type, postfix)) or type
835 cur = postfix and ('%s_%s' % (type, postfix)) or type
836 if mode and cur in self.t:
836 if mode and cur in self.t:
837 types[type] = cur
837 types[type] = cur
838
838
839 try:
839 try:
840
840
841 # write header
841 # write header
842 if types['header']:
842 if types['header']:
843 h = templater.stringify(self.t(types['header'], **props))
843 h = templater.stringify(self.t(types['header'], **props))
844 if self.buffered:
844 if self.buffered:
845 self.header[ctx.rev()] = h
845 self.header[ctx.rev()] = h
846 else:
846 else:
847 if self.lastheader != h:
847 if self.lastheader != h:
848 self.lastheader = h
848 self.lastheader = h
849 self.ui.write(h)
849 self.ui.write(h)
850
850
851 # write changeset metadata, then patch if requested
851 # write changeset metadata, then patch if requested
852 key = types['changeset']
852 key = types['changeset']
853 self.ui.write(templater.stringify(self.t(key, **props)))
853 self.ui.write(templater.stringify(self.t(key, **props)))
854 self.showpatch(ctx.node(), matchfn)
854 self.showpatch(ctx.node(), matchfn)
855
855
856 if types['footer']:
856 if types['footer']:
857 if not self.footer:
857 if not self.footer:
858 self.footer = templater.stringify(self.t(types['footer'],
858 self.footer = templater.stringify(self.t(types['footer'],
859 **props))
859 **props))
860
860
861 except KeyError, inst:
861 except KeyError, inst:
862 msg = _("%s: no key named '%s'")
862 msg = _("%s: no key named '%s'")
863 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
863 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
864 except SyntaxError, inst:
864 except SyntaxError, inst:
865 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
865 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
866
866
867 def show_changeset(ui, repo, opts, buffered=False):
867 def show_changeset(ui, repo, opts, buffered=False):
868 """show one changeset using template or regular display.
868 """show one changeset using template or regular display.
869
869
870 Display format will be the first non-empty hit of:
870 Display format will be the first non-empty hit of:
871 1. option 'template'
871 1. option 'template'
872 2. option 'style'
872 2. option 'style'
873 3. [ui] setting 'logtemplate'
873 3. [ui] setting 'logtemplate'
874 4. [ui] setting 'style'
874 4. [ui] setting 'style'
875 If all of these values are either the unset or the empty string,
875 If all of these values are either the unset or the empty string,
876 regular display via changeset_printer() is done.
876 regular display via changeset_printer() is done.
877 """
877 """
878 # options
878 # options
879 patch = False
879 patch = False
880 if opts.get('patch') or opts.get('stat'):
880 if opts.get('patch') or opts.get('stat'):
881 patch = matchall(repo)
881 patch = matchall(repo)
882
882
883 tmpl = opts.get('template')
883 tmpl = opts.get('template')
884 style = None
884 style = None
885 if tmpl:
885 if tmpl:
886 tmpl = templater.parsestring(tmpl, quoted=False)
886 tmpl = templater.parsestring(tmpl, quoted=False)
887 else:
887 else:
888 style = opts.get('style')
888 style = opts.get('style')
889
889
890 # ui settings
890 # ui settings
891 if not (tmpl or style):
891 if not (tmpl or style):
892 tmpl = ui.config('ui', 'logtemplate')
892 tmpl = ui.config('ui', 'logtemplate')
893 if tmpl:
893 if tmpl:
894 tmpl = templater.parsestring(tmpl)
894 tmpl = templater.parsestring(tmpl)
895 else:
895 else:
896 style = util.expandpath(ui.config('ui', 'style', ''))
896 style = util.expandpath(ui.config('ui', 'style', ''))
897
897
898 if not (tmpl or style):
898 if not (tmpl or style):
899 return changeset_printer(ui, repo, patch, opts, buffered)
899 return changeset_printer(ui, repo, patch, opts, buffered)
900
900
901 mapfile = None
901 mapfile = None
902 if style and not tmpl:
902 if style and not tmpl:
903 mapfile = style
903 mapfile = style
904 if not os.path.split(mapfile)[0]:
904 if not os.path.split(mapfile)[0]:
905 mapname = (templater.templatepath('map-cmdline.' + mapfile)
905 mapname = (templater.templatepath('map-cmdline.' + mapfile)
906 or templater.templatepath(mapfile))
906 or templater.templatepath(mapfile))
907 if mapname:
907 if mapname:
908 mapfile = mapname
908 mapfile = mapname
909
909
910 try:
910 try:
911 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
911 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
912 except SyntaxError, inst:
912 except SyntaxError, inst:
913 raise util.Abort(inst.args[0])
913 raise util.Abort(inst.args[0])
914 if tmpl:
914 if tmpl:
915 t.use_template(tmpl)
915 t.use_template(tmpl)
916 return t
916 return t
917
917
918 def finddate(ui, repo, date):
918 def finddate(ui, repo, date):
919 """Find the tipmost changeset that matches the given date spec"""
919 """Find the tipmost changeset that matches the given date spec"""
920
920
921 df = util.matchdate(date)
921 df = util.matchdate(date)
922 m = matchall(repo)
922 m = matchall(repo)
923 results = {}
923 results = {}
924
924
925 def prep(ctx, fns):
925 def prep(ctx, fns):
926 d = ctx.date()
926 d = ctx.date()
927 if df(d[0]):
927 if df(d[0]):
928 results[ctx.rev()] = d
928 results[ctx.rev()] = d
929
929
930 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
930 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
931 rev = ctx.rev()
931 rev = ctx.rev()
932 if rev in results:
932 if rev in results:
933 ui.status(_("Found revision %s from %s\n") %
933 ui.status(_("Found revision %s from %s\n") %
934 (rev, util.datestr(results[rev])))
934 (rev, util.datestr(results[rev])))
935 return str(rev)
935 return str(rev)
936
936
937 raise util.Abort(_("revision matching date not found"))
937 raise util.Abort(_("revision matching date not found"))
938
938
939 def walkchangerevs(repo, match, opts, prepare):
939 def walkchangerevs(repo, match, opts, prepare):
940 '''Iterate over files and the revs in which they changed.
940 '''Iterate over files and the revs in which they changed.
941
941
942 Callers most commonly need to iterate backwards over the history
942 Callers most commonly need to iterate backwards over the history
943 in which they are interested. Doing so has awful (quadratic-looking)
943 in which they are interested. Doing so has awful (quadratic-looking)
944 performance, so we use iterators in a "windowed" way.
944 performance, so we use iterators in a "windowed" way.
945
945
946 We walk a window of revisions in the desired order. Within the
946 We walk a window of revisions in the desired order. Within the
947 window, we first walk forwards to gather data, then in the desired
947 window, we first walk forwards to gather data, then in the desired
948 order (usually backwards) to display it.
948 order (usually backwards) to display it.
949
949
950 This function returns an iterator yielding contexts. Before
950 This function returns an iterator yielding contexts. Before
951 yielding each context, the iterator will first call the prepare
951 yielding each context, the iterator will first call the prepare
952 function on each context in the window in forward order.'''
952 function on each context in the window in forward order.'''
953
953
954 def increasing_windows(start, end, windowsize=8, sizelimit=512):
954 def increasing_windows(start, end, windowsize=8, sizelimit=512):
955 if start < end:
955 if start < end:
956 while start < end:
956 while start < end:
957 yield start, min(windowsize, end - start)
957 yield start, min(windowsize, end - start)
958 start += windowsize
958 start += windowsize
959 if windowsize < sizelimit:
959 if windowsize < sizelimit:
960 windowsize *= 2
960 windowsize *= 2
961 else:
961 else:
962 while start > end:
962 while start > end:
963 yield start, min(windowsize, start - end - 1)
963 yield start, min(windowsize, start - end - 1)
964 start -= windowsize
964 start -= windowsize
965 if windowsize < sizelimit:
965 if windowsize < sizelimit:
966 windowsize *= 2
966 windowsize *= 2
967
967
968 follow = opts.get('follow') or opts.get('follow_first')
968 follow = opts.get('follow') or opts.get('follow_first')
969
969
970 if not len(repo):
970 if not len(repo):
971 return []
971 return []
972
972
973 if follow:
973 if follow:
974 defrange = '%s:0' % repo['.'].rev()
974 defrange = '%s:0' % repo['.'].rev()
975 else:
975 else:
976 defrange = '-1:0'
976 defrange = '-1:0'
977 revs = revrange(repo, opts['rev'] or [defrange])
977 revs = revrange(repo, opts['rev'] or [defrange])
978 if not revs:
978 if not revs:
979 return []
979 return []
980 wanted = set()
980 wanted = set()
981 slowpath = match.anypats() or (match.files() and opts.get('removed'))
981 slowpath = match.anypats() or (match.files() and opts.get('removed'))
982 fncache = {}
982 fncache = {}
983 change = util.cachefunc(repo.changectx)
983 change = util.cachefunc(repo.changectx)
984
984
985 # First step is to fill wanted, the set of revisions that we want to yield.
985 # First step is to fill wanted, the set of revisions that we want to yield.
986 # When it does not induce extra cost, we also fill fncache for revisions in
986 # When it does not induce extra cost, we also fill fncache for revisions in
987 # wanted: a cache of filenames that were changed (ctx.files()) and that
987 # wanted: a cache of filenames that were changed (ctx.files()) and that
988 # match the file filtering conditions.
988 # match the file filtering conditions.
989
989
990 if not slowpath and not match.files():
990 if not slowpath and not match.files():
991 # No files, no patterns. Display all revs.
991 # No files, no patterns. Display all revs.
992 wanted = set(revs)
992 wanted = set(revs)
993 copies = []
993 copies = []
994
994
995 if not slowpath:
995 if not slowpath:
996 # We only have to read through the filelog to find wanted revisions
996 # We only have to read through the filelog to find wanted revisions
997
997
998 minrev, maxrev = min(revs), max(revs)
998 minrev, maxrev = min(revs), max(revs)
999 def filerevgen(filelog, last):
999 def filerevgen(filelog, last):
1000 """
1000 """
1001 Only files, no patterns. Check the history of each file.
1001 Only files, no patterns. Check the history of each file.
1002
1002
1003 Examines filelog entries within minrev, maxrev linkrev range
1003 Examines filelog entries within minrev, maxrev linkrev range
1004 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1004 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1005 tuples in backwards order
1005 tuples in backwards order
1006 """
1006 """
1007 cl_count = len(repo)
1007 cl_count = len(repo)
1008 revs = []
1008 revs = []
1009 for j in xrange(0, last + 1):
1009 for j in xrange(0, last + 1):
1010 linkrev = filelog.linkrev(j)
1010 linkrev = filelog.linkrev(j)
1011 if linkrev < minrev:
1011 if linkrev < minrev:
1012 continue
1012 continue
1013 # only yield rev for which we have the changelog, it can
1013 # only yield rev for which we have the changelog, it can
1014 # happen while doing "hg log" during a pull or commit
1014 # happen while doing "hg log" during a pull or commit
1015 if linkrev >= cl_count:
1015 if linkrev >= cl_count:
1016 break
1016 break
1017
1017
1018 parentlinkrevs = []
1018 parentlinkrevs = []
1019 for p in filelog.parentrevs(j):
1019 for p in filelog.parentrevs(j):
1020 if p != nullrev:
1020 if p != nullrev:
1021 parentlinkrevs.append(filelog.linkrev(p))
1021 parentlinkrevs.append(filelog.linkrev(p))
1022 n = filelog.node(j)
1022 n = filelog.node(j)
1023 revs.append((linkrev, parentlinkrevs,
1023 revs.append((linkrev, parentlinkrevs,
1024 follow and filelog.renamed(n)))
1024 follow and filelog.renamed(n)))
1025
1025
1026 return reversed(revs)
1026 return reversed(revs)
1027 def iterfiles():
1027 def iterfiles():
1028 for filename in match.files():
1028 for filename in match.files():
1029 yield filename, None
1029 yield filename, None
1030 for filename_node in copies:
1030 for filename_node in copies:
1031 yield filename_node
1031 yield filename_node
1032 for file_, node in iterfiles():
1032 for file_, node in iterfiles():
1033 filelog = repo.file(file_)
1033 filelog = repo.file(file_)
1034 if not len(filelog):
1034 if not len(filelog):
1035 if node is None:
1035 if node is None:
1036 # A zero count may be a directory or deleted file, so
1036 # A zero count may be a directory or deleted file, so
1037 # try to find matching entries on the slow path.
1037 # try to find matching entries on the slow path.
1038 if follow:
1038 if follow:
1039 raise util.Abort(
1039 raise util.Abort(
1040 _('cannot follow nonexistent file: "%s"') % file_)
1040 _('cannot follow nonexistent file: "%s"') % file_)
1041 slowpath = True
1041 slowpath = True
1042 break
1042 break
1043 else:
1043 else:
1044 continue
1044 continue
1045
1045
1046 if node is None:
1046 if node is None:
1047 last = len(filelog) - 1
1047 last = len(filelog) - 1
1048 else:
1048 else:
1049 last = filelog.rev(node)
1049 last = filelog.rev(node)
1050
1050
1051
1051
1052 # keep track of all ancestors of the file
1052 # keep track of all ancestors of the file
1053 ancestors = set([filelog.linkrev(last)])
1053 ancestors = set([filelog.linkrev(last)])
1054
1054
1055 # iterate from latest to oldest revision
1055 # iterate from latest to oldest revision
1056 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1056 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1057 if not follow:
1057 if not follow:
1058 if rev > maxrev:
1058 if rev > maxrev:
1059 continue
1059 continue
1060 else:
1060 else:
1061 # Note that last might not be the first interesting
1061 # Note that last might not be the first interesting
1062 # rev to us:
1062 # rev to us:
1063 # if the file has been changed after maxrev, we'll
1063 # if the file has been changed after maxrev, we'll
1064 # have linkrev(last) > maxrev, and we still need
1064 # have linkrev(last) > maxrev, and we still need
1065 # to explore the file graph
1065 # to explore the file graph
1066 if rev not in ancestors:
1066 if rev not in ancestors:
1067 continue
1067 continue
1068 # XXX insert 1327 fix here
1068 # XXX insert 1327 fix here
1069 if flparentlinkrevs:
1069 if flparentlinkrevs:
1070 ancestors.update(flparentlinkrevs)
1070 ancestors.update(flparentlinkrevs)
1071
1071
1072 fncache.setdefault(rev, []).append(file_)
1072 fncache.setdefault(rev, []).append(file_)
1073 wanted.add(rev)
1073 wanted.add(rev)
1074 if copied:
1074 if copied:
1075 copies.append(copied)
1075 copies.append(copied)
1076 if slowpath:
1076 if slowpath:
1077 # We have to read the changelog to match filenames against
1077 # We have to read the changelog to match filenames against
1078 # changed files
1078 # changed files
1079
1079
1080 if follow:
1080 if follow:
1081 raise util.Abort(_('can only follow copies/renames for explicit '
1081 raise util.Abort(_('can only follow copies/renames for explicit '
1082 'filenames'))
1082 'filenames'))
1083
1083
1084 # The slow path checks files modified in every changeset.
1084 # The slow path checks files modified in every changeset.
1085 for i in sorted(revs):
1085 for i in sorted(revs):
1086 ctx = change(i)
1086 ctx = change(i)
1087 matches = filter(match, ctx.files())
1087 matches = filter(match, ctx.files())
1088 if matches:
1088 if matches:
1089 fncache[i] = matches
1089 fncache[i] = matches
1090 wanted.add(i)
1090 wanted.add(i)
1091
1091
1092 class followfilter(object):
1092 class followfilter(object):
1093 def __init__(self, onlyfirst=False):
1093 def __init__(self, onlyfirst=False):
1094 self.startrev = nullrev
1094 self.startrev = nullrev
1095 self.roots = set()
1095 self.roots = set()
1096 self.onlyfirst = onlyfirst
1096 self.onlyfirst = onlyfirst
1097
1097
1098 def match(self, rev):
1098 def match(self, rev):
1099 def realparents(rev):
1099 def realparents(rev):
1100 if self.onlyfirst:
1100 if self.onlyfirst:
1101 return repo.changelog.parentrevs(rev)[0:1]
1101 return repo.changelog.parentrevs(rev)[0:1]
1102 else:
1102 else:
1103 return filter(lambda x: x != nullrev,
1103 return filter(lambda x: x != nullrev,
1104 repo.changelog.parentrevs(rev))
1104 repo.changelog.parentrevs(rev))
1105
1105
1106 if self.startrev == nullrev:
1106 if self.startrev == nullrev:
1107 self.startrev = rev
1107 self.startrev = rev
1108 return True
1108 return True
1109
1109
1110 if rev > self.startrev:
1110 if rev > self.startrev:
1111 # forward: all descendants
1111 # forward: all descendants
1112 if not self.roots:
1112 if not self.roots:
1113 self.roots.add(self.startrev)
1113 self.roots.add(self.startrev)
1114 for parent in realparents(rev):
1114 for parent in realparents(rev):
1115 if parent in self.roots:
1115 if parent in self.roots:
1116 self.roots.add(rev)
1116 self.roots.add(rev)
1117 return True
1117 return True
1118 else:
1118 else:
1119 # backwards: all parents
1119 # backwards: all parents
1120 if not self.roots:
1120 if not self.roots:
1121 self.roots.update(realparents(self.startrev))
1121 self.roots.update(realparents(self.startrev))
1122 if rev in self.roots:
1122 if rev in self.roots:
1123 self.roots.remove(rev)
1123 self.roots.remove(rev)
1124 self.roots.update(realparents(rev))
1124 self.roots.update(realparents(rev))
1125 return True
1125 return True
1126
1126
1127 return False
1127 return False
1128
1128
1129 # it might be worthwhile to do this in the iterator if the rev range
1129 # it might be worthwhile to do this in the iterator if the rev range
1130 # is descending and the prune args are all within that range
1130 # is descending and the prune args are all within that range
1131 for rev in opts.get('prune', ()):
1131 for rev in opts.get('prune', ()):
1132 rev = repo.changelog.rev(repo.lookup(rev))
1132 rev = repo.changelog.rev(repo.lookup(rev))
1133 ff = followfilter()
1133 ff = followfilter()
1134 stop = min(revs[0], revs[-1])
1134 stop = min(revs[0], revs[-1])
1135 for x in xrange(rev, stop - 1, -1):
1135 for x in xrange(rev, stop - 1, -1):
1136 if ff.match(x):
1136 if ff.match(x):
1137 wanted.discard(x)
1137 wanted.discard(x)
1138
1138
1139 # Now that wanted is correctly initialized, we can iterate over the
1139 # Now that wanted is correctly initialized, we can iterate over the
1140 # revision range, yielding only revisions in wanted.
1140 # revision range, yielding only revisions in wanted.
1141 def iterate():
1141 def iterate():
1142 if follow and not match.files():
1142 if follow and not match.files():
1143 ff = followfilter(onlyfirst=opts.get('follow_first'))
1143 ff = followfilter(onlyfirst=opts.get('follow_first'))
1144 def want(rev):
1144 def want(rev):
1145 return ff.match(rev) and rev in wanted
1145 return ff.match(rev) and rev in wanted
1146 else:
1146 else:
1147 def want(rev):
1147 def want(rev):
1148 return rev in wanted
1148 return rev in wanted
1149
1149
1150 for i, window in increasing_windows(0, len(revs)):
1150 for i, window in increasing_windows(0, len(revs)):
1151 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1151 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1152 for rev in sorted(nrevs):
1152 for rev in sorted(nrevs):
1153 fns = fncache.get(rev)
1153 fns = fncache.get(rev)
1154 ctx = change(rev)
1154 ctx = change(rev)
1155 if not fns:
1155 if not fns:
1156 def fns_generator():
1156 def fns_generator():
1157 for f in ctx.files():
1157 for f in ctx.files():
1158 if match(f):
1158 if match(f):
1159 yield f
1159 yield f
1160 fns = fns_generator()
1160 fns = fns_generator()
1161 prepare(ctx, fns)
1161 prepare(ctx, fns)
1162 for rev in nrevs:
1162 for rev in nrevs:
1163 yield change(rev)
1163 yield change(rev)
1164 return iterate()
1164 return iterate()
1165
1165
1166 def add(ui, repo, match, dryrun, listsubrepos, prefix):
1166 def add(ui, repo, match, dryrun, listsubrepos, prefix):
1167 join = lambda f: os.path.join(prefix, f)
1167 join = lambda f: os.path.join(prefix, f)
1168 bad = []
1168 bad = []
1169 oldbad = match.bad
1169 oldbad = match.bad
1170 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1170 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1171 names = []
1171 names = []
1172 wctx = repo[None]
1172 wctx = repo[None]
1173 cca = None
1173 cca = None
1174 abort, warn = scmutil.checkportabilityalert(ui)
1174 abort, warn = scmutil.checkportabilityalert(ui)
1175 if abort or warn:
1175 if abort or warn:
1176 cca = scmutil.casecollisionauditor(ui, abort, wctx)
1176 cca = scmutil.casecollisionauditor(ui, abort, wctx)
1177 for f in repo.walk(match):
1177 for f in repo.walk(match):
1178 exact = match.exact(f)
1178 exact = match.exact(f)
1179 if exact or f not in repo.dirstate:
1179 if exact or f not in repo.dirstate:
1180 if cca:
1180 if cca:
1181 cca(f)
1181 cca(f)
1182 names.append(f)
1182 names.append(f)
1183 if ui.verbose or not exact:
1183 if ui.verbose or not exact:
1184 ui.status(_('adding %s\n') % match.rel(join(f)))
1184 ui.status(_('adding %s\n') % match.rel(join(f)))
1185
1185
1186 if listsubrepos:
1186 if listsubrepos:
1187 for subpath in wctx.substate:
1187 for subpath in wctx.substate:
1188 sub = wctx.sub(subpath)
1188 sub = wctx.sub(subpath)
1189 try:
1189 try:
1190 submatch = matchmod.narrowmatcher(subpath, match)
1190 submatch = matchmod.narrowmatcher(subpath, match)
1191 bad.extend(sub.add(ui, submatch, dryrun, prefix))
1191 bad.extend(sub.add(ui, submatch, dryrun, prefix))
1192 except error.LookupError:
1192 except error.LookupError:
1193 ui.status(_("skipping missing subrepository: %s\n")
1193 ui.status(_("skipping missing subrepository: %s\n")
1194 % join(subpath))
1194 % join(subpath))
1195
1195
1196 if not dryrun:
1196 if not dryrun:
1197 rejected = wctx.add(names, prefix)
1197 rejected = wctx.add(names, prefix)
1198 bad.extend(f for f in rejected if f in match.files())
1198 bad.extend(f for f in rejected if f in match.files())
1199 return bad
1199 return bad
1200
1200
1201 def commit(ui, repo, commitfunc, pats, opts):
1201 def commit(ui, repo, commitfunc, pats, opts):
1202 '''commit the specified files or all outstanding changes'''
1202 '''commit the specified files or all outstanding changes'''
1203 date = opts.get('date')
1203 date = opts.get('date')
1204 if date:
1204 if date:
1205 opts['date'] = util.parsedate(date)
1205 opts['date'] = util.parsedate(date)
1206 message = logmessage(opts)
1206 message = logmessage(opts)
1207
1207
1208 # extract addremove carefully -- this function can be called from a command
1208 # extract addremove carefully -- this function can be called from a command
1209 # that doesn't support addremove
1209 # that doesn't support addremove
1210 if opts.get('addremove'):
1210 if opts.get('addremove'):
1211 addremove(repo, pats, opts)
1211 addremove(repo, pats, opts)
1212
1212
1213 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1213 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1214
1214
1215 def commiteditor(repo, ctx, subs):
1215 def commiteditor(repo, ctx, subs):
1216 if ctx.description():
1216 if ctx.description():
1217 return ctx.description()
1217 return ctx.description()
1218 return commitforceeditor(repo, ctx, subs)
1218 return commitforceeditor(repo, ctx, subs)
1219
1219
1220 def commitforceeditor(repo, ctx, subs):
1220 def commitforceeditor(repo, ctx, subs):
1221 edittext = []
1221 edittext = []
1222 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1222 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1223 if ctx.description():
1223 if ctx.description():
1224 edittext.append(ctx.description())
1224 edittext.append(ctx.description())
1225 edittext.append("")
1225 edittext.append("")
1226 edittext.append("") # Empty line between message and comments.
1226 edittext.append("") # Empty line between message and comments.
1227 edittext.append(_("HG: Enter commit message."
1227 edittext.append(_("HG: Enter commit message."
1228 " Lines beginning with 'HG:' are removed."))
1228 " Lines beginning with 'HG:' are removed."))
1229 edittext.append(_("HG: Leave message empty to abort commit."))
1229 edittext.append(_("HG: Leave message empty to abort commit."))
1230 edittext.append("HG: --")
1230 edittext.append("HG: --")
1231 edittext.append(_("HG: user: %s") % ctx.user())
1231 edittext.append(_("HG: user: %s") % ctx.user())
1232 if ctx.p2():
1232 if ctx.p2():
1233 edittext.append(_("HG: branch merge"))
1233 edittext.append(_("HG: branch merge"))
1234 if ctx.branch():
1234 if ctx.branch():
1235 edittext.append(_("HG: branch '%s'") % ctx.branch())
1235 edittext.append(_("HG: branch '%s'") % ctx.branch())
1236 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1236 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1237 edittext.extend([_("HG: added %s") % f for f in added])
1237 edittext.extend([_("HG: added %s") % f for f in added])
1238 edittext.extend([_("HG: changed %s") % f for f in modified])
1238 edittext.extend([_("HG: changed %s") % f for f in modified])
1239 edittext.extend([_("HG: removed %s") % f for f in removed])
1239 edittext.extend([_("HG: removed %s") % f for f in removed])
1240 if not added and not modified and not removed:
1240 if not added and not modified and not removed:
1241 edittext.append(_("HG: no files changed"))
1241 edittext.append(_("HG: no files changed"))
1242 edittext.append("")
1242 edittext.append("")
1243 # run editor in the repository root
1243 # run editor in the repository root
1244 olddir = os.getcwd()
1244 olddir = os.getcwd()
1245 os.chdir(repo.root)
1245 os.chdir(repo.root)
1246 text = repo.ui.edit("\n".join(edittext), ctx.user())
1246 text = repo.ui.edit("\n".join(edittext), ctx.user())
1247 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
1247 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
1248 os.chdir(olddir)
1248 os.chdir(olddir)
1249
1249
1250 if not text.strip():
1250 if not text.strip():
1251 raise util.Abort(_("empty commit message"))
1251 raise util.Abort(_("empty commit message"))
1252
1252
1253 return text
1253 return text
1254
1255 def command(table):
1256 '''returns a function object bound to table which can be used as
1257 a decorator for populating table as a command table'''
1258
1259 def cmd(name, options, synopsis=None):
1260 def decorator(func):
1261 if synopsis:
1262 table[name] = func, options, synopsis
1263 else:
1264 table[name] = func, options
1265 return func
1266 return decorator
1267
1268 return cmd
This diff has been collapsed as it changes many lines, (1202 lines changed) Show them Hide them
@@ -1,5020 +1,4888
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, bin, nullid, nullrev, short
8 from node import hex, bin, 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, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, 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, templatefilters
16 import minirst, revset, templatefilters
17 import dagparser, context, simplemerge
17 import dagparser, context, simplemerge
18 import random, setdiscovery, treediscovery, dagutil
18 import random, setdiscovery, treediscovery, dagutil
19
19
20 table = {}
21
22 command = cmdutil.command(table)
23
24 # common command options
25
26 globalopts = [
27 ('R', 'repository', '',
28 _('repository root directory or name of overlay bundle file'),
29 _('REPO')),
30 ('', 'cwd', '',
31 _('change working directory'), _('DIR')),
32 ('y', 'noninteractive', None,
33 _('do not prompt, assume \'yes\' for any required answers')),
34 ('q', 'quiet', None, _('suppress output')),
35 ('v', 'verbose', None, _('enable additional output')),
36 ('', 'config', [],
37 _('set/override config option (use \'section.name=value\')'),
38 _('CONFIG')),
39 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debugger', None, _('start debugger')),
41 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 _('ENCODE')),
43 ('', 'encodingmode', encoding.encodingmode,
44 _('set the charset encoding mode'), _('MODE')),
45 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'time', None, _('time how long the command takes')),
47 ('', 'profile', None, _('print command execution profile')),
48 ('', 'version', None, _('output version information and exit')),
49 ('h', 'help', None, _('display help and exit')),
50 ]
51
52 dryrunopts = [('n', 'dry-run', None,
53 _('do not perform actions, just print output'))]
54
55 remoteopts = [
56 ('e', 'ssh', '',
57 _('specify ssh command to use'), _('CMD')),
58 ('', 'remotecmd', '',
59 _('specify hg command to run on the remote side'), _('CMD')),
60 ('', 'insecure', None,
61 _('do not verify server certificate (ignoring web.cacerts config)')),
62 ]
63
64 walkopts = [
65 ('I', 'include', [],
66 _('include names matching the given patterns'), _('PATTERN')),
67 ('X', 'exclude', [],
68 _('exclude names matching the given patterns'), _('PATTERN')),
69 ]
70
71 commitopts = [
72 ('m', 'message', '',
73 _('use text as commit message'), _('TEXT')),
74 ('l', 'logfile', '',
75 _('read commit message from file'), _('FILE')),
76 ]
77
78 commitopts2 = [
79 ('d', 'date', '',
80 _('record the specified date as commit date'), _('DATE')),
81 ('u', 'user', '',
82 _('record the specified user as committer'), _('USER')),
83 ]
84
85 templateopts = [
86 ('', 'style', '',
87 _('display using template map file'), _('STYLE')),
88 ('', 'template', '',
89 _('display with template'), _('TEMPLATE')),
90 ]
91
92 logopts = [
93 ('p', 'patch', None, _('show patch')),
94 ('g', 'git', None, _('use git extended diff format')),
95 ('l', 'limit', '',
96 _('limit number of changes displayed'), _('NUM')),
97 ('M', 'no-merges', None, _('do not show merges')),
98 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ] + templateopts
100
101 diffopts = [
102 ('a', 'text', None, _('treat all files as text')),
103 ('g', 'git', None, _('use git extended diff format')),
104 ('', 'nodates', None, _('omit dates from diff headers'))
105 ]
106
107 diffopts2 = [
108 ('p', 'show-function', None, _('show which function each change is in')),
109 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
116 ('U', 'unified', '',
117 _('number of lines of context to show'), _('NUM')),
118 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ]
120
121 similarityopts = [
122 ('s', 'similarity', '',
123 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
124 ]
125
126 subrepoopts = [
127 ('S', 'subrepos', None,
128 _('recurse into subrepositories'))
129 ]
130
20 # Commands start here, listed alphabetically
131 # Commands start here, listed alphabetically
21
132
133 @command('^add',
134 walkopts + subrepoopts + dryrunopts,
135 _('[OPTION]... [FILE]...'))
22 def add(ui, repo, *pats, **opts):
136 def add(ui, repo, *pats, **opts):
23 """add the specified files on the next commit
137 """add the specified files on the next commit
24
138
25 Schedule files to be version controlled and added to the
139 Schedule files to be version controlled and added to the
26 repository.
140 repository.
27
141
28 The files will be added to the repository at the next commit. To
142 The files will be added to the repository at the next commit. To
29 undo an add before that, see :hg:`forget`.
143 undo an add before that, see :hg:`forget`.
30
144
31 If no names are given, add all files to the repository.
145 If no names are given, add all files to the repository.
32
146
33 .. container:: verbose
147 .. container:: verbose
34
148
35 An example showing how new (unknown) files are added
149 An example showing how new (unknown) files are added
36 automatically by :hg:`add`::
150 automatically by :hg:`add`::
37
151
38 $ ls
152 $ ls
39 foo.c
153 foo.c
40 $ hg status
154 $ hg status
41 ? foo.c
155 ? foo.c
42 $ hg add
156 $ hg add
43 adding foo.c
157 adding foo.c
44 $ hg status
158 $ hg status
45 A foo.c
159 A foo.c
46
160
47 Returns 0 if all files are successfully added.
161 Returns 0 if all files are successfully added.
48 """
162 """
49
163
50 m = cmdutil.match(repo, pats, opts)
164 m = cmdutil.match(repo, pats, opts)
51 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
165 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
52 opts.get('subrepos'), prefix="")
166 opts.get('subrepos'), prefix="")
53 return rejected and 1 or 0
167 return rejected and 1 or 0
54
168
169 @command('addremove',
170 similarityopts + walkopts + dryrunopts,
171 _('[OPTION]... [FILE]...'))
55 def addremove(ui, repo, *pats, **opts):
172 def addremove(ui, repo, *pats, **opts):
56 """add all new files, delete all missing files
173 """add all new files, delete all missing files
57
174
58 Add all new files and remove all missing files from the
175 Add all new files and remove all missing files from the
59 repository.
176 repository.
60
177
61 New files are ignored if they match any of the patterns in
178 New files are ignored if they match any of the patterns in
62 ``.hgignore``. As with add, these changes take effect at the next
179 ``.hgignore``. As with add, these changes take effect at the next
63 commit.
180 commit.
64
181
65 Use the -s/--similarity option to detect renamed files. With a
182 Use the -s/--similarity option to detect renamed files. With a
66 parameter greater than 0, this compares every removed file with
183 parameter greater than 0, this compares every removed file with
67 every added file and records those similar enough as renames. This
184 every added file and records those similar enough as renames. This
68 option takes a percentage between 0 (disabled) and 100 (files must
185 option takes a percentage between 0 (disabled) and 100 (files must
69 be identical) as its parameter. Detecting renamed files this way
186 be identical) as its parameter. Detecting renamed files this way
70 can be expensive. After using this option, :hg:`status -C` can be
187 can be expensive. After using this option, :hg:`status -C` can be
71 used to check which files were identified as moved or renamed.
188 used to check which files were identified as moved or renamed.
72
189
73 Returns 0 if all files are successfully added.
190 Returns 0 if all files are successfully added.
74 """
191 """
75 try:
192 try:
76 sim = float(opts.get('similarity') or 100)
193 sim = float(opts.get('similarity') or 100)
77 except ValueError:
194 except ValueError:
78 raise util.Abort(_('similarity must be a number'))
195 raise util.Abort(_('similarity must be a number'))
79 if sim < 0 or sim > 100:
196 if sim < 0 or sim > 100:
80 raise util.Abort(_('similarity must be between 0 and 100'))
197 raise util.Abort(_('similarity must be between 0 and 100'))
81 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
198 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
82
199
200 @command('^annotate|blame',
201 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
202 ('', 'follow', None,
203 _('follow copies/renames and list the filename (DEPRECATED)')),
204 ('', 'no-follow', None, _("don't follow copies and renames")),
205 ('a', 'text', None, _('treat all files as text')),
206 ('u', 'user', None, _('list the author (long with -v)')),
207 ('f', 'file', None, _('list the filename')),
208 ('d', 'date', None, _('list the date (short with -q)')),
209 ('n', 'number', None, _('list the revision number (default)')),
210 ('c', 'changeset', None, _('list the changeset')),
211 ('l', 'line-number', None, _('show line number at the first appearance'))
212 ] + walkopts,
213 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
83 def annotate(ui, repo, *pats, **opts):
214 def annotate(ui, repo, *pats, **opts):
84 """show changeset information by line for each file
215 """show changeset information by line for each file
85
216
86 List changes in files, showing the revision id responsible for
217 List changes in files, showing the revision id responsible for
87 each line
218 each line
88
219
89 This command is useful for discovering when a change was made and
220 This command is useful for discovering when a change was made and
90 by whom.
221 by whom.
91
222
92 Without the -a/--text option, annotate will avoid processing files
223 Without the -a/--text option, annotate will avoid processing files
93 it detects as binary. With -a, annotate will annotate the file
224 it detects as binary. With -a, annotate will annotate the file
94 anyway, although the results will probably be neither useful
225 anyway, although the results will probably be neither useful
95 nor desirable.
226 nor desirable.
96
227
97 Returns 0 on success.
228 Returns 0 on success.
98 """
229 """
99 if opts.get('follow'):
230 if opts.get('follow'):
100 # --follow is deprecated and now just an alias for -f/--file
231 # --follow is deprecated and now just an alias for -f/--file
101 # to mimic the behavior of Mercurial before version 1.5
232 # to mimic the behavior of Mercurial before version 1.5
102 opts['file'] = True
233 opts['file'] = True
103
234
104 datefunc = ui.quiet and util.shortdate or util.datestr
235 datefunc = ui.quiet and util.shortdate or util.datestr
105 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
236 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
106
237
107 if not pats:
238 if not pats:
108 raise util.Abort(_('at least one filename or pattern is required'))
239 raise util.Abort(_('at least one filename or pattern is required'))
109
240
110 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
241 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
111 ('number', lambda x: str(x[0].rev())),
242 ('number', lambda x: str(x[0].rev())),
112 ('changeset', lambda x: short(x[0].node())),
243 ('changeset', lambda x: short(x[0].node())),
113 ('date', getdate),
244 ('date', getdate),
114 ('file', lambda x: x[0].path()),
245 ('file', lambda x: x[0].path()),
115 ]
246 ]
116
247
117 if (not opts.get('user') and not opts.get('changeset')
248 if (not opts.get('user') and not opts.get('changeset')
118 and not opts.get('date') and not opts.get('file')):
249 and not opts.get('date') and not opts.get('file')):
119 opts['number'] = True
250 opts['number'] = True
120
251
121 linenumber = opts.get('line_number') is not None
252 linenumber = opts.get('line_number') is not None
122 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
253 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
123 raise util.Abort(_('at least one of -n/-c is required for -l'))
254 raise util.Abort(_('at least one of -n/-c is required for -l'))
124
255
125 funcmap = [func for op, func in opmap if opts.get(op)]
256 funcmap = [func for op, func in opmap if opts.get(op)]
126 if linenumber:
257 if linenumber:
127 lastfunc = funcmap[-1]
258 lastfunc = funcmap[-1]
128 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
259 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
129
260
130 def bad(x, y):
261 def bad(x, y):
131 raise util.Abort("%s: %s" % (x, y))
262 raise util.Abort("%s: %s" % (x, y))
132
263
133 ctx = cmdutil.revsingle(repo, opts.get('rev'))
264 ctx = cmdutil.revsingle(repo, opts.get('rev'))
134 m = cmdutil.match(repo, pats, opts)
265 m = cmdutil.match(repo, pats, opts)
135 m.bad = bad
266 m.bad = bad
136 follow = not opts.get('no_follow')
267 follow = not opts.get('no_follow')
137 for abs in ctx.walk(m):
268 for abs in ctx.walk(m):
138 fctx = ctx[abs]
269 fctx = ctx[abs]
139 if not opts.get('text') and util.binary(fctx.data()):
270 if not opts.get('text') and util.binary(fctx.data()):
140 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
271 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
141 continue
272 continue
142
273
143 lines = fctx.annotate(follow=follow, linenumber=linenumber)
274 lines = fctx.annotate(follow=follow, linenumber=linenumber)
144 pieces = []
275 pieces = []
145
276
146 for f in funcmap:
277 for f in funcmap:
147 l = [f(n) for n, dummy in lines]
278 l = [f(n) for n, dummy in lines]
148 if l:
279 if l:
149 sized = [(x, encoding.colwidth(x)) for x in l]
280 sized = [(x, encoding.colwidth(x)) for x in l]
150 ml = max([w for x, w in sized])
281 ml = max([w for x, w in sized])
151 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
282 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
152
283
153 if pieces:
284 if pieces:
154 for p, l in zip(zip(*pieces), lines):
285 for p, l in zip(zip(*pieces), lines):
155 ui.write("%s: %s" % (" ".join(p), l[1]))
286 ui.write("%s: %s" % (" ".join(p), l[1]))
156
287
288 @command('archive',
289 [('', 'no-decode', None, _('do not pass files through decoders')),
290 ('p', 'prefix', '', _('directory prefix for files in archive'),
291 _('PREFIX')),
292 ('r', 'rev', '', _('revision to distribute'), _('REV')),
293 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
294 ] + subrepoopts + walkopts,
295 _('[OPTION]... DEST'))
157 def archive(ui, repo, dest, **opts):
296 def archive(ui, repo, dest, **opts):
158 '''create an unversioned archive of a repository revision
297 '''create an unversioned archive of a repository revision
159
298
160 By default, the revision used is the parent of the working
299 By default, the revision used is the parent of the working
161 directory; use -r/--rev to specify a different revision.
300 directory; use -r/--rev to specify a different revision.
162
301
163 The archive type is automatically detected based on file
302 The archive type is automatically detected based on file
164 extension (or override using -t/--type).
303 extension (or override using -t/--type).
165
304
166 Valid types are:
305 Valid types are:
167
306
168 :``files``: a directory full of files (default)
307 :``files``: a directory full of files (default)
169 :``tar``: tar archive, uncompressed
308 :``tar``: tar archive, uncompressed
170 :``tbz2``: tar archive, compressed using bzip2
309 :``tbz2``: tar archive, compressed using bzip2
171 :``tgz``: tar archive, compressed using gzip
310 :``tgz``: tar archive, compressed using gzip
172 :``uzip``: zip archive, uncompressed
311 :``uzip``: zip archive, uncompressed
173 :``zip``: zip archive, compressed using deflate
312 :``zip``: zip archive, compressed using deflate
174
313
175 The exact name of the destination archive or directory is given
314 The exact name of the destination archive or directory is given
176 using a format string; see :hg:`help export` for details.
315 using a format string; see :hg:`help export` for details.
177
316
178 Each member added to an archive file has a directory prefix
317 Each member added to an archive file has a directory prefix
179 prepended. Use -p/--prefix to specify a format string for the
318 prepended. Use -p/--prefix to specify a format string for the
180 prefix. The default is the basename of the archive, with suffixes
319 prefix. The default is the basename of the archive, with suffixes
181 removed.
320 removed.
182
321
183 Returns 0 on success.
322 Returns 0 on success.
184 '''
323 '''
185
324
186 ctx = cmdutil.revsingle(repo, opts.get('rev'))
325 ctx = cmdutil.revsingle(repo, opts.get('rev'))
187 if not ctx:
326 if not ctx:
188 raise util.Abort(_('no working directory: please specify a revision'))
327 raise util.Abort(_('no working directory: please specify a revision'))
189 node = ctx.node()
328 node = ctx.node()
190 dest = cmdutil.makefilename(repo, dest, node)
329 dest = cmdutil.makefilename(repo, dest, node)
191 if os.path.realpath(dest) == repo.root:
330 if os.path.realpath(dest) == repo.root:
192 raise util.Abort(_('repository root cannot be destination'))
331 raise util.Abort(_('repository root cannot be destination'))
193
332
194 kind = opts.get('type') or archival.guesskind(dest) or 'files'
333 kind = opts.get('type') or archival.guesskind(dest) or 'files'
195 prefix = opts.get('prefix')
334 prefix = opts.get('prefix')
196
335
197 if dest == '-':
336 if dest == '-':
198 if kind == 'files':
337 if kind == 'files':
199 raise util.Abort(_('cannot archive plain files to stdout'))
338 raise util.Abort(_('cannot archive plain files to stdout'))
200 dest = sys.stdout
339 dest = sys.stdout
201 if not prefix:
340 if not prefix:
202 prefix = os.path.basename(repo.root) + '-%h'
341 prefix = os.path.basename(repo.root) + '-%h'
203
342
204 prefix = cmdutil.makefilename(repo, prefix, node)
343 prefix = cmdutil.makefilename(repo, prefix, node)
205 matchfn = cmdutil.match(repo, [], opts)
344 matchfn = cmdutil.match(repo, [], opts)
206 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
345 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
207 matchfn, prefix, subrepos=opts.get('subrepos'))
346 matchfn, prefix, subrepos=opts.get('subrepos'))
208
347
348 @command('backout',
349 [('', 'merge', None, _('merge with old dirstate parent after backout')),
350 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
351 ('t', 'tool', '', _('specify merge tool')),
352 ('r', 'rev', '', _('revision to backout'), _('REV')),
353 ] + walkopts + commitopts + commitopts2,
354 _('[OPTION]... [-r] REV'))
209 def backout(ui, repo, node=None, rev=None, **opts):
355 def backout(ui, repo, node=None, rev=None, **opts):
210 '''reverse effect of earlier changeset
356 '''reverse effect of earlier changeset
211
357
212 Prepare a new changeset with the effect of REV undone in the
358 Prepare a new changeset with the effect of REV undone in the
213 current working directory.
359 current working directory.
214
360
215 If REV is the parent of the working directory, then this new changeset
361 If REV is the parent of the working directory, then this new changeset
216 is committed automatically. Otherwise, hg needs to merge the
362 is committed automatically. Otherwise, hg needs to merge the
217 changes and the merged result is left uncommitted.
363 changes and the merged result is left uncommitted.
218
364
219 By default, the pending changeset will have one parent,
365 By default, the pending changeset will have one parent,
220 maintaining a linear history. With --merge, the pending changeset
366 maintaining a linear history. With --merge, the pending changeset
221 will instead have two parents: the old parent of the working
367 will instead have two parents: the old parent of the working
222 directory and a new child of REV that simply undoes REV.
368 directory and a new child of REV that simply undoes REV.
223
369
224 Before version 1.7, the behavior without --merge was equivalent to
370 Before version 1.7, the behavior without --merge was equivalent to
225 specifying --merge followed by :hg:`update --clean .` to cancel
371 specifying --merge followed by :hg:`update --clean .` to cancel
226 the merge and leave the child of REV as a head to be merged
372 the merge and leave the child of REV as a head to be merged
227 separately.
373 separately.
228
374
229 See :hg:`help dates` for a list of formats valid for -d/--date.
375 See :hg:`help dates` for a list of formats valid for -d/--date.
230
376
231 Returns 0 on success.
377 Returns 0 on success.
232 '''
378 '''
233 if rev and node:
379 if rev and node:
234 raise util.Abort(_("please specify just one revision"))
380 raise util.Abort(_("please specify just one revision"))
235
381
236 if not rev:
382 if not rev:
237 rev = node
383 rev = node
238
384
239 if not rev:
385 if not rev:
240 raise util.Abort(_("please specify a revision to backout"))
386 raise util.Abort(_("please specify a revision to backout"))
241
387
242 date = opts.get('date')
388 date = opts.get('date')
243 if date:
389 if date:
244 opts['date'] = util.parsedate(date)
390 opts['date'] = util.parsedate(date)
245
391
246 cmdutil.bailifchanged(repo)
392 cmdutil.bailifchanged(repo)
247 node = cmdutil.revsingle(repo, rev).node()
393 node = cmdutil.revsingle(repo, rev).node()
248
394
249 op1, op2 = repo.dirstate.parents()
395 op1, op2 = repo.dirstate.parents()
250 a = repo.changelog.ancestor(op1, node)
396 a = repo.changelog.ancestor(op1, node)
251 if a != node:
397 if a != node:
252 raise util.Abort(_('cannot backout change on a different branch'))
398 raise util.Abort(_('cannot backout change on a different branch'))
253
399
254 p1, p2 = repo.changelog.parents(node)
400 p1, p2 = repo.changelog.parents(node)
255 if p1 == nullid:
401 if p1 == nullid:
256 raise util.Abort(_('cannot backout a change with no parents'))
402 raise util.Abort(_('cannot backout a change with no parents'))
257 if p2 != nullid:
403 if p2 != nullid:
258 if not opts.get('parent'):
404 if not opts.get('parent'):
259 raise util.Abort(_('cannot backout a merge changeset without '
405 raise util.Abort(_('cannot backout a merge changeset without '
260 '--parent'))
406 '--parent'))
261 p = repo.lookup(opts['parent'])
407 p = repo.lookup(opts['parent'])
262 if p not in (p1, p2):
408 if p not in (p1, p2):
263 raise util.Abort(_('%s is not a parent of %s') %
409 raise util.Abort(_('%s is not a parent of %s') %
264 (short(p), short(node)))
410 (short(p), short(node)))
265 parent = p
411 parent = p
266 else:
412 else:
267 if opts.get('parent'):
413 if opts.get('parent'):
268 raise util.Abort(_('cannot use --parent on non-merge changeset'))
414 raise util.Abort(_('cannot use --parent on non-merge changeset'))
269 parent = p1
415 parent = p1
270
416
271 # the backout should appear on the same branch
417 # the backout should appear on the same branch
272 branch = repo.dirstate.branch()
418 branch = repo.dirstate.branch()
273 hg.clean(repo, node, show_stats=False)
419 hg.clean(repo, node, show_stats=False)
274 repo.dirstate.setbranch(branch)
420 repo.dirstate.setbranch(branch)
275 revert_opts = opts.copy()
421 revert_opts = opts.copy()
276 revert_opts['date'] = None
422 revert_opts['date'] = None
277 revert_opts['all'] = True
423 revert_opts['all'] = True
278 revert_opts['rev'] = hex(parent)
424 revert_opts['rev'] = hex(parent)
279 revert_opts['no_backup'] = None
425 revert_opts['no_backup'] = None
280 revert(ui, repo, **revert_opts)
426 revert(ui, repo, **revert_opts)
281 if not opts.get('merge') and op1 != node:
427 if not opts.get('merge') and op1 != node:
282 try:
428 try:
283 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
429 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
284 return hg.update(repo, op1)
430 return hg.update(repo, op1)
285 finally:
431 finally:
286 ui.setconfig('ui', 'forcemerge', '')
432 ui.setconfig('ui', 'forcemerge', '')
287
433
288 commit_opts = opts.copy()
434 commit_opts = opts.copy()
289 commit_opts['addremove'] = False
435 commit_opts['addremove'] = False
290 if not commit_opts['message'] and not commit_opts['logfile']:
436 if not commit_opts['message'] and not commit_opts['logfile']:
291 # we don't translate commit messages
437 # we don't translate commit messages
292 commit_opts['message'] = "Backed out changeset %s" % short(node)
438 commit_opts['message'] = "Backed out changeset %s" % short(node)
293 commit_opts['force_editor'] = True
439 commit_opts['force_editor'] = True
294 commit(ui, repo, **commit_opts)
440 commit(ui, repo, **commit_opts)
295 def nice(node):
441 def nice(node):
296 return '%d:%s' % (repo.changelog.rev(node), short(node))
442 return '%d:%s' % (repo.changelog.rev(node), short(node))
297 ui.status(_('changeset %s backs out changeset %s\n') %
443 ui.status(_('changeset %s backs out changeset %s\n') %
298 (nice(repo.changelog.tip()), nice(node)))
444 (nice(repo.changelog.tip()), nice(node)))
299 if opts.get('merge') and op1 != node:
445 if opts.get('merge') and op1 != node:
300 hg.clean(repo, op1, show_stats=False)
446 hg.clean(repo, op1, show_stats=False)
301 ui.status(_('merging with changeset %s\n')
447 ui.status(_('merging with changeset %s\n')
302 % nice(repo.changelog.tip()))
448 % nice(repo.changelog.tip()))
303 try:
449 try:
304 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
450 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
305 return hg.merge(repo, hex(repo.changelog.tip()))
451 return hg.merge(repo, hex(repo.changelog.tip()))
306 finally:
452 finally:
307 ui.setconfig('ui', 'forcemerge', '')
453 ui.setconfig('ui', 'forcemerge', '')
308 return 0
454 return 0
309
455
456 @command('bisect',
457 [('r', 'reset', False, _('reset bisect state')),
458 ('g', 'good', False, _('mark changeset good')),
459 ('b', 'bad', False, _('mark changeset bad')),
460 ('s', 'skip', False, _('skip testing changeset')),
461 ('e', 'extend', False, _('extend the bisect range')),
462 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
463 ('U', 'noupdate', False, _('do not update to target'))],
464 _("[-gbsr] [-U] [-c CMD] [REV]"))
310 def bisect(ui, repo, rev=None, extra=None, command=None,
465 def bisect(ui, repo, rev=None, extra=None, command=None,
311 reset=None, good=None, bad=None, skip=None, extend=None,
466 reset=None, good=None, bad=None, skip=None, extend=None,
312 noupdate=None):
467 noupdate=None):
313 """subdivision search of changesets
468 """subdivision search of changesets
314
469
315 This command helps to find changesets which introduce problems. To
470 This command helps to find changesets which introduce problems. To
316 use, mark the earliest changeset you know exhibits the problem as
471 use, mark the earliest changeset you know exhibits the problem as
317 bad, then mark the latest changeset which is free from the problem
472 bad, then mark the latest changeset which is free from the problem
318 as good. Bisect will update your working directory to a revision
473 as good. Bisect will update your working directory to a revision
319 for testing (unless the -U/--noupdate option is specified). Once
474 for testing (unless the -U/--noupdate option is specified). Once
320 you have performed tests, mark the working directory as good or
475 you have performed tests, mark the working directory as good or
321 bad, and bisect will either update to another candidate changeset
476 bad, and bisect will either update to another candidate changeset
322 or announce that it has found the bad revision.
477 or announce that it has found the bad revision.
323
478
324 As a shortcut, you can also use the revision argument to mark a
479 As a shortcut, you can also use the revision argument to mark a
325 revision as good or bad without checking it out first.
480 revision as good or bad without checking it out first.
326
481
327 If you supply a command, it will be used for automatic bisection.
482 If you supply a command, it will be used for automatic bisection.
328 Its exit status will be used to mark revisions as good or bad:
483 Its exit status will be used to mark revisions as good or bad:
329 status 0 means good, 125 means to skip the revision, 127
484 status 0 means good, 125 means to skip the revision, 127
330 (command not found) will abort the bisection, and any other
485 (command not found) will abort the bisection, and any other
331 non-zero exit status means the revision is bad.
486 non-zero exit status means the revision is bad.
332
487
333 Returns 0 on success.
488 Returns 0 on success.
334 """
489 """
335 def extendbisectrange(nodes, good):
490 def extendbisectrange(nodes, good):
336 # bisect is incomplete when it ends on a merge node and
491 # bisect is incomplete when it ends on a merge node and
337 # one of the parent was not checked.
492 # one of the parent was not checked.
338 parents = repo[nodes[0]].parents()
493 parents = repo[nodes[0]].parents()
339 if len(parents) > 1:
494 if len(parents) > 1:
340 side = good and state['bad'] or state['good']
495 side = good and state['bad'] or state['good']
341 num = len(set(i.node() for i in parents) & set(side))
496 num = len(set(i.node() for i in parents) & set(side))
342 if num == 1:
497 if num == 1:
343 return parents[0].ancestor(parents[1])
498 return parents[0].ancestor(parents[1])
344 return None
499 return None
345
500
346 def print_result(nodes, good):
501 def print_result(nodes, good):
347 displayer = cmdutil.show_changeset(ui, repo, {})
502 displayer = cmdutil.show_changeset(ui, repo, {})
348 if len(nodes) == 1:
503 if len(nodes) == 1:
349 # narrowed it down to a single revision
504 # narrowed it down to a single revision
350 if good:
505 if good:
351 ui.write(_("The first good revision is:\n"))
506 ui.write(_("The first good revision is:\n"))
352 else:
507 else:
353 ui.write(_("The first bad revision is:\n"))
508 ui.write(_("The first bad revision is:\n"))
354 displayer.show(repo[nodes[0]])
509 displayer.show(repo[nodes[0]])
355 extendnode = extendbisectrange(nodes, good)
510 extendnode = extendbisectrange(nodes, good)
356 if extendnode is not None:
511 if extendnode is not None:
357 ui.write(_('Not all ancestors of this changeset have been'
512 ui.write(_('Not all ancestors of this changeset have been'
358 ' checked.\nUse bisect --extend to continue the '
513 ' checked.\nUse bisect --extend to continue the '
359 'bisection from\nthe common ancestor, %s.\n')
514 'bisection from\nthe common ancestor, %s.\n')
360 % extendnode)
515 % extendnode)
361 else:
516 else:
362 # multiple possible revisions
517 # multiple possible revisions
363 if good:
518 if good:
364 ui.write(_("Due to skipped revisions, the first "
519 ui.write(_("Due to skipped revisions, the first "
365 "good revision could be any of:\n"))
520 "good revision could be any of:\n"))
366 else:
521 else:
367 ui.write(_("Due to skipped revisions, the first "
522 ui.write(_("Due to skipped revisions, the first "
368 "bad revision could be any of:\n"))
523 "bad revision could be any of:\n"))
369 for n in nodes:
524 for n in nodes:
370 displayer.show(repo[n])
525 displayer.show(repo[n])
371 displayer.close()
526 displayer.close()
372
527
373 def check_state(state, interactive=True):
528 def check_state(state, interactive=True):
374 if not state['good'] or not state['bad']:
529 if not state['good'] or not state['bad']:
375 if (good or bad or skip or reset) and interactive:
530 if (good or bad or skip or reset) and interactive:
376 return
531 return
377 if not state['good']:
532 if not state['good']:
378 raise util.Abort(_('cannot bisect (no known good revisions)'))
533 raise util.Abort(_('cannot bisect (no known good revisions)'))
379 else:
534 else:
380 raise util.Abort(_('cannot bisect (no known bad revisions)'))
535 raise util.Abort(_('cannot bisect (no known bad revisions)'))
381 return True
536 return True
382
537
383 # backward compatibility
538 # backward compatibility
384 if rev in "good bad reset init".split():
539 if rev in "good bad reset init".split():
385 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
540 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
386 cmd, rev, extra = rev, extra, None
541 cmd, rev, extra = rev, extra, None
387 if cmd == "good":
542 if cmd == "good":
388 good = True
543 good = True
389 elif cmd == "bad":
544 elif cmd == "bad":
390 bad = True
545 bad = True
391 else:
546 else:
392 reset = True
547 reset = True
393 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
548 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
394 raise util.Abort(_('incompatible arguments'))
549 raise util.Abort(_('incompatible arguments'))
395
550
396 if reset:
551 if reset:
397 p = repo.join("bisect.state")
552 p = repo.join("bisect.state")
398 if os.path.exists(p):
553 if os.path.exists(p):
399 os.unlink(p)
554 os.unlink(p)
400 return
555 return
401
556
402 state = hbisect.load_state(repo)
557 state = hbisect.load_state(repo)
403
558
404 if command:
559 if command:
405 changesets = 1
560 changesets = 1
406 try:
561 try:
407 while changesets:
562 while changesets:
408 # update state
563 # update state
409 status = util.system(command)
564 status = util.system(command)
410 if status == 125:
565 if status == 125:
411 transition = "skip"
566 transition = "skip"
412 elif status == 0:
567 elif status == 0:
413 transition = "good"
568 transition = "good"
414 # status < 0 means process was killed
569 # status < 0 means process was killed
415 elif status == 127:
570 elif status == 127:
416 raise util.Abort(_("failed to execute %s") % command)
571 raise util.Abort(_("failed to execute %s") % command)
417 elif status < 0:
572 elif status < 0:
418 raise util.Abort(_("%s killed") % command)
573 raise util.Abort(_("%s killed") % command)
419 else:
574 else:
420 transition = "bad"
575 transition = "bad"
421 ctx = cmdutil.revsingle(repo, rev)
576 ctx = cmdutil.revsingle(repo, rev)
422 rev = None # clear for future iterations
577 rev = None # clear for future iterations
423 state[transition].append(ctx.node())
578 state[transition].append(ctx.node())
424 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
579 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
425 check_state(state, interactive=False)
580 check_state(state, interactive=False)
426 # bisect
581 # bisect
427 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
582 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
428 # update to next check
583 # update to next check
429 cmdutil.bailifchanged(repo)
584 cmdutil.bailifchanged(repo)
430 hg.clean(repo, nodes[0], show_stats=False)
585 hg.clean(repo, nodes[0], show_stats=False)
431 finally:
586 finally:
432 hbisect.save_state(repo, state)
587 hbisect.save_state(repo, state)
433 print_result(nodes, good)
588 print_result(nodes, good)
434 return
589 return
435
590
436 # update state
591 # update state
437
592
438 if rev:
593 if rev:
439 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
594 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
440 else:
595 else:
441 nodes = [repo.lookup('.')]
596 nodes = [repo.lookup('.')]
442
597
443 if good or bad or skip:
598 if good or bad or skip:
444 if good:
599 if good:
445 state['good'] += nodes
600 state['good'] += nodes
446 elif bad:
601 elif bad:
447 state['bad'] += nodes
602 state['bad'] += nodes
448 elif skip:
603 elif skip:
449 state['skip'] += nodes
604 state['skip'] += nodes
450 hbisect.save_state(repo, state)
605 hbisect.save_state(repo, state)
451
606
452 if not check_state(state):
607 if not check_state(state):
453 return
608 return
454
609
455 # actually bisect
610 # actually bisect
456 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
611 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
457 if extend:
612 if extend:
458 if not changesets:
613 if not changesets:
459 extendnode = extendbisectrange(nodes, good)
614 extendnode = extendbisectrange(nodes, good)
460 if extendnode is not None:
615 if extendnode is not None:
461 ui.write(_("Extending search to changeset %d:%s\n"
616 ui.write(_("Extending search to changeset %d:%s\n"
462 % (extendnode.rev(), extendnode)))
617 % (extendnode.rev(), extendnode)))
463 if noupdate:
618 if noupdate:
464 return
619 return
465 cmdutil.bailifchanged(repo)
620 cmdutil.bailifchanged(repo)
466 return hg.clean(repo, extendnode.node())
621 return hg.clean(repo, extendnode.node())
467 raise util.Abort(_("nothing to extend"))
622 raise util.Abort(_("nothing to extend"))
468
623
469 if changesets == 0:
624 if changesets == 0:
470 print_result(nodes, good)
625 print_result(nodes, good)
471 else:
626 else:
472 assert len(nodes) == 1 # only a single node can be tested next
627 assert len(nodes) == 1 # only a single node can be tested next
473 node = nodes[0]
628 node = nodes[0]
474 # compute the approximate number of remaining tests
629 # compute the approximate number of remaining tests
475 tests, size = 0, 2
630 tests, size = 0, 2
476 while size <= changesets:
631 while size <= changesets:
477 tests, size = tests + 1, size * 2
632 tests, size = tests + 1, size * 2
478 rev = repo.changelog.rev(node)
633 rev = repo.changelog.rev(node)
479 ui.write(_("Testing changeset %d:%s "
634 ui.write(_("Testing changeset %d:%s "
480 "(%d changesets remaining, ~%d tests)\n")
635 "(%d changesets remaining, ~%d tests)\n")
481 % (rev, short(node), changesets, tests))
636 % (rev, short(node), changesets, tests))
482 if not noupdate:
637 if not noupdate:
483 cmdutil.bailifchanged(repo)
638 cmdutil.bailifchanged(repo)
484 return hg.clean(repo, node)
639 return hg.clean(repo, node)
485
640
641 @command('bookmarks',
642 [('f', 'force', False, _('force')),
643 ('r', 'rev', '', _('revision'), _('REV')),
644 ('d', 'delete', False, _('delete a given bookmark')),
645 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
646 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
647 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
486 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
648 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
487 rename=None, inactive=False):
649 rename=None, inactive=False):
488 '''track a line of development with movable markers
650 '''track a line of development with movable markers
489
651
490 Bookmarks are pointers to certain commits that move when
652 Bookmarks are pointers to certain commits that move when
491 committing. Bookmarks are local. They can be renamed, copied and
653 committing. Bookmarks are local. They can be renamed, copied and
492 deleted. It is possible to use bookmark names in :hg:`merge` and
654 deleted. It is possible to use bookmark names in :hg:`merge` and
493 :hg:`update` to merge and update respectively to a given bookmark.
655 :hg:`update` to merge and update respectively to a given bookmark.
494
656
495 You can use :hg:`bookmark NAME` to set a bookmark on the working
657 You can use :hg:`bookmark NAME` to set a bookmark on the working
496 directory's parent revision with the given name. If you specify
658 directory's parent revision with the given name. If you specify
497 a revision using -r REV (where REV may be an existing bookmark),
659 a revision using -r REV (where REV may be an existing bookmark),
498 the bookmark is assigned to that revision.
660 the bookmark is assigned to that revision.
499
661
500 Bookmarks can be pushed and pulled between repositories (see :hg:`help
662 Bookmarks can be pushed and pulled between repositories (see :hg:`help
501 push` and :hg:`help pull`). This requires both the local and remote
663 push` and :hg:`help pull`). This requires both the local and remote
502 repositories to support bookmarks. For versions prior to 1.8, this means
664 repositories to support bookmarks. For versions prior to 1.8, this means
503 the bookmarks extension must be enabled.
665 the bookmarks extension must be enabled.
504 '''
666 '''
505 hexfn = ui.debugflag and hex or short
667 hexfn = ui.debugflag and hex or short
506 marks = repo._bookmarks
668 marks = repo._bookmarks
507 cur = repo.changectx('.').node()
669 cur = repo.changectx('.').node()
508
670
509 if rename:
671 if rename:
510 if rename not in marks:
672 if rename not in marks:
511 raise util.Abort(_("bookmark '%s' does not exist") % rename)
673 raise util.Abort(_("bookmark '%s' does not exist") % rename)
512 if mark in marks and not force:
674 if mark in marks and not force:
513 raise util.Abort(_("bookmark '%s' already exists "
675 raise util.Abort(_("bookmark '%s' already exists "
514 "(use -f to force)") % mark)
676 "(use -f to force)") % mark)
515 if mark is None:
677 if mark is None:
516 raise util.Abort(_("new bookmark name required"))
678 raise util.Abort(_("new bookmark name required"))
517 marks[mark] = marks[rename]
679 marks[mark] = marks[rename]
518 if repo._bookmarkcurrent == rename and not inactive:
680 if repo._bookmarkcurrent == rename and not inactive:
519 bookmarks.setcurrent(repo, mark)
681 bookmarks.setcurrent(repo, mark)
520 del marks[rename]
682 del marks[rename]
521 bookmarks.write(repo)
683 bookmarks.write(repo)
522 return
684 return
523
685
524 if delete:
686 if delete:
525 if mark is None:
687 if mark is None:
526 raise util.Abort(_("bookmark name required"))
688 raise util.Abort(_("bookmark name required"))
527 if mark not in marks:
689 if mark not in marks:
528 raise util.Abort(_("bookmark '%s' does not exist") % mark)
690 raise util.Abort(_("bookmark '%s' does not exist") % mark)
529 if mark == repo._bookmarkcurrent:
691 if mark == repo._bookmarkcurrent:
530 bookmarks.setcurrent(repo, None)
692 bookmarks.setcurrent(repo, None)
531 del marks[mark]
693 del marks[mark]
532 bookmarks.write(repo)
694 bookmarks.write(repo)
533 return
695 return
534
696
535 if mark is not None:
697 if mark is not None:
536 if "\n" in mark:
698 if "\n" in mark:
537 raise util.Abort(_("bookmark name cannot contain newlines"))
699 raise util.Abort(_("bookmark name cannot contain newlines"))
538 mark = mark.strip()
700 mark = mark.strip()
539 if not mark:
701 if not mark:
540 raise util.Abort(_("bookmark names cannot consist entirely of "
702 raise util.Abort(_("bookmark names cannot consist entirely of "
541 "whitespace"))
703 "whitespace"))
542 if inactive and mark == repo._bookmarkcurrent:
704 if inactive and mark == repo._bookmarkcurrent:
543 bookmarks.setcurrent(repo, None)
705 bookmarks.setcurrent(repo, None)
544 return
706 return
545 if mark in marks and not force:
707 if mark in marks and not force:
546 raise util.Abort(_("bookmark '%s' already exists "
708 raise util.Abort(_("bookmark '%s' already exists "
547 "(use -f to force)") % mark)
709 "(use -f to force)") % mark)
548 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
710 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
549 and not force):
711 and not force):
550 raise util.Abort(
712 raise util.Abort(
551 _("a bookmark cannot have the name of an existing branch"))
713 _("a bookmark cannot have the name of an existing branch"))
552 if rev:
714 if rev:
553 marks[mark] = repo.lookup(rev)
715 marks[mark] = repo.lookup(rev)
554 else:
716 else:
555 marks[mark] = repo.changectx('.').node()
717 marks[mark] = repo.changectx('.').node()
556 if not inactive and repo.changectx('.').node() == marks[mark]:
718 if not inactive and repo.changectx('.').node() == marks[mark]:
557 bookmarks.setcurrent(repo, mark)
719 bookmarks.setcurrent(repo, mark)
558 bookmarks.write(repo)
720 bookmarks.write(repo)
559 return
721 return
560
722
561 if mark is None:
723 if mark is None:
562 if rev:
724 if rev:
563 raise util.Abort(_("bookmark name required"))
725 raise util.Abort(_("bookmark name required"))
564 if len(marks) == 0:
726 if len(marks) == 0:
565 ui.status(_("no bookmarks set\n"))
727 ui.status(_("no bookmarks set\n"))
566 else:
728 else:
567 for bmark, n in sorted(marks.iteritems()):
729 for bmark, n in sorted(marks.iteritems()):
568 current = repo._bookmarkcurrent
730 current = repo._bookmarkcurrent
569 if bmark == current and n == cur:
731 if bmark == current and n == cur:
570 prefix, label = '*', 'bookmarks.current'
732 prefix, label = '*', 'bookmarks.current'
571 else:
733 else:
572 prefix, label = ' ', ''
734 prefix, label = ' ', ''
573
735
574 if ui.quiet:
736 if ui.quiet:
575 ui.write("%s\n" % bmark, label=label)
737 ui.write("%s\n" % bmark, label=label)
576 else:
738 else:
577 ui.write(" %s %-25s %d:%s\n" % (
739 ui.write(" %s %-25s %d:%s\n" % (
578 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
740 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
579 label=label)
741 label=label)
580 return
742 return
581
743
744 @command('branch',
745 [('f', 'force', None,
746 _('set branch name even if it shadows an existing branch')),
747 ('C', 'clean', None, _('reset branch name to parent branch name'))],
748 _('[-fC] [NAME]'))
582 def branch(ui, repo, label=None, **opts):
749 def branch(ui, repo, label=None, **opts):
583 """set or show the current branch name
750 """set or show the current branch name
584
751
585 With no argument, show the current branch name. With one argument,
752 With no argument, show the current branch name. With one argument,
586 set the working directory branch name (the branch will not exist
753 set the working directory branch name (the branch will not exist
587 in the repository until the next commit). Standard practice
754 in the repository until the next commit). Standard practice
588 recommends that primary development take place on the 'default'
755 recommends that primary development take place on the 'default'
589 branch.
756 branch.
590
757
591 Unless -f/--force is specified, branch will not let you set a
758 Unless -f/--force is specified, branch will not let you set a
592 branch name that already exists, even if it's inactive.
759 branch name that already exists, even if it's inactive.
593
760
594 Use -C/--clean to reset the working directory branch to that of
761 Use -C/--clean to reset the working directory branch to that of
595 the parent of the working directory, negating a previous branch
762 the parent of the working directory, negating a previous branch
596 change.
763 change.
597
764
598 Use the command :hg:`update` to switch to an existing branch. Use
765 Use the command :hg:`update` to switch to an existing branch. Use
599 :hg:`commit --close-branch` to mark this branch as closed.
766 :hg:`commit --close-branch` to mark this branch as closed.
600
767
601 Returns 0 on success.
768 Returns 0 on success.
602 """
769 """
603
770
604 if opts.get('clean'):
771 if opts.get('clean'):
605 label = repo[None].p1().branch()
772 label = repo[None].p1().branch()
606 repo.dirstate.setbranch(label)
773 repo.dirstate.setbranch(label)
607 ui.status(_('reset working directory to branch %s\n') % label)
774 ui.status(_('reset working directory to branch %s\n') % label)
608 elif label:
775 elif label:
609 if not opts.get('force') and label in repo.branchtags():
776 if not opts.get('force') and label in repo.branchtags():
610 if label not in [p.branch() for p in repo.parents()]:
777 if label not in [p.branch() for p in repo.parents()]:
611 raise util.Abort(_('a branch of the same name already exists'),
778 raise util.Abort(_('a branch of the same name already exists'),
612 # i18n: "it" refers to an existing branch
779 # i18n: "it" refers to an existing branch
613 hint=_("use 'hg update' to switch to it"))
780 hint=_("use 'hg update' to switch to it"))
614 repo.dirstate.setbranch(label)
781 repo.dirstate.setbranch(label)
615 ui.status(_('marked working directory as branch %s\n') % label)
782 ui.status(_('marked working directory as branch %s\n') % label)
616 else:
783 else:
617 ui.write("%s\n" % repo.dirstate.branch())
784 ui.write("%s\n" % repo.dirstate.branch())
618
785
786 @command('branches',
787 [('a', 'active', False, _('show only branches that have unmerged heads')),
788 ('c', 'closed', False, _('show normal and closed branches'))],
789 _('[-ac]'))
619 def branches(ui, repo, active=False, closed=False):
790 def branches(ui, repo, active=False, closed=False):
620 """list repository named branches
791 """list repository named branches
621
792
622 List the repository's named branches, indicating which ones are
793 List the repository's named branches, indicating which ones are
623 inactive. If -c/--closed is specified, also list branches which have
794 inactive. If -c/--closed is specified, also list branches which have
624 been marked closed (see :hg:`commit --close-branch`).
795 been marked closed (see :hg:`commit --close-branch`).
625
796
626 If -a/--active is specified, only show active branches. A branch
797 If -a/--active is specified, only show active branches. A branch
627 is considered active if it contains repository heads.
798 is considered active if it contains repository heads.
628
799
629 Use the command :hg:`update` to switch to an existing branch.
800 Use the command :hg:`update` to switch to an existing branch.
630
801
631 Returns 0.
802 Returns 0.
632 """
803 """
633
804
634 hexfunc = ui.debugflag and hex or short
805 hexfunc = ui.debugflag and hex or short
635 activebranches = [repo[n].branch() for n in repo.heads()]
806 activebranches = [repo[n].branch() for n in repo.heads()]
636 def testactive(tag, node):
807 def testactive(tag, node):
637 realhead = tag in activebranches
808 realhead = tag in activebranches
638 open = node in repo.branchheads(tag, closed=False)
809 open = node in repo.branchheads(tag, closed=False)
639 return realhead and open
810 return realhead and open
640 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
811 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
641 for tag, node in repo.branchtags().items()],
812 for tag, node in repo.branchtags().items()],
642 reverse=True)
813 reverse=True)
643
814
644 for isactive, node, tag in branches:
815 for isactive, node, tag in branches:
645 if (not active) or isactive:
816 if (not active) or isactive:
646 if ui.quiet:
817 if ui.quiet:
647 ui.write("%s\n" % tag)
818 ui.write("%s\n" % tag)
648 else:
819 else:
649 hn = repo.lookup(node)
820 hn = repo.lookup(node)
650 if isactive:
821 if isactive:
651 label = 'branches.active'
822 label = 'branches.active'
652 notice = ''
823 notice = ''
653 elif hn not in repo.branchheads(tag, closed=False):
824 elif hn not in repo.branchheads(tag, closed=False):
654 if not closed:
825 if not closed:
655 continue
826 continue
656 label = 'branches.closed'
827 label = 'branches.closed'
657 notice = _(' (closed)')
828 notice = _(' (closed)')
658 else:
829 else:
659 label = 'branches.inactive'
830 label = 'branches.inactive'
660 notice = _(' (inactive)')
831 notice = _(' (inactive)')
661 if tag == repo.dirstate.branch():
832 if tag == repo.dirstate.branch():
662 label = 'branches.current'
833 label = 'branches.current'
663 rev = str(node).rjust(31 - encoding.colwidth(tag))
834 rev = str(node).rjust(31 - encoding.colwidth(tag))
664 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
835 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
665 tag = ui.label(tag, label)
836 tag = ui.label(tag, label)
666 ui.write("%s %s%s\n" % (tag, rev, notice))
837 ui.write("%s %s%s\n" % (tag, rev, notice))
667
838
839 @command('bundle',
840 [('f', 'force', None, _('run even when the destination is unrelated')),
841 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
842 _('REV')),
843 ('b', 'branch', [], _('a specific branch you would like to bundle'),
844 _('BRANCH')),
845 ('', 'base', [],
846 _('a base changeset assumed to be available at the destination'),
847 _('REV')),
848 ('a', 'all', None, _('bundle all changesets in the repository')),
849 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
850 ] + remoteopts,
851 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
668 def bundle(ui, repo, fname, dest=None, **opts):
852 def bundle(ui, repo, fname, dest=None, **opts):
669 """create a changegroup file
853 """create a changegroup file
670
854
671 Generate a compressed changegroup file collecting changesets not
855 Generate a compressed changegroup file collecting changesets not
672 known to be in another repository.
856 known to be in another repository.
673
857
674 If you omit the destination repository, then hg assumes the
858 If you omit the destination repository, then hg assumes the
675 destination will have all the nodes you specify with --base
859 destination will have all the nodes you specify with --base
676 parameters. To create a bundle containing all changesets, use
860 parameters. To create a bundle containing all changesets, use
677 -a/--all (or --base null).
861 -a/--all (or --base null).
678
862
679 You can change compression method with the -t/--type option.
863 You can change compression method with the -t/--type option.
680 The available compression methods are: none, bzip2, and
864 The available compression methods are: none, bzip2, and
681 gzip (by default, bundles are compressed using bzip2).
865 gzip (by default, bundles are compressed using bzip2).
682
866
683 The bundle file can then be transferred using conventional means
867 The bundle file can then be transferred using conventional means
684 and applied to another repository with the unbundle or pull
868 and applied to another repository with the unbundle or pull
685 command. This is useful when direct push and pull are not
869 command. This is useful when direct push and pull are not
686 available or when exporting an entire repository is undesirable.
870 available or when exporting an entire repository is undesirable.
687
871
688 Applying bundles preserves all changeset contents including
872 Applying bundles preserves all changeset contents including
689 permissions, copy/rename information, and revision history.
873 permissions, copy/rename information, and revision history.
690
874
691 Returns 0 on success, 1 if no changes found.
875 Returns 0 on success, 1 if no changes found.
692 """
876 """
693 revs = None
877 revs = None
694 if 'rev' in opts:
878 if 'rev' in opts:
695 revs = cmdutil.revrange(repo, opts['rev'])
879 revs = cmdutil.revrange(repo, opts['rev'])
696
880
697 if opts.get('all'):
881 if opts.get('all'):
698 base = ['null']
882 base = ['null']
699 else:
883 else:
700 base = cmdutil.revrange(repo, opts.get('base'))
884 base = cmdutil.revrange(repo, opts.get('base'))
701 if base:
885 if base:
702 if dest:
886 if dest:
703 raise util.Abort(_("--base is incompatible with specifying "
887 raise util.Abort(_("--base is incompatible with specifying "
704 "a destination"))
888 "a destination"))
705 common = [repo.lookup(rev) for rev in base]
889 common = [repo.lookup(rev) for rev in base]
706 heads = revs and map(repo.lookup, revs) or revs
890 heads = revs and map(repo.lookup, revs) or revs
707 else:
891 else:
708 dest = ui.expandpath(dest or 'default-push', dest or 'default')
892 dest = ui.expandpath(dest or 'default-push', dest or 'default')
709 dest, branches = hg.parseurl(dest, opts.get('branch'))
893 dest, branches = hg.parseurl(dest, opts.get('branch'))
710 other = hg.repository(hg.remoteui(repo, opts), dest)
894 other = hg.repository(hg.remoteui(repo, opts), dest)
711 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
895 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
712 heads = revs and map(repo.lookup, revs) or revs
896 heads = revs and map(repo.lookup, revs) or revs
713 common, outheads = discovery.findcommonoutgoing(repo, other,
897 common, outheads = discovery.findcommonoutgoing(repo, other,
714 onlyheads=heads,
898 onlyheads=heads,
715 force=opts.get('force'))
899 force=opts.get('force'))
716
900
717 cg = repo.getbundle('bundle', common=common, heads=heads)
901 cg = repo.getbundle('bundle', common=common, heads=heads)
718 if not cg:
902 if not cg:
719 ui.status(_("no changes found\n"))
903 ui.status(_("no changes found\n"))
720 return 1
904 return 1
721
905
722 bundletype = opts.get('type', 'bzip2').lower()
906 bundletype = opts.get('type', 'bzip2').lower()
723 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
907 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
724 bundletype = btypes.get(bundletype)
908 bundletype = btypes.get(bundletype)
725 if bundletype not in changegroup.bundletypes:
909 if bundletype not in changegroup.bundletypes:
726 raise util.Abort(_('unknown bundle type specified with --type'))
910 raise util.Abort(_('unknown bundle type specified with --type'))
727
911
728 changegroup.writebundle(cg, fname, bundletype)
912 changegroup.writebundle(cg, fname, bundletype)
729
913
914 @command('cat',
915 [('o', 'output', '',
916 _('print output to file with formatted name'), _('FORMAT')),
917 ('r', 'rev', '', _('print the given revision'), _('REV')),
918 ('', 'decode', None, _('apply any matching decode filter')),
919 ] + walkopts,
920 _('[OPTION]... FILE...'))
730 def cat(ui, repo, file1, *pats, **opts):
921 def cat(ui, repo, file1, *pats, **opts):
731 """output the current or given revision of files
922 """output the current or given revision of files
732
923
733 Print the specified files as they were at the given revision. If
924 Print the specified files as they were at the given revision. If
734 no revision is given, the parent of the working directory is used,
925 no revision is given, the parent of the working directory is used,
735 or tip if no revision is checked out.
926 or tip if no revision is checked out.
736
927
737 Output may be to a file, in which case the name of the file is
928 Output may be to a file, in which case the name of the file is
738 given using a format string. The formatting rules are the same as
929 given using a format string. The formatting rules are the same as
739 for the export command, with the following additions:
930 for the export command, with the following additions:
740
931
741 :``%s``: basename of file being printed
932 :``%s``: basename of file being printed
742 :``%d``: dirname of file being printed, or '.' if in repository root
933 :``%d``: dirname of file being printed, or '.' if in repository root
743 :``%p``: root-relative path name of file being printed
934 :``%p``: root-relative path name of file being printed
744
935
745 Returns 0 on success.
936 Returns 0 on success.
746 """
937 """
747 ctx = cmdutil.revsingle(repo, opts.get('rev'))
938 ctx = cmdutil.revsingle(repo, opts.get('rev'))
748 err = 1
939 err = 1
749 m = cmdutil.match(repo, (file1,) + pats, opts)
940 m = cmdutil.match(repo, (file1,) + pats, opts)
750 for abs in ctx.walk(m):
941 for abs in ctx.walk(m):
751 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
942 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
752 pathname=abs)
943 pathname=abs)
753 data = ctx[abs].data()
944 data = ctx[abs].data()
754 if opts.get('decode'):
945 if opts.get('decode'):
755 data = repo.wwritedata(abs, data)
946 data = repo.wwritedata(abs, data)
756 fp.write(data)
947 fp.write(data)
757 fp.close()
948 fp.close()
758 err = 0
949 err = 0
759 return err
950 return err
760
951
952 @command('^clone',
953 [('U', 'noupdate', None,
954 _('the clone will include an empty working copy (only a repository)')),
955 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
956 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
957 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
958 ('', 'pull', None, _('use pull protocol to copy metadata')),
959 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
960 ] + remoteopts,
961 _('[OPTION]... SOURCE [DEST]'))
761 def clone(ui, source, dest=None, **opts):
962 def clone(ui, source, dest=None, **opts):
762 """make a copy of an existing repository
963 """make a copy of an existing repository
763
964
764 Create a copy of an existing repository in a new directory.
965 Create a copy of an existing repository in a new directory.
765
966
766 If no destination directory name is specified, it defaults to the
967 If no destination directory name is specified, it defaults to the
767 basename of the source.
968 basename of the source.
768
969
769 The location of the source is added to the new repository's
970 The location of the source is added to the new repository's
770 ``.hg/hgrc`` file, as the default to be used for future pulls.
971 ``.hg/hgrc`` file, as the default to be used for future pulls.
771
972
772 See :hg:`help urls` for valid source format details.
973 See :hg:`help urls` for valid source format details.
773
974
774 It is possible to specify an ``ssh://`` URL as the destination, but no
975 It is possible to specify an ``ssh://`` URL as the destination, but no
775 ``.hg/hgrc`` and working directory will be created on the remote side.
976 ``.hg/hgrc`` and working directory will be created on the remote side.
776 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
977 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
777
978
778 A set of changesets (tags, or branch names) to pull may be specified
979 A set of changesets (tags, or branch names) to pull may be specified
779 by listing each changeset (tag, or branch name) with -r/--rev.
980 by listing each changeset (tag, or branch name) with -r/--rev.
780 If -r/--rev is used, the cloned repository will contain only a subset
981 If -r/--rev is used, the cloned repository will contain only a subset
781 of the changesets of the source repository. Only the set of changesets
982 of the changesets of the source repository. Only the set of changesets
782 defined by all -r/--rev options (including all their ancestors)
983 defined by all -r/--rev options (including all their ancestors)
783 will be pulled into the destination repository.
984 will be pulled into the destination repository.
784 No subsequent changesets (including subsequent tags) will be present
985 No subsequent changesets (including subsequent tags) will be present
785 in the destination.
986 in the destination.
786
987
787 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
988 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
788 local source repositories.
989 local source repositories.
789
990
790 For efficiency, hardlinks are used for cloning whenever the source
991 For efficiency, hardlinks are used for cloning whenever the source
791 and destination are on the same filesystem (note this applies only
992 and destination are on the same filesystem (note this applies only
792 to the repository data, not to the working directory). Some
993 to the repository data, not to the working directory). Some
793 filesystems, such as AFS, implement hardlinking incorrectly, but
994 filesystems, such as AFS, implement hardlinking incorrectly, but
794 do not report errors. In these cases, use the --pull option to
995 do not report errors. In these cases, use the --pull option to
795 avoid hardlinking.
996 avoid hardlinking.
796
997
797 In some cases, you can clone repositories and the working directory
998 In some cases, you can clone repositories and the working directory
798 using full hardlinks with ::
999 using full hardlinks with ::
799
1000
800 $ cp -al REPO REPOCLONE
1001 $ cp -al REPO REPOCLONE
801
1002
802 This is the fastest way to clone, but it is not always safe. The
1003 This is the fastest way to clone, but it is not always safe. The
803 operation is not atomic (making sure REPO is not modified during
1004 operation is not atomic (making sure REPO is not modified during
804 the operation is up to you) and you have to make sure your editor
1005 the operation is up to you) and you have to make sure your editor
805 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
1006 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
806 this is not compatible with certain extensions that place their
1007 this is not compatible with certain extensions that place their
807 metadata under the .hg directory, such as mq.
1008 metadata under the .hg directory, such as mq.
808
1009
809 Mercurial will update the working directory to the first applicable
1010 Mercurial will update the working directory to the first applicable
810 revision from this list:
1011 revision from this list:
811
1012
812 a) null if -U or the source repository has no changesets
1013 a) null if -U or the source repository has no changesets
813 b) if -u . and the source repository is local, the first parent of
1014 b) if -u . and the source repository is local, the first parent of
814 the source repository's working directory
1015 the source repository's working directory
815 c) the changeset specified with -u (if a branch name, this means the
1016 c) the changeset specified with -u (if a branch name, this means the
816 latest head of that branch)
1017 latest head of that branch)
817 d) the changeset specified with -r
1018 d) the changeset specified with -r
818 e) the tipmost head specified with -b
1019 e) the tipmost head specified with -b
819 f) the tipmost head specified with the url#branch source syntax
1020 f) the tipmost head specified with the url#branch source syntax
820 g) the tipmost head of the default branch
1021 g) the tipmost head of the default branch
821 h) tip
1022 h) tip
822
1023
823 Returns 0 on success.
1024 Returns 0 on success.
824 """
1025 """
825 if opts.get('noupdate') and opts.get('updaterev'):
1026 if opts.get('noupdate') and opts.get('updaterev'):
826 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1027 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
827
1028
828 r = hg.clone(hg.remoteui(ui, opts), source, dest,
1029 r = hg.clone(hg.remoteui(ui, opts), source, dest,
829 pull=opts.get('pull'),
1030 pull=opts.get('pull'),
830 stream=opts.get('uncompressed'),
1031 stream=opts.get('uncompressed'),
831 rev=opts.get('rev'),
1032 rev=opts.get('rev'),
832 update=opts.get('updaterev') or not opts.get('noupdate'),
1033 update=opts.get('updaterev') or not opts.get('noupdate'),
833 branch=opts.get('branch'))
1034 branch=opts.get('branch'))
834
1035
835 return r is None
1036 return r is None
836
1037
1038 @command('^commit|ci',
1039 [('A', 'addremove', None,
1040 _('mark new/missing files as added/removed before committing')),
1041 ('', 'close-branch', None,
1042 _('mark a branch as closed, hiding it from the branch list')),
1043 ] + walkopts + commitopts + commitopts2,
1044 _('[OPTION]... [FILE]...'))
837 def commit(ui, repo, *pats, **opts):
1045 def commit(ui, repo, *pats, **opts):
838 """commit the specified files or all outstanding changes
1046 """commit the specified files or all outstanding changes
839
1047
840 Commit changes to the given files into the repository. Unlike a
1048 Commit changes to the given files into the repository. Unlike a
841 centralized SCM, this operation is a local operation. See
1049 centralized SCM, this operation is a local operation. See
842 :hg:`push` for a way to actively distribute your changes.
1050 :hg:`push` for a way to actively distribute your changes.
843
1051
844 If a list of files is omitted, all changes reported by :hg:`status`
1052 If a list of files is omitted, all changes reported by :hg:`status`
845 will be committed.
1053 will be committed.
846
1054
847 If you are committing the result of a merge, do not provide any
1055 If you are committing the result of a merge, do not provide any
848 filenames or -I/-X filters.
1056 filenames or -I/-X filters.
849
1057
850 If no commit message is specified, Mercurial starts your
1058 If no commit message is specified, Mercurial starts your
851 configured editor where you can enter a message. In case your
1059 configured editor where you can enter a message. In case your
852 commit fails, you will find a backup of your message in
1060 commit fails, you will find a backup of your message in
853 ``.hg/last-message.txt``.
1061 ``.hg/last-message.txt``.
854
1062
855 See :hg:`help dates` for a list of formats valid for -d/--date.
1063 See :hg:`help dates` for a list of formats valid for -d/--date.
856
1064
857 Returns 0 on success, 1 if nothing changed.
1065 Returns 0 on success, 1 if nothing changed.
858 """
1066 """
859 extra = {}
1067 extra = {}
860 if opts.get('close_branch'):
1068 if opts.get('close_branch'):
861 if repo['.'].node() not in repo.branchheads():
1069 if repo['.'].node() not in repo.branchheads():
862 # The topo heads set is included in the branch heads set of the
1070 # The topo heads set is included in the branch heads set of the
863 # current branch, so it's sufficient to test branchheads
1071 # current branch, so it's sufficient to test branchheads
864 raise util.Abort(_('can only close branch heads'))
1072 raise util.Abort(_('can only close branch heads'))
865 extra['close'] = 1
1073 extra['close'] = 1
866 e = cmdutil.commiteditor
1074 e = cmdutil.commiteditor
867 if opts.get('force_editor'):
1075 if opts.get('force_editor'):
868 e = cmdutil.commitforceeditor
1076 e = cmdutil.commitforceeditor
869
1077
870 def commitfunc(ui, repo, message, match, opts):
1078 def commitfunc(ui, repo, message, match, opts):
871 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1079 return repo.commit(message, opts.get('user'), opts.get('date'), match,
872 editor=e, extra=extra)
1080 editor=e, extra=extra)
873
1081
874 branch = repo[None].branch()
1082 branch = repo[None].branch()
875 bheads = repo.branchheads(branch)
1083 bheads = repo.branchheads(branch)
876
1084
877 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1085 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
878 if not node:
1086 if not node:
879 stat = repo.status(match=cmdutil.match(repo, pats, opts))
1087 stat = repo.status(match=cmdutil.match(repo, pats, opts))
880 if stat[3]:
1088 if stat[3]:
881 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1089 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
882 % len(stat[3]))
1090 % len(stat[3]))
883 else:
1091 else:
884 ui.status(_("nothing changed\n"))
1092 ui.status(_("nothing changed\n"))
885 return 1
1093 return 1
886
1094
887 ctx = repo[node]
1095 ctx = repo[node]
888 parents = ctx.parents()
1096 parents = ctx.parents()
889
1097
890 if bheads and not [x for x in parents
1098 if bheads and not [x for x in parents
891 if x.node() in bheads and x.branch() == branch]:
1099 if x.node() in bheads and x.branch() == branch]:
892 ui.status(_('created new head\n'))
1100 ui.status(_('created new head\n'))
893 # The message is not printed for initial roots. For the other
1101 # The message is not printed for initial roots. For the other
894 # changesets, it is printed in the following situations:
1102 # changesets, it is printed in the following situations:
895 #
1103 #
896 # Par column: for the 2 parents with ...
1104 # Par column: for the 2 parents with ...
897 # N: null or no parent
1105 # N: null or no parent
898 # B: parent is on another named branch
1106 # B: parent is on another named branch
899 # C: parent is a regular non head changeset
1107 # C: parent is a regular non head changeset
900 # H: parent was a branch head of the current branch
1108 # H: parent was a branch head of the current branch
901 # Msg column: whether we print "created new head" message
1109 # Msg column: whether we print "created new head" message
902 # In the following, it is assumed that there already exists some
1110 # In the following, it is assumed that there already exists some
903 # initial branch heads of the current branch, otherwise nothing is
1111 # initial branch heads of the current branch, otherwise nothing is
904 # printed anyway.
1112 # printed anyway.
905 #
1113 #
906 # Par Msg Comment
1114 # Par Msg Comment
907 # NN y additional topo root
1115 # NN y additional topo root
908 #
1116 #
909 # BN y additional branch root
1117 # BN y additional branch root
910 # CN y additional topo head
1118 # CN y additional topo head
911 # HN n usual case
1119 # HN n usual case
912 #
1120 #
913 # BB y weird additional branch root
1121 # BB y weird additional branch root
914 # CB y branch merge
1122 # CB y branch merge
915 # HB n merge with named branch
1123 # HB n merge with named branch
916 #
1124 #
917 # CC y additional head from merge
1125 # CC y additional head from merge
918 # CH n merge with a head
1126 # CH n merge with a head
919 #
1127 #
920 # HH n head merge: head count decreases
1128 # HH n head merge: head count decreases
921
1129
922 if not opts.get('close_branch'):
1130 if not opts.get('close_branch'):
923 for r in parents:
1131 for r in parents:
924 if r.extra().get('close') and r.branch() == branch:
1132 if r.extra().get('close') and r.branch() == branch:
925 ui.status(_('reopening closed branch head %d\n') % r)
1133 ui.status(_('reopening closed branch head %d\n') % r)
926
1134
927 if ui.debugflag:
1135 if ui.debugflag:
928 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1136 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
929 elif ui.verbose:
1137 elif ui.verbose:
930 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1138 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
931
1139
1140 @command('copy|cp',
1141 [('A', 'after', None, _('record a copy that has already occurred')),
1142 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1143 ] + walkopts + dryrunopts,
1144 _('[OPTION]... [SOURCE]... DEST'))
932 def copy(ui, repo, *pats, **opts):
1145 def copy(ui, repo, *pats, **opts):
933 """mark files as copied for the next commit
1146 """mark files as copied for the next commit
934
1147
935 Mark dest as having copies of source files. If dest is a
1148 Mark dest as having copies of source files. If dest is a
936 directory, copies are put in that directory. If dest is a file,
1149 directory, copies are put in that directory. If dest is a file,
937 the source must be a single file.
1150 the source must be a single file.
938
1151
939 By default, this command copies the contents of files as they
1152 By default, this command copies the contents of files as they
940 exist in the working directory. If invoked with -A/--after, the
1153 exist in the working directory. If invoked with -A/--after, the
941 operation is recorded, but no copying is performed.
1154 operation is recorded, but no copying is performed.
942
1155
943 This command takes effect with the next commit. To undo a copy
1156 This command takes effect with the next commit. To undo a copy
944 before that, see :hg:`revert`.
1157 before that, see :hg:`revert`.
945
1158
946 Returns 0 on success, 1 if errors are encountered.
1159 Returns 0 on success, 1 if errors are encountered.
947 """
1160 """
948 wlock = repo.wlock(False)
1161 wlock = repo.wlock(False)
949 try:
1162 try:
950 return cmdutil.copy(ui, repo, pats, opts)
1163 return cmdutil.copy(ui, repo, pats, opts)
951 finally:
1164 finally:
952 wlock.release()
1165 wlock.release()
953
1166
1167 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
954 def debugancestor(ui, repo, *args):
1168 def debugancestor(ui, repo, *args):
955 """find the ancestor revision of two revisions in a given index"""
1169 """find the ancestor revision of two revisions in a given index"""
956 if len(args) == 3:
1170 if len(args) == 3:
957 index, rev1, rev2 = args
1171 index, rev1, rev2 = args
958 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1172 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
959 lookup = r.lookup
1173 lookup = r.lookup
960 elif len(args) == 2:
1174 elif len(args) == 2:
961 if not repo:
1175 if not repo:
962 raise util.Abort(_("there is no Mercurial repository here "
1176 raise util.Abort(_("there is no Mercurial repository here "
963 "(.hg not found)"))
1177 "(.hg not found)"))
964 rev1, rev2 = args
1178 rev1, rev2 = args
965 r = repo.changelog
1179 r = repo.changelog
966 lookup = repo.lookup
1180 lookup = repo.lookup
967 else:
1181 else:
968 raise util.Abort(_('either two or three arguments required'))
1182 raise util.Abort(_('either two or three arguments required'))
969 a = r.ancestor(lookup(rev1), lookup(rev2))
1183 a = r.ancestor(lookup(rev1), lookup(rev2))
970 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1184 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
971
1185
1186 @command('debugbuilddag',
1187 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1188 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1189 ('n', 'new-file', None, _('add new file at each rev'))],
1190 _('[OPTION]... [TEXT]'))
972 def debugbuilddag(ui, repo, text=None,
1191 def debugbuilddag(ui, repo, text=None,
973 mergeable_file=False,
1192 mergeable_file=False,
974 overwritten_file=False,
1193 overwritten_file=False,
975 new_file=False):
1194 new_file=False):
976 """builds a repo with a given DAG from scratch in the current empty repo
1195 """builds a repo with a given DAG from scratch in the current empty repo
977
1196
978 The description of the DAG is read from stdin if not given on the
1197 The description of the DAG is read from stdin if not given on the
979 command line.
1198 command line.
980
1199
981 Elements:
1200 Elements:
982
1201
983 - "+n" is a linear run of n nodes based on the current default parent
1202 - "+n" is a linear run of n nodes based on the current default parent
984 - "." is a single node based on the current default parent
1203 - "." is a single node based on the current default parent
985 - "$" resets the default parent to null (implied at the start);
1204 - "$" resets the default parent to null (implied at the start);
986 otherwise the default parent is always the last node created
1205 otherwise the default parent is always the last node created
987 - "<p" sets the default parent to the backref p
1206 - "<p" sets the default parent to the backref p
988 - "*p" is a fork at parent p, which is a backref
1207 - "*p" is a fork at parent p, which is a backref
989 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1208 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
990 - "/p2" is a merge of the preceding node and p2
1209 - "/p2" is a merge of the preceding node and p2
991 - ":tag" defines a local tag for the preceding node
1210 - ":tag" defines a local tag for the preceding node
992 - "@branch" sets the named branch for subsequent nodes
1211 - "@branch" sets the named branch for subsequent nodes
993 - "#...\\n" is a comment up to the end of the line
1212 - "#...\\n" is a comment up to the end of the line
994
1213
995 Whitespace between the above elements is ignored.
1214 Whitespace between the above elements is ignored.
996
1215
997 A backref is either
1216 A backref is either
998
1217
999 - a number n, which references the node curr-n, where curr is the current
1218 - a number n, which references the node curr-n, where curr is the current
1000 node, or
1219 node, or
1001 - the name of a local tag you placed earlier using ":tag", or
1220 - the name of a local tag you placed earlier using ":tag", or
1002 - empty to denote the default parent.
1221 - empty to denote the default parent.
1003
1222
1004 All string valued-elements are either strictly alphanumeric, or must
1223 All string valued-elements are either strictly alphanumeric, or must
1005 be enclosed in double quotes ("..."), with "\\" as escape character.
1224 be enclosed in double quotes ("..."), with "\\" as escape character.
1006 """
1225 """
1007
1226
1008 if text is None:
1227 if text is None:
1009 ui.status(_("reading DAG from stdin\n"))
1228 ui.status(_("reading DAG from stdin\n"))
1010 text = sys.stdin.read()
1229 text = sys.stdin.read()
1011
1230
1012 cl = repo.changelog
1231 cl = repo.changelog
1013 if len(cl) > 0:
1232 if len(cl) > 0:
1014 raise util.Abort(_('repository is not empty'))
1233 raise util.Abort(_('repository is not empty'))
1015
1234
1016 # determine number of revs in DAG
1235 # determine number of revs in DAG
1017 total = 0
1236 total = 0
1018 for type, data in dagparser.parsedag(text):
1237 for type, data in dagparser.parsedag(text):
1019 if type == 'n':
1238 if type == 'n':
1020 total += 1
1239 total += 1
1021
1240
1022 if mergeable_file:
1241 if mergeable_file:
1023 linesperrev = 2
1242 linesperrev = 2
1024 # make a file with k lines per rev
1243 # make a file with k lines per rev
1025 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1244 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1026 initialmergedlines.append("")
1245 initialmergedlines.append("")
1027
1246
1028 tags = []
1247 tags = []
1029
1248
1030 tr = repo.transaction("builddag")
1249 tr = repo.transaction("builddag")
1031 try:
1250 try:
1032
1251
1033 at = -1
1252 at = -1
1034 atbranch = 'default'
1253 atbranch = 'default'
1035 nodeids = []
1254 nodeids = []
1036 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1255 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1037 for type, data in dagparser.parsedag(text):
1256 for type, data in dagparser.parsedag(text):
1038 if type == 'n':
1257 if type == 'n':
1039 ui.note('node %s\n' % str(data))
1258 ui.note('node %s\n' % str(data))
1040 id, ps = data
1259 id, ps = data
1041
1260
1042 files = []
1261 files = []
1043 fctxs = {}
1262 fctxs = {}
1044
1263
1045 p2 = None
1264 p2 = None
1046 if mergeable_file:
1265 if mergeable_file:
1047 fn = "mf"
1266 fn = "mf"
1048 p1 = repo[ps[0]]
1267 p1 = repo[ps[0]]
1049 if len(ps) > 1:
1268 if len(ps) > 1:
1050 p2 = repo[ps[1]]
1269 p2 = repo[ps[1]]
1051 pa = p1.ancestor(p2)
1270 pa = p1.ancestor(p2)
1052 base, local, other = [x[fn].data() for x in pa, p1, p2]
1271 base, local, other = [x[fn].data() for x in pa, p1, p2]
1053 m3 = simplemerge.Merge3Text(base, local, other)
1272 m3 = simplemerge.Merge3Text(base, local, other)
1054 ml = [l.strip() for l in m3.merge_lines()]
1273 ml = [l.strip() for l in m3.merge_lines()]
1055 ml.append("")
1274 ml.append("")
1056 elif at > 0:
1275 elif at > 0:
1057 ml = p1[fn].data().split("\n")
1276 ml = p1[fn].data().split("\n")
1058 else:
1277 else:
1059 ml = initialmergedlines
1278 ml = initialmergedlines
1060 ml[id * linesperrev] += " r%i" % id
1279 ml[id * linesperrev] += " r%i" % id
1061 mergedtext = "\n".join(ml)
1280 mergedtext = "\n".join(ml)
1062 files.append(fn)
1281 files.append(fn)
1063 fctxs[fn] = context.memfilectx(fn, mergedtext)
1282 fctxs[fn] = context.memfilectx(fn, mergedtext)
1064
1283
1065 if overwritten_file:
1284 if overwritten_file:
1066 fn = "of"
1285 fn = "of"
1067 files.append(fn)
1286 files.append(fn)
1068 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1287 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1069
1288
1070 if new_file:
1289 if new_file:
1071 fn = "nf%i" % id
1290 fn = "nf%i" % id
1072 files.append(fn)
1291 files.append(fn)
1073 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1292 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1074 if len(ps) > 1:
1293 if len(ps) > 1:
1075 if not p2:
1294 if not p2:
1076 p2 = repo[ps[1]]
1295 p2 = repo[ps[1]]
1077 for fn in p2:
1296 for fn in p2:
1078 if fn.startswith("nf"):
1297 if fn.startswith("nf"):
1079 files.append(fn)
1298 files.append(fn)
1080 fctxs[fn] = p2[fn]
1299 fctxs[fn] = p2[fn]
1081
1300
1082 def fctxfn(repo, cx, path):
1301 def fctxfn(repo, cx, path):
1083 return fctxs.get(path)
1302 return fctxs.get(path)
1084
1303
1085 if len(ps) == 0 or ps[0] < 0:
1304 if len(ps) == 0 or ps[0] < 0:
1086 pars = [None, None]
1305 pars = [None, None]
1087 elif len(ps) == 1:
1306 elif len(ps) == 1:
1088 pars = [nodeids[ps[0]], None]
1307 pars = [nodeids[ps[0]], None]
1089 else:
1308 else:
1090 pars = [nodeids[p] for p in ps]
1309 pars = [nodeids[p] for p in ps]
1091 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1310 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1092 date=(id, 0),
1311 date=(id, 0),
1093 user="debugbuilddag",
1312 user="debugbuilddag",
1094 extra={'branch': atbranch})
1313 extra={'branch': atbranch})
1095 nodeid = repo.commitctx(cx)
1314 nodeid = repo.commitctx(cx)
1096 nodeids.append(nodeid)
1315 nodeids.append(nodeid)
1097 at = id
1316 at = id
1098 elif type == 'l':
1317 elif type == 'l':
1099 id, name = data
1318 id, name = data
1100 ui.note('tag %s\n' % name)
1319 ui.note('tag %s\n' % name)
1101 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1320 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1102 elif type == 'a':
1321 elif type == 'a':
1103 ui.note('branch %s\n' % data)
1322 ui.note('branch %s\n' % data)
1104 atbranch = data
1323 atbranch = data
1105 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1324 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1106 tr.close()
1325 tr.close()
1107 finally:
1326 finally:
1108 ui.progress(_('building'), None)
1327 ui.progress(_('building'), None)
1109 tr.release()
1328 tr.release()
1110
1329
1111 if tags:
1330 if tags:
1112 repo.opener.write("localtags", "".join(tags))
1331 repo.opener.write("localtags", "".join(tags))
1113
1332
1333 @command('debugcommands', [], _('[COMMAND]'))
1114 def debugcommands(ui, cmd='', *args):
1334 def debugcommands(ui, cmd='', *args):
1115 """list all available commands and options"""
1335 """list all available commands and options"""
1116 for cmd, vals in sorted(table.iteritems()):
1336 for cmd, vals in sorted(table.iteritems()):
1117 cmd = cmd.split('|')[0].strip('^')
1337 cmd = cmd.split('|')[0].strip('^')
1118 opts = ', '.join([i[1] for i in vals[1]])
1338 opts = ', '.join([i[1] for i in vals[1]])
1119 ui.write('%s: %s\n' % (cmd, opts))
1339 ui.write('%s: %s\n' % (cmd, opts))
1120
1340
1341 @command('debugcomplete',
1342 [('o', 'options', None, _('show the command options'))],
1343 _('[-o] CMD'))
1121 def debugcomplete(ui, cmd='', **opts):
1344 def debugcomplete(ui, cmd='', **opts):
1122 """returns the completion list associated with the given command"""
1345 """returns the completion list associated with the given command"""
1123
1346
1124 if opts.get('options'):
1347 if opts.get('options'):
1125 options = []
1348 options = []
1126 otables = [globalopts]
1349 otables = [globalopts]
1127 if cmd:
1350 if cmd:
1128 aliases, entry = cmdutil.findcmd(cmd, table, False)
1351 aliases, entry = cmdutil.findcmd(cmd, table, False)
1129 otables.append(entry[1])
1352 otables.append(entry[1])
1130 for t in otables:
1353 for t in otables:
1131 for o in t:
1354 for o in t:
1132 if "(DEPRECATED)" in o[3]:
1355 if "(DEPRECATED)" in o[3]:
1133 continue
1356 continue
1134 if o[0]:
1357 if o[0]:
1135 options.append('-%s' % o[0])
1358 options.append('-%s' % o[0])
1136 options.append('--%s' % o[1])
1359 options.append('--%s' % o[1])
1137 ui.write("%s\n" % "\n".join(options))
1360 ui.write("%s\n" % "\n".join(options))
1138 return
1361 return
1139
1362
1140 cmdlist = cmdutil.findpossible(cmd, table)
1363 cmdlist = cmdutil.findpossible(cmd, table)
1141 if ui.verbose:
1364 if ui.verbose:
1142 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1365 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1143 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1366 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1144
1367
1368 @command('debugfsinfo', [], _('[PATH]'))
1145 def debugfsinfo(ui, path = "."):
1369 def debugfsinfo(ui, path = "."):
1146 """show information detected about current filesystem"""
1370 """show information detected about current filesystem"""
1147 util.writefile('.debugfsinfo', '')
1371 util.writefile('.debugfsinfo', '')
1148 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1372 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1149 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1373 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1150 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1374 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1151 and 'yes' or 'no'))
1375 and 'yes' or 'no'))
1152 os.unlink('.debugfsinfo')
1376 os.unlink('.debugfsinfo')
1153
1377
1378 @command('debugrebuildstate',
1379 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1380 _('[-r REV] [REV]'))
1154 def debugrebuildstate(ui, repo, rev="tip"):
1381 def debugrebuildstate(ui, repo, rev="tip"):
1155 """rebuild the dirstate as it would look like for the given revision"""
1382 """rebuild the dirstate as it would look like for the given revision"""
1156 ctx = cmdutil.revsingle(repo, rev)
1383 ctx = cmdutil.revsingle(repo, rev)
1157 wlock = repo.wlock()
1384 wlock = repo.wlock()
1158 try:
1385 try:
1159 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1386 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1160 finally:
1387 finally:
1161 wlock.release()
1388 wlock.release()
1162
1389
1390 @command('debugcheckstate', [], '')
1163 def debugcheckstate(ui, repo):
1391 def debugcheckstate(ui, repo):
1164 """validate the correctness of the current dirstate"""
1392 """validate the correctness of the current dirstate"""
1165 parent1, parent2 = repo.dirstate.parents()
1393 parent1, parent2 = repo.dirstate.parents()
1166 m1 = repo[parent1].manifest()
1394 m1 = repo[parent1].manifest()
1167 m2 = repo[parent2].manifest()
1395 m2 = repo[parent2].manifest()
1168 errors = 0
1396 errors = 0
1169 for f in repo.dirstate:
1397 for f in repo.dirstate:
1170 state = repo.dirstate[f]
1398 state = repo.dirstate[f]
1171 if state in "nr" and f not in m1:
1399 if state in "nr" and f not in m1:
1172 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1400 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1173 errors += 1
1401 errors += 1
1174 if state in "a" and f in m1:
1402 if state in "a" and f in m1:
1175 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1403 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1176 errors += 1
1404 errors += 1
1177 if state in "m" and f not in m1 and f not in m2:
1405 if state in "m" and f not in m1 and f not in m2:
1178 ui.warn(_("%s in state %s, but not in either manifest\n") %
1406 ui.warn(_("%s in state %s, but not in either manifest\n") %
1179 (f, state))
1407 (f, state))
1180 errors += 1
1408 errors += 1
1181 for f in m1:
1409 for f in m1:
1182 state = repo.dirstate[f]
1410 state = repo.dirstate[f]
1183 if state not in "nrm":
1411 if state not in "nrm":
1184 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1412 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1185 errors += 1
1413 errors += 1
1186 if errors:
1414 if errors:
1187 error = _(".hg/dirstate inconsistent with current parent's manifest")
1415 error = _(".hg/dirstate inconsistent with current parent's manifest")
1188 raise util.Abort(error)
1416 raise util.Abort(error)
1189
1417
1418 @command('showconfig|debugconfig',
1419 [('u', 'untrusted', None, _('show untrusted configuration options'))],
1420 _('[-u] [NAME]...'))
1190 def showconfig(ui, repo, *values, **opts):
1421 def showconfig(ui, repo, *values, **opts):
1191 """show combined config settings from all hgrc files
1422 """show combined config settings from all hgrc files
1192
1423
1193 With no arguments, print names and values of all config items.
1424 With no arguments, print names and values of all config items.
1194
1425
1195 With one argument of the form section.name, print just the value
1426 With one argument of the form section.name, print just the value
1196 of that config item.
1427 of that config item.
1197
1428
1198 With multiple arguments, print names and values of all config
1429 With multiple arguments, print names and values of all config
1199 items with matching section names.
1430 items with matching section names.
1200
1431
1201 With --debug, the source (filename and line number) is printed
1432 With --debug, the source (filename and line number) is printed
1202 for each config item.
1433 for each config item.
1203
1434
1204 Returns 0 on success.
1435 Returns 0 on success.
1205 """
1436 """
1206
1437
1207 for f in scmutil.rcpath():
1438 for f in scmutil.rcpath():
1208 ui.debug(_('read config from: %s\n') % f)
1439 ui.debug(_('read config from: %s\n') % f)
1209 untrusted = bool(opts.get('untrusted'))
1440 untrusted = bool(opts.get('untrusted'))
1210 if values:
1441 if values:
1211 sections = [v for v in values if '.' not in v]
1442 sections = [v for v in values if '.' not in v]
1212 items = [v for v in values if '.' in v]
1443 items = [v for v in values if '.' in v]
1213 if len(items) > 1 or items and sections:
1444 if len(items) > 1 or items and sections:
1214 raise util.Abort(_('only one config item permitted'))
1445 raise util.Abort(_('only one config item permitted'))
1215 for section, name, value in ui.walkconfig(untrusted=untrusted):
1446 for section, name, value in ui.walkconfig(untrusted=untrusted):
1216 value = str(value).replace('\n', '\\n')
1447 value = str(value).replace('\n', '\\n')
1217 sectname = section + '.' + name
1448 sectname = section + '.' + name
1218 if values:
1449 if values:
1219 for v in values:
1450 for v in values:
1220 if v == section:
1451 if v == section:
1221 ui.debug('%s: ' %
1452 ui.debug('%s: ' %
1222 ui.configsource(section, name, untrusted))
1453 ui.configsource(section, name, untrusted))
1223 ui.write('%s=%s\n' % (sectname, value))
1454 ui.write('%s=%s\n' % (sectname, value))
1224 elif v == sectname:
1455 elif v == sectname:
1225 ui.debug('%s: ' %
1456 ui.debug('%s: ' %
1226 ui.configsource(section, name, untrusted))
1457 ui.configsource(section, name, untrusted))
1227 ui.write(value, '\n')
1458 ui.write(value, '\n')
1228 else:
1459 else:
1229 ui.debug('%s: ' %
1460 ui.debug('%s: ' %
1230 ui.configsource(section, name, untrusted))
1461 ui.configsource(section, name, untrusted))
1231 ui.write('%s=%s\n' % (sectname, value))
1462 ui.write('%s=%s\n' % (sectname, value))
1232
1463
1464 @command('debugknown', [], _('REPO ID...'))
1233 def debugknown(ui, repopath, *ids, **opts):
1465 def debugknown(ui, repopath, *ids, **opts):
1234 """test whether node ids are known to a repo
1466 """test whether node ids are known to a repo
1235
1467
1236 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1468 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1237 indicating unknown/known.
1469 indicating unknown/known.
1238 """
1470 """
1239 repo = hg.repository(ui, repopath)
1471 repo = hg.repository(ui, repopath)
1240 if not repo.capable('known'):
1472 if not repo.capable('known'):
1241 raise util.Abort("known() not supported by target repository")
1473 raise util.Abort("known() not supported by target repository")
1242 flags = repo.known([bin(s) for s in ids])
1474 flags = repo.known([bin(s) for s in ids])
1243 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1475 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1244
1476
1477 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1245 def debugbundle(ui, bundlepath, all=None, **opts):
1478 def debugbundle(ui, bundlepath, all=None, **opts):
1246 """lists the contents of a bundle"""
1479 """lists the contents of a bundle"""
1247 f = url.open(ui, bundlepath)
1480 f = url.open(ui, bundlepath)
1248 try:
1481 try:
1249 gen = changegroup.readbundle(f, bundlepath)
1482 gen = changegroup.readbundle(f, bundlepath)
1250 if all:
1483 if all:
1251 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1484 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1252
1485
1253 def showchunks(named):
1486 def showchunks(named):
1254 ui.write("\n%s\n" % named)
1487 ui.write("\n%s\n" % named)
1255 chain = None
1488 chain = None
1256 while 1:
1489 while 1:
1257 chunkdata = gen.deltachunk(chain)
1490 chunkdata = gen.deltachunk(chain)
1258 if not chunkdata:
1491 if not chunkdata:
1259 break
1492 break
1260 node = chunkdata['node']
1493 node = chunkdata['node']
1261 p1 = chunkdata['p1']
1494 p1 = chunkdata['p1']
1262 p2 = chunkdata['p2']
1495 p2 = chunkdata['p2']
1263 cs = chunkdata['cs']
1496 cs = chunkdata['cs']
1264 deltabase = chunkdata['deltabase']
1497 deltabase = chunkdata['deltabase']
1265 delta = chunkdata['delta']
1498 delta = chunkdata['delta']
1266 ui.write("%s %s %s %s %s %s\n" %
1499 ui.write("%s %s %s %s %s %s\n" %
1267 (hex(node), hex(p1), hex(p2),
1500 (hex(node), hex(p1), hex(p2),
1268 hex(cs), hex(deltabase), len(delta)))
1501 hex(cs), hex(deltabase), len(delta)))
1269 chain = node
1502 chain = node
1270
1503
1271 chunkdata = gen.changelogheader()
1504 chunkdata = gen.changelogheader()
1272 showchunks("changelog")
1505 showchunks("changelog")
1273 chunkdata = gen.manifestheader()
1506 chunkdata = gen.manifestheader()
1274 showchunks("manifest")
1507 showchunks("manifest")
1275 while 1:
1508 while 1:
1276 chunkdata = gen.filelogheader()
1509 chunkdata = gen.filelogheader()
1277 if not chunkdata:
1510 if not chunkdata:
1278 break
1511 break
1279 fname = chunkdata['filename']
1512 fname = chunkdata['filename']
1280 showchunks(fname)
1513 showchunks(fname)
1281 else:
1514 else:
1282 chunkdata = gen.changelogheader()
1515 chunkdata = gen.changelogheader()
1283 chain = None
1516 chain = None
1284 while 1:
1517 while 1:
1285 chunkdata = gen.deltachunk(chain)
1518 chunkdata = gen.deltachunk(chain)
1286 if not chunkdata:
1519 if not chunkdata:
1287 break
1520 break
1288 node = chunkdata['node']
1521 node = chunkdata['node']
1289 ui.write("%s\n" % hex(node))
1522 ui.write("%s\n" % hex(node))
1290 chain = node
1523 chain = node
1291 finally:
1524 finally:
1292 f.close()
1525 f.close()
1293
1526
1527 @command('debuggetbundle',
1528 [('H', 'head', [], _('id of head node'), _('ID')),
1529 ('C', 'common', [], _('id of common node'), _('ID')),
1530 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1531 _('REPO FILE [-H|-C ID]...'))
1294 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1532 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1295 """retrieves a bundle from a repo
1533 """retrieves a bundle from a repo
1296
1534
1297 Every ID must be a full-length hex node id string. Saves the bundle to the
1535 Every ID must be a full-length hex node id string. Saves the bundle to the
1298 given file.
1536 given file.
1299 """
1537 """
1300 repo = hg.repository(ui, repopath)
1538 repo = hg.repository(ui, repopath)
1301 if not repo.capable('getbundle'):
1539 if not repo.capable('getbundle'):
1302 raise util.Abort("getbundle() not supported by target repository")
1540 raise util.Abort("getbundle() not supported by target repository")
1303 args = {}
1541 args = {}
1304 if common:
1542 if common:
1305 args['common'] = [bin(s) for s in common]
1543 args['common'] = [bin(s) for s in common]
1306 if head:
1544 if head:
1307 args['heads'] = [bin(s) for s in head]
1545 args['heads'] = [bin(s) for s in head]
1308 bundle = repo.getbundle('debug', **args)
1546 bundle = repo.getbundle('debug', **args)
1309
1547
1310 bundletype = opts.get('type', 'bzip2').lower()
1548 bundletype = opts.get('type', 'bzip2').lower()
1311 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1549 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1312 bundletype = btypes.get(bundletype)
1550 bundletype = btypes.get(bundletype)
1313 if bundletype not in changegroup.bundletypes:
1551 if bundletype not in changegroup.bundletypes:
1314 raise util.Abort(_('unknown bundle type specified with --type'))
1552 raise util.Abort(_('unknown bundle type specified with --type'))
1315 changegroup.writebundle(bundle, bundlepath, bundletype)
1553 changegroup.writebundle(bundle, bundlepath, bundletype)
1316
1554
1555 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1317 def debugpushkey(ui, repopath, namespace, *keyinfo):
1556 def debugpushkey(ui, repopath, namespace, *keyinfo):
1318 '''access the pushkey key/value protocol
1557 '''access the pushkey key/value protocol
1319
1558
1320 With two args, list the keys in the given namespace.
1559 With two args, list the keys in the given namespace.
1321
1560
1322 With five args, set a key to new if it currently is set to old.
1561 With five args, set a key to new if it currently is set to old.
1323 Reports success or failure.
1562 Reports success or failure.
1324 '''
1563 '''
1325
1564
1326 target = hg.repository(ui, repopath)
1565 target = hg.repository(ui, repopath)
1327 if keyinfo:
1566 if keyinfo:
1328 key, old, new = keyinfo
1567 key, old, new = keyinfo
1329 r = target.pushkey(namespace, key, old, new)
1568 r = target.pushkey(namespace, key, old, new)
1330 ui.status(str(r) + '\n')
1569 ui.status(str(r) + '\n')
1331 return not r
1570 return not r
1332 else:
1571 else:
1333 for k, v in target.listkeys(namespace).iteritems():
1572 for k, v in target.listkeys(namespace).iteritems():
1334 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1573 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1335 v.encode('string-escape')))
1574 v.encode('string-escape')))
1336
1575
1576 @command('debugrevspec', [], ('REVSPEC'))
1337 def debugrevspec(ui, repo, expr):
1577 def debugrevspec(ui, repo, expr):
1338 '''parse and apply a revision specification'''
1578 '''parse and apply a revision specification'''
1339 if ui.verbose:
1579 if ui.verbose:
1340 tree = revset.parse(expr)[0]
1580 tree = revset.parse(expr)[0]
1341 ui.note(tree, "\n")
1581 ui.note(tree, "\n")
1342 newtree = revset.findaliases(ui, tree)
1582 newtree = revset.findaliases(ui, tree)
1343 if newtree != tree:
1583 if newtree != tree:
1344 ui.note(newtree, "\n")
1584 ui.note(newtree, "\n")
1345 func = revset.match(ui, expr)
1585 func = revset.match(ui, expr)
1346 for c in func(repo, range(len(repo))):
1586 for c in func(repo, range(len(repo))):
1347 ui.write("%s\n" % c)
1587 ui.write("%s\n" % c)
1348
1588
1589 @command('debugsetparents', [], _('REV1 [REV2]'))
1349 def debugsetparents(ui, repo, rev1, rev2=None):
1590 def debugsetparents(ui, repo, rev1, rev2=None):
1350 """manually set the parents of the current working directory
1591 """manually set the parents of the current working directory
1351
1592
1352 This is useful for writing repository conversion tools, but should
1593 This is useful for writing repository conversion tools, but should
1353 be used with care.
1594 be used with care.
1354
1595
1355 Returns 0 on success.
1596 Returns 0 on success.
1356 """
1597 """
1357
1598
1358 r1 = cmdutil.revsingle(repo, rev1).node()
1599 r1 = cmdutil.revsingle(repo, rev1).node()
1359 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1600 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1360
1601
1361 wlock = repo.wlock()
1602 wlock = repo.wlock()
1362 try:
1603 try:
1363 repo.dirstate.setparents(r1, r2)
1604 repo.dirstate.setparents(r1, r2)
1364 finally:
1605 finally:
1365 wlock.release()
1606 wlock.release()
1366
1607
1608 @command('debugstate',
1609 [('', 'nodates', None, _('do not display the saved mtime')),
1610 ('', 'datesort', None, _('sort by saved mtime'))],
1611 _('[OPTION]...'))
1367 def debugstate(ui, repo, nodates=None, datesort=None):
1612 def debugstate(ui, repo, nodates=None, datesort=None):
1368 """show the contents of the current dirstate"""
1613 """show the contents of the current dirstate"""
1369 timestr = ""
1614 timestr = ""
1370 showdate = not nodates
1615 showdate = not nodates
1371 if datesort:
1616 if datesort:
1372 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
1617 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
1373 else:
1618 else:
1374 keyfunc = None # sort by filename
1619 keyfunc = None # sort by filename
1375 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
1620 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
1376 if showdate:
1621 if showdate:
1377 if ent[3] == -1:
1622 if ent[3] == -1:
1378 # Pad or slice to locale representation
1623 # Pad or slice to locale representation
1379 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1624 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1380 time.localtime(0)))
1625 time.localtime(0)))
1381 timestr = 'unset'
1626 timestr = 'unset'
1382 timestr = (timestr[:locale_len] +
1627 timestr = (timestr[:locale_len] +
1383 ' ' * (locale_len - len(timestr)))
1628 ' ' * (locale_len - len(timestr)))
1384 else:
1629 else:
1385 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1630 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1386 time.localtime(ent[3]))
1631 time.localtime(ent[3]))
1387 if ent[1] & 020000:
1632 if ent[1] & 020000:
1388 mode = 'lnk'
1633 mode = 'lnk'
1389 else:
1634 else:
1390 mode = '%3o' % (ent[1] & 0777)
1635 mode = '%3o' % (ent[1] & 0777)
1391 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1636 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1392 for f in repo.dirstate.copies():
1637 for f in repo.dirstate.copies():
1393 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1638 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1394
1639
1640 @command('debugsub',
1641 [('r', 'rev', '',
1642 _('revision to check'), _('REV'))],
1643 _('[-r REV] [REV]'))
1395 def debugsub(ui, repo, rev=None):
1644 def debugsub(ui, repo, rev=None):
1396 ctx = cmdutil.revsingle(repo, rev, None)
1645 ctx = cmdutil.revsingle(repo, rev, None)
1397 for k, v in sorted(ctx.substate.items()):
1646 for k, v in sorted(ctx.substate.items()):
1398 ui.write('path %s\n' % k)
1647 ui.write('path %s\n' % k)
1399 ui.write(' source %s\n' % v[0])
1648 ui.write(' source %s\n' % v[0])
1400 ui.write(' revision %s\n' % v[1])
1649 ui.write(' revision %s\n' % v[1])
1401
1650
1651 @command('debugdag',
1652 [('t', 'tags', None, _('use tags as labels')),
1653 ('b', 'branches', None, _('annotate with branch names')),
1654 ('', 'dots', None, _('use dots for runs')),
1655 ('s', 'spaces', None, _('separate elements by spaces'))],
1656 _('[OPTION]... [FILE [REV]...]'))
1402 def debugdag(ui, repo, file_=None, *revs, **opts):
1657 def debugdag(ui, repo, file_=None, *revs, **opts):
1403 """format the changelog or an index DAG as a concise textual description
1658 """format the changelog or an index DAG as a concise textual description
1404
1659
1405 If you pass a revlog index, the revlog's DAG is emitted. If you list
1660 If you pass a revlog index, the revlog's DAG is emitted. If you list
1406 revision numbers, they get labelled in the output as rN.
1661 revision numbers, they get labelled in the output as rN.
1407
1662
1408 Otherwise, the changelog DAG of the current repo is emitted.
1663 Otherwise, the changelog DAG of the current repo is emitted.
1409 """
1664 """
1410 spaces = opts.get('spaces')
1665 spaces = opts.get('spaces')
1411 dots = opts.get('dots')
1666 dots = opts.get('dots')
1412 if file_:
1667 if file_:
1413 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1668 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1414 revs = set((int(r) for r in revs))
1669 revs = set((int(r) for r in revs))
1415 def events():
1670 def events():
1416 for r in rlog:
1671 for r in rlog:
1417 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1672 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1418 if r in revs:
1673 if r in revs:
1419 yield 'l', (r, "r%i" % r)
1674 yield 'l', (r, "r%i" % r)
1420 elif repo:
1675 elif repo:
1421 cl = repo.changelog
1676 cl = repo.changelog
1422 tags = opts.get('tags')
1677 tags = opts.get('tags')
1423 branches = opts.get('branches')
1678 branches = opts.get('branches')
1424 if tags:
1679 if tags:
1425 labels = {}
1680 labels = {}
1426 for l, n in repo.tags().items():
1681 for l, n in repo.tags().items():
1427 labels.setdefault(cl.rev(n), []).append(l)
1682 labels.setdefault(cl.rev(n), []).append(l)
1428 def events():
1683 def events():
1429 b = "default"
1684 b = "default"
1430 for r in cl:
1685 for r in cl:
1431 if branches:
1686 if branches:
1432 newb = cl.read(cl.node(r))[5]['branch']
1687 newb = cl.read(cl.node(r))[5]['branch']
1433 if newb != b:
1688 if newb != b:
1434 yield 'a', newb
1689 yield 'a', newb
1435 b = newb
1690 b = newb
1436 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1691 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1437 if tags:
1692 if tags:
1438 ls = labels.get(r)
1693 ls = labels.get(r)
1439 if ls:
1694 if ls:
1440 for l in ls:
1695 for l in ls:
1441 yield 'l', (r, l)
1696 yield 'l', (r, l)
1442 else:
1697 else:
1443 raise util.Abort(_('need repo for changelog dag'))
1698 raise util.Abort(_('need repo for changelog dag'))
1444
1699
1445 for line in dagparser.dagtextlines(events(),
1700 for line in dagparser.dagtextlines(events(),
1446 addspaces=spaces,
1701 addspaces=spaces,
1447 wraplabels=True,
1702 wraplabels=True,
1448 wrapannotations=True,
1703 wrapannotations=True,
1449 wrapnonlinear=dots,
1704 wrapnonlinear=dots,
1450 usedots=dots,
1705 usedots=dots,
1451 maxlinewidth=70):
1706 maxlinewidth=70):
1452 ui.write(line)
1707 ui.write(line)
1453 ui.write("\n")
1708 ui.write("\n")
1454
1709
1710 @command('debugdata', [], _('FILE REV'))
1455 def debugdata(ui, repo, file_, rev):
1711 def debugdata(ui, repo, file_, rev):
1456 """dump the contents of a data file revision"""
1712 """dump the contents of a data file revision"""
1457 r = None
1713 r = None
1458 if repo:
1714 if repo:
1459 filelog = repo.file(file_)
1715 filelog = repo.file(file_)
1460 if len(filelog):
1716 if len(filelog):
1461 r = filelog
1717 r = filelog
1462 if not r:
1718 if not r:
1463 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
1719 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
1464 file_[:-2] + ".i")
1720 file_[:-2] + ".i")
1465 try:
1721 try:
1466 ui.write(r.revision(r.lookup(rev)))
1722 ui.write(r.revision(r.lookup(rev)))
1467 except KeyError:
1723 except KeyError:
1468 raise util.Abort(_('invalid revision identifier %s') % rev)
1724 raise util.Abort(_('invalid revision identifier %s') % rev)
1469
1725
1726 @command('debugdate',
1727 [('e', 'extended', None, _('try extended date formats'))],
1728 _('[-e] DATE [RANGE]'))
1470 def debugdate(ui, date, range=None, **opts):
1729 def debugdate(ui, date, range=None, **opts):
1471 """parse and display a date"""
1730 """parse and display a date"""
1472 if opts["extended"]:
1731 if opts["extended"]:
1473 d = util.parsedate(date, util.extendeddateformats)
1732 d = util.parsedate(date, util.extendeddateformats)
1474 else:
1733 else:
1475 d = util.parsedate(date)
1734 d = util.parsedate(date)
1476 ui.write("internal: %s %s\n" % d)
1735 ui.write("internal: %s %s\n" % d)
1477 ui.write("standard: %s\n" % util.datestr(d))
1736 ui.write("standard: %s\n" % util.datestr(d))
1478 if range:
1737 if range:
1479 m = util.matchdate(range)
1738 m = util.matchdate(range)
1480 ui.write("match: %s\n" % m(d[0]))
1739 ui.write("match: %s\n" % m(d[0]))
1481
1740
1741 @command('debugignore', [], '')
1482 def debugignore(ui, repo, *values, **opts):
1742 def debugignore(ui, repo, *values, **opts):
1483 """display the combined ignore pattern"""
1743 """display the combined ignore pattern"""
1484 ignore = repo.dirstate._ignore
1744 ignore = repo.dirstate._ignore
1485 if hasattr(ignore, 'includepat'):
1745 if hasattr(ignore, 'includepat'):
1486 ui.write("%s\n" % ignore.includepat)
1746 ui.write("%s\n" % ignore.includepat)
1487 else:
1747 else:
1488 raise util.Abort(_("no ignore patterns found"))
1748 raise util.Abort(_("no ignore patterns found"))
1489
1749
1750 @command('debugdiscovery',
1751 [('', 'old', None, _('use old-style discovery')),
1752 ('', 'nonheads', None,
1753 _('use old-style discovery with non-heads included')),
1754 ] + remoteopts,
1755 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1490 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1756 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1491 """runs the changeset discovery protocol in isolation"""
1757 """runs the changeset discovery protocol in isolation"""
1492 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1758 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1493 remote = hg.repository(hg.remoteui(repo, opts), remoteurl)
1759 remote = hg.repository(hg.remoteui(repo, opts), remoteurl)
1494 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1760 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1495
1761
1496 # make sure tests are repeatable
1762 # make sure tests are repeatable
1497 random.seed(12323)
1763 random.seed(12323)
1498
1764
1499 def doit(localheads, remoteheads):
1765 def doit(localheads, remoteheads):
1500 if opts.get('old'):
1766 if opts.get('old'):
1501 if localheads:
1767 if localheads:
1502 raise util.Abort('cannot use localheads with old style discovery')
1768 raise util.Abort('cannot use localheads with old style discovery')
1503 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1769 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1504 force=True)
1770 force=True)
1505 common = set(common)
1771 common = set(common)
1506 if not opts.get('nonheads'):
1772 if not opts.get('nonheads'):
1507 ui.write("unpruned common: %s\n" % " ".join([short(n)
1773 ui.write("unpruned common: %s\n" % " ".join([short(n)
1508 for n in common]))
1774 for n in common]))
1509 dag = dagutil.revlogdag(repo.changelog)
1775 dag = dagutil.revlogdag(repo.changelog)
1510 all = dag.ancestorset(dag.internalizeall(common))
1776 all = dag.ancestorset(dag.internalizeall(common))
1511 common = dag.externalizeall(dag.headsetofconnecteds(all))
1777 common = dag.externalizeall(dag.headsetofconnecteds(all))
1512 else:
1778 else:
1513 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1779 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1514 common = set(common)
1780 common = set(common)
1515 rheads = set(hds)
1781 rheads = set(hds)
1516 lheads = set(repo.heads())
1782 lheads = set(repo.heads())
1517 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1783 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1518 if lheads <= common:
1784 if lheads <= common:
1519 ui.write("local is subset\n")
1785 ui.write("local is subset\n")
1520 elif rheads <= common:
1786 elif rheads <= common:
1521 ui.write("remote is subset\n")
1787 ui.write("remote is subset\n")
1522
1788
1523 serverlogs = opts.get('serverlog')
1789 serverlogs = opts.get('serverlog')
1524 if serverlogs:
1790 if serverlogs:
1525 for filename in serverlogs:
1791 for filename in serverlogs:
1526 logfile = open(filename, 'r')
1792 logfile = open(filename, 'r')
1527 try:
1793 try:
1528 line = logfile.readline()
1794 line = logfile.readline()
1529 while line:
1795 while line:
1530 parts = line.strip().split(';')
1796 parts = line.strip().split(';')
1531 op = parts[1]
1797 op = parts[1]
1532 if op == 'cg':
1798 if op == 'cg':
1533 pass
1799 pass
1534 elif op == 'cgss':
1800 elif op == 'cgss':
1535 doit(parts[2].split(' '), parts[3].split(' '))
1801 doit(parts[2].split(' '), parts[3].split(' '))
1536 elif op == 'unb':
1802 elif op == 'unb':
1537 doit(parts[3].split(' '), parts[2].split(' '))
1803 doit(parts[3].split(' '), parts[2].split(' '))
1538 line = logfile.readline()
1804 line = logfile.readline()
1539 finally:
1805 finally:
1540 logfile.close()
1806 logfile.close()
1541
1807
1542 else:
1808 else:
1543 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1809 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1544 opts.get('remote_head'))
1810 opts.get('remote_head'))
1545 localrevs = opts.get('local_head')
1811 localrevs = opts.get('local_head')
1546 doit(localrevs, remoterevs)
1812 doit(localrevs, remoterevs)
1547
1813
1548
1814 @command('debugindex',
1815 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1816 _('FILE'))
1549 def debugindex(ui, repo, file_, **opts):
1817 def debugindex(ui, repo, file_, **opts):
1550 """dump the contents of an index file"""
1818 """dump the contents of an index file"""
1551 r = None
1819 r = None
1552 if repo:
1820 if repo:
1553 filelog = repo.file(file_)
1821 filelog = repo.file(file_)
1554 if len(filelog):
1822 if len(filelog):
1555 r = filelog
1823 r = filelog
1556
1824
1557 format = opts.get('format', 0)
1825 format = opts.get('format', 0)
1558 if format not in (0, 1):
1826 if format not in (0, 1):
1559 raise util.Abort(_("unknown format %d") % format)
1827 raise util.Abort(_("unknown format %d") % format)
1560
1828
1561 if not r:
1829 if not r:
1562 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1830 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1563
1831
1564 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1832 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1565 if generaldelta:
1833 if generaldelta:
1566 basehdr = ' delta'
1834 basehdr = ' delta'
1567 else:
1835 else:
1568 basehdr = ' base'
1836 basehdr = ' base'
1569
1837
1570 if format == 0:
1838 if format == 0:
1571 ui.write(" rev offset length " + basehdr + " linkrev"
1839 ui.write(" rev offset length " + basehdr + " linkrev"
1572 " nodeid p1 p2\n")
1840 " nodeid p1 p2\n")
1573 elif format == 1:
1841 elif format == 1:
1574 ui.write(" rev flag offset length"
1842 ui.write(" rev flag offset length"
1575 " size " + basehdr + " link p1 p2 nodeid\n")
1843 " size " + basehdr + " link p1 p2 nodeid\n")
1576
1844
1577 for i in r:
1845 for i in r:
1578 node = r.node(i)
1846 node = r.node(i)
1579 if generaldelta:
1847 if generaldelta:
1580 base = r.deltaparent(i)
1848 base = r.deltaparent(i)
1581 else:
1849 else:
1582 base = r.chainbase(i)
1850 base = r.chainbase(i)
1583 if format == 0:
1851 if format == 0:
1584 try:
1852 try:
1585 pp = r.parents(node)
1853 pp = r.parents(node)
1586 except:
1854 except:
1587 pp = [nullid, nullid]
1855 pp = [nullid, nullid]
1588 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1856 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1589 i, r.start(i), r.length(i), base, r.linkrev(i),
1857 i, r.start(i), r.length(i), base, r.linkrev(i),
1590 short(node), short(pp[0]), short(pp[1])))
1858 short(node), short(pp[0]), short(pp[1])))
1591 elif format == 1:
1859 elif format == 1:
1592 pr = r.parentrevs(i)
1860 pr = r.parentrevs(i)
1593 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1861 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1594 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1862 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1595 base, r.linkrev(i), pr[0], pr[1], short(node)))
1863 base, r.linkrev(i), pr[0], pr[1], short(node)))
1596
1864
1865 @command('debugindexdot', [], _('FILE'))
1597 def debugindexdot(ui, repo, file_):
1866 def debugindexdot(ui, repo, file_):
1598 """dump an index DAG as a graphviz dot file"""
1867 """dump an index DAG as a graphviz dot file"""
1599 r = None
1868 r = None
1600 if repo:
1869 if repo:
1601 filelog = repo.file(file_)
1870 filelog = repo.file(file_)
1602 if len(filelog):
1871 if len(filelog):
1603 r = filelog
1872 r = filelog
1604 if not r:
1873 if not r:
1605 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1874 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1606 ui.write("digraph G {\n")
1875 ui.write("digraph G {\n")
1607 for i in r:
1876 for i in r:
1608 node = r.node(i)
1877 node = r.node(i)
1609 pp = r.parents(node)
1878 pp = r.parents(node)
1610 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1879 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1611 if pp[1] != nullid:
1880 if pp[1] != nullid:
1612 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1881 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1613 ui.write("}\n")
1882 ui.write("}\n")
1614
1883
1884 @command('debuginstall', [], '')
1615 def debuginstall(ui):
1885 def debuginstall(ui):
1616 '''test Mercurial installation
1886 '''test Mercurial installation
1617
1887
1618 Returns 0 on success.
1888 Returns 0 on success.
1619 '''
1889 '''
1620
1890
1621 def writetemp(contents):
1891 def writetemp(contents):
1622 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1892 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1623 f = os.fdopen(fd, "wb")
1893 f = os.fdopen(fd, "wb")
1624 f.write(contents)
1894 f.write(contents)
1625 f.close()
1895 f.close()
1626 return name
1896 return name
1627
1897
1628 problems = 0
1898 problems = 0
1629
1899
1630 # encoding
1900 # encoding
1631 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1901 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1632 try:
1902 try:
1633 encoding.fromlocal("test")
1903 encoding.fromlocal("test")
1634 except util.Abort, inst:
1904 except util.Abort, inst:
1635 ui.write(" %s\n" % inst)
1905 ui.write(" %s\n" % inst)
1636 ui.write(_(" (check that your locale is properly set)\n"))
1906 ui.write(_(" (check that your locale is properly set)\n"))
1637 problems += 1
1907 problems += 1
1638
1908
1639 # compiled modules
1909 # compiled modules
1640 ui.status(_("Checking installed modules (%s)...\n")
1910 ui.status(_("Checking installed modules (%s)...\n")
1641 % os.path.dirname(__file__))
1911 % os.path.dirname(__file__))
1642 try:
1912 try:
1643 import bdiff, mpatch, base85, osutil
1913 import bdiff, mpatch, base85, osutil
1644 except Exception, inst:
1914 except Exception, inst:
1645 ui.write(" %s\n" % inst)
1915 ui.write(" %s\n" % inst)
1646 ui.write(_(" One or more extensions could not be found"))
1916 ui.write(_(" One or more extensions could not be found"))
1647 ui.write(_(" (check that you compiled the extensions)\n"))
1917 ui.write(_(" (check that you compiled the extensions)\n"))
1648 problems += 1
1918 problems += 1
1649
1919
1650 # templates
1920 # templates
1651 ui.status(_("Checking templates...\n"))
1921 ui.status(_("Checking templates...\n"))
1652 try:
1922 try:
1653 import templater
1923 import templater
1654 templater.templater(templater.templatepath("map-cmdline.default"))
1924 templater.templater(templater.templatepath("map-cmdline.default"))
1655 except Exception, inst:
1925 except Exception, inst:
1656 ui.write(" %s\n" % inst)
1926 ui.write(" %s\n" % inst)
1657 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1927 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1658 problems += 1
1928 problems += 1
1659
1929
1660 # editor
1930 # editor
1661 ui.status(_("Checking commit editor...\n"))
1931 ui.status(_("Checking commit editor...\n"))
1662 editor = ui.geteditor()
1932 editor = ui.geteditor()
1663 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1933 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1664 if not cmdpath:
1934 if not cmdpath:
1665 if editor == 'vi':
1935 if editor == 'vi':
1666 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1936 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1667 ui.write(_(" (specify a commit editor in your configuration"
1937 ui.write(_(" (specify a commit editor in your configuration"
1668 " file)\n"))
1938 " file)\n"))
1669 else:
1939 else:
1670 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1940 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1671 ui.write(_(" (specify a commit editor in your configuration"
1941 ui.write(_(" (specify a commit editor in your configuration"
1672 " file)\n"))
1942 " file)\n"))
1673 problems += 1
1943 problems += 1
1674
1944
1675 # check username
1945 # check username
1676 ui.status(_("Checking username...\n"))
1946 ui.status(_("Checking username...\n"))
1677 try:
1947 try:
1678 ui.username()
1948 ui.username()
1679 except util.Abort, e:
1949 except util.Abort, e:
1680 ui.write(" %s\n" % e)
1950 ui.write(" %s\n" % e)
1681 ui.write(_(" (specify a username in your configuration file)\n"))
1951 ui.write(_(" (specify a username in your configuration file)\n"))
1682 problems += 1
1952 problems += 1
1683
1953
1684 if not problems:
1954 if not problems:
1685 ui.status(_("No problems detected\n"))
1955 ui.status(_("No problems detected\n"))
1686 else:
1956 else:
1687 ui.write(_("%s problems detected,"
1957 ui.write(_("%s problems detected,"
1688 " please check your install!\n") % problems)
1958 " please check your install!\n") % problems)
1689
1959
1690 return problems
1960 return problems
1691
1961
1962 @command('debugrename',
1963 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1964 _('[-r REV] FILE'))
1692 def debugrename(ui, repo, file1, *pats, **opts):
1965 def debugrename(ui, repo, file1, *pats, **opts):
1693 """dump rename information"""
1966 """dump rename information"""
1694
1967
1695 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1968 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1696 m = cmdutil.match(repo, (file1,) + pats, opts)
1969 m = cmdutil.match(repo, (file1,) + pats, opts)
1697 for abs in ctx.walk(m):
1970 for abs in ctx.walk(m):
1698 fctx = ctx[abs]
1971 fctx = ctx[abs]
1699 o = fctx.filelog().renamed(fctx.filenode())
1972 o = fctx.filelog().renamed(fctx.filenode())
1700 rel = m.rel(abs)
1973 rel = m.rel(abs)
1701 if o:
1974 if o:
1702 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1975 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1703 else:
1976 else:
1704 ui.write(_("%s not renamed\n") % rel)
1977 ui.write(_("%s not renamed\n") % rel)
1705
1978
1979 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
1706 def debugwalk(ui, repo, *pats, **opts):
1980 def debugwalk(ui, repo, *pats, **opts):
1707 """show how files match on given patterns"""
1981 """show how files match on given patterns"""
1708 m = cmdutil.match(repo, pats, opts)
1982 m = cmdutil.match(repo, pats, opts)
1709 items = list(repo.walk(m))
1983 items = list(repo.walk(m))
1710 if not items:
1984 if not items:
1711 return
1985 return
1712 fmt = 'f %%-%ds %%-%ds %%s' % (
1986 fmt = 'f %%-%ds %%-%ds %%s' % (
1713 max([len(abs) for abs in items]),
1987 max([len(abs) for abs in items]),
1714 max([len(m.rel(abs)) for abs in items]))
1988 max([len(m.rel(abs)) for abs in items]))
1715 for abs in items:
1989 for abs in items:
1716 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1990 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1717 ui.write("%s\n" % line.rstrip())
1991 ui.write("%s\n" % line.rstrip())
1718
1992
1993 @command('debugwireargs',
1994 [('', 'three', '', 'three'),
1995 ('', 'four', '', 'four'),
1996 ('', 'five', '', 'five'),
1997 ] + remoteopts,
1998 _('REPO [OPTIONS]... [ONE [TWO]]'))
1719 def debugwireargs(ui, repopath, *vals, **opts):
1999 def debugwireargs(ui, repopath, *vals, **opts):
1720 repo = hg.repository(hg.remoteui(ui, opts), repopath)
2000 repo = hg.repository(hg.remoteui(ui, opts), repopath)
1721 for opt in remoteopts:
2001 for opt in remoteopts:
1722 del opts[opt[1]]
2002 del opts[opt[1]]
1723 args = {}
2003 args = {}
1724 for k, v in opts.iteritems():
2004 for k, v in opts.iteritems():
1725 if v:
2005 if v:
1726 args[k] = v
2006 args[k] = v
1727 # run twice to check that we don't mess up the stream for the next command
2007 # run twice to check that we don't mess up the stream for the next command
1728 res1 = repo.debugwireargs(*vals, **args)
2008 res1 = repo.debugwireargs(*vals, **args)
1729 res2 = repo.debugwireargs(*vals, **args)
2009 res2 = repo.debugwireargs(*vals, **args)
1730 ui.write("%s\n" % res1)
2010 ui.write("%s\n" % res1)
1731 if res1 != res2:
2011 if res1 != res2:
1732 ui.warn("%s\n" % res2)
2012 ui.warn("%s\n" % res2)
1733
2013
2014 @command('^diff',
2015 [('r', 'rev', [], _('revision'), _('REV')),
2016 ('c', 'change', '', _('change made by revision'), _('REV'))
2017 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2018 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
1734 def diff(ui, repo, *pats, **opts):
2019 def diff(ui, repo, *pats, **opts):
1735 """diff repository (or selected files)
2020 """diff repository (or selected files)
1736
2021
1737 Show differences between revisions for the specified files.
2022 Show differences between revisions for the specified files.
1738
2023
1739 Differences between files are shown using the unified diff format.
2024 Differences between files are shown using the unified diff format.
1740
2025
1741 .. note::
2026 .. note::
1742 diff may generate unexpected results for merges, as it will
2027 diff may generate unexpected results for merges, as it will
1743 default to comparing against the working directory's first
2028 default to comparing against the working directory's first
1744 parent changeset if no revisions are specified.
2029 parent changeset if no revisions are specified.
1745
2030
1746 When two revision arguments are given, then changes are shown
2031 When two revision arguments are given, then changes are shown
1747 between those revisions. If only one revision is specified then
2032 between those revisions. If only one revision is specified then
1748 that revision is compared to the working directory, and, when no
2033 that revision is compared to the working directory, and, when no
1749 revisions are specified, the working directory files are compared
2034 revisions are specified, the working directory files are compared
1750 to its parent.
2035 to its parent.
1751
2036
1752 Alternatively you can specify -c/--change with a revision to see
2037 Alternatively you can specify -c/--change with a revision to see
1753 the changes in that changeset relative to its first parent.
2038 the changes in that changeset relative to its first parent.
1754
2039
1755 Without the -a/--text option, diff will avoid generating diffs of
2040 Without the -a/--text option, diff will avoid generating diffs of
1756 files it detects as binary. With -a, diff will generate a diff
2041 files it detects as binary. With -a, diff will generate a diff
1757 anyway, probably with undesirable results.
2042 anyway, probably with undesirable results.
1758
2043
1759 Use the -g/--git option to generate diffs in the git extended diff
2044 Use the -g/--git option to generate diffs in the git extended diff
1760 format. For more information, read :hg:`help diffs`.
2045 format. For more information, read :hg:`help diffs`.
1761
2046
1762 Returns 0 on success.
2047 Returns 0 on success.
1763 """
2048 """
1764
2049
1765 revs = opts.get('rev')
2050 revs = opts.get('rev')
1766 change = opts.get('change')
2051 change = opts.get('change')
1767 stat = opts.get('stat')
2052 stat = opts.get('stat')
1768 reverse = opts.get('reverse')
2053 reverse = opts.get('reverse')
1769
2054
1770 if revs and change:
2055 if revs and change:
1771 msg = _('cannot specify --rev and --change at the same time')
2056 msg = _('cannot specify --rev and --change at the same time')
1772 raise util.Abort(msg)
2057 raise util.Abort(msg)
1773 elif change:
2058 elif change:
1774 node2 = cmdutil.revsingle(repo, change, None).node()
2059 node2 = cmdutil.revsingle(repo, change, None).node()
1775 node1 = repo[node2].p1().node()
2060 node1 = repo[node2].p1().node()
1776 else:
2061 else:
1777 node1, node2 = cmdutil.revpair(repo, revs)
2062 node1, node2 = cmdutil.revpair(repo, revs)
1778
2063
1779 if reverse:
2064 if reverse:
1780 node1, node2 = node2, node1
2065 node1, node2 = node2, node1
1781
2066
1782 diffopts = patch.diffopts(ui, opts)
2067 diffopts = patch.diffopts(ui, opts)
1783 m = cmdutil.match(repo, pats, opts)
2068 m = cmdutil.match(repo, pats, opts)
1784 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2069 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1785 listsubrepos=opts.get('subrepos'))
2070 listsubrepos=opts.get('subrepos'))
1786
2071
2072 @command('^export',
2073 [('o', 'output', '',
2074 _('print output to file with formatted name'), _('FORMAT')),
2075 ('', 'switch-parent', None, _('diff against the second parent')),
2076 ('r', 'rev', [], _('revisions to export'), _('REV')),
2077 ] + diffopts,
2078 _('[OPTION]... [-o OUTFILESPEC] REV...'))
1787 def export(ui, repo, *changesets, **opts):
2079 def export(ui, repo, *changesets, **opts):
1788 """dump the header and diffs for one or more changesets
2080 """dump the header and diffs for one or more changesets
1789
2081
1790 Print the changeset header and diffs for one or more revisions.
2082 Print the changeset header and diffs for one or more revisions.
1791
2083
1792 The information shown in the changeset header is: author, date,
2084 The information shown in the changeset header is: author, date,
1793 branch name (if non-default), changeset hash, parent(s) and commit
2085 branch name (if non-default), changeset hash, parent(s) and commit
1794 comment.
2086 comment.
1795
2087
1796 .. note::
2088 .. note::
1797 export may generate unexpected diff output for merge
2089 export may generate unexpected diff output for merge
1798 changesets, as it will compare the merge changeset against its
2090 changesets, as it will compare the merge changeset against its
1799 first parent only.
2091 first parent only.
1800
2092
1801 Output may be to a file, in which case the name of the file is
2093 Output may be to a file, in which case the name of the file is
1802 given using a format string. The formatting rules are as follows:
2094 given using a format string. The formatting rules are as follows:
1803
2095
1804 :``%%``: literal "%" character
2096 :``%%``: literal "%" character
1805 :``%H``: changeset hash (40 hexadecimal digits)
2097 :``%H``: changeset hash (40 hexadecimal digits)
1806 :``%N``: number of patches being generated
2098 :``%N``: number of patches being generated
1807 :``%R``: changeset revision number
2099 :``%R``: changeset revision number
1808 :``%b``: basename of the exporting repository
2100 :``%b``: basename of the exporting repository
1809 :``%h``: short-form changeset hash (12 hexadecimal digits)
2101 :``%h``: short-form changeset hash (12 hexadecimal digits)
1810 :``%n``: zero-padded sequence number, starting at 1
2102 :``%n``: zero-padded sequence number, starting at 1
1811 :``%r``: zero-padded changeset revision number
2103 :``%r``: zero-padded changeset revision number
1812
2104
1813 Without the -a/--text option, export will avoid generating diffs
2105 Without the -a/--text option, export will avoid generating diffs
1814 of files it detects as binary. With -a, export will generate a
2106 of files it detects as binary. With -a, export will generate a
1815 diff anyway, probably with undesirable results.
2107 diff anyway, probably with undesirable results.
1816
2108
1817 Use the -g/--git option to generate diffs in the git extended diff
2109 Use the -g/--git option to generate diffs in the git extended diff
1818 format. See :hg:`help diffs` for more information.
2110 format. See :hg:`help diffs` for more information.
1819
2111
1820 With the --switch-parent option, the diff will be against the
2112 With the --switch-parent option, the diff will be against the
1821 second parent. It can be useful to review a merge.
2113 second parent. It can be useful to review a merge.
1822
2114
1823 Returns 0 on success.
2115 Returns 0 on success.
1824 """
2116 """
1825 changesets += tuple(opts.get('rev', []))
2117 changesets += tuple(opts.get('rev', []))
1826 if not changesets:
2118 if not changesets:
1827 raise util.Abort(_("export requires at least one changeset"))
2119 raise util.Abort(_("export requires at least one changeset"))
1828 revs = cmdutil.revrange(repo, changesets)
2120 revs = cmdutil.revrange(repo, changesets)
1829 if len(revs) > 1:
2121 if len(revs) > 1:
1830 ui.note(_('exporting patches:\n'))
2122 ui.note(_('exporting patches:\n'))
1831 else:
2123 else:
1832 ui.note(_('exporting patch:\n'))
2124 ui.note(_('exporting patch:\n'))
1833 cmdutil.export(repo, revs, template=opts.get('output'),
2125 cmdutil.export(repo, revs, template=opts.get('output'),
1834 switch_parent=opts.get('switch_parent'),
2126 switch_parent=opts.get('switch_parent'),
1835 opts=patch.diffopts(ui, opts))
2127 opts=patch.diffopts(ui, opts))
1836
2128
2129 @command('^forget', walkopts, _('[OPTION]... FILE...'))
1837 def forget(ui, repo, *pats, **opts):
2130 def forget(ui, repo, *pats, **opts):
1838 """forget the specified files on the next commit
2131 """forget the specified files on the next commit
1839
2132
1840 Mark the specified files so they will no longer be tracked
2133 Mark the specified files so they will no longer be tracked
1841 after the next commit.
2134 after the next commit.
1842
2135
1843 This only removes files from the current branch, not from the
2136 This only removes files from the current branch, not from the
1844 entire project history, and it does not delete them from the
2137 entire project history, and it does not delete them from the
1845 working directory.
2138 working directory.
1846
2139
1847 To undo a forget before the next commit, see :hg:`add`.
2140 To undo a forget before the next commit, see :hg:`add`.
1848
2141
1849 Returns 0 on success.
2142 Returns 0 on success.
1850 """
2143 """
1851
2144
1852 if not pats:
2145 if not pats:
1853 raise util.Abort(_('no files specified'))
2146 raise util.Abort(_('no files specified'))
1854
2147
1855 m = cmdutil.match(repo, pats, opts)
2148 m = cmdutil.match(repo, pats, opts)
1856 s = repo.status(match=m, clean=True)
2149 s = repo.status(match=m, clean=True)
1857 forget = sorted(s[0] + s[1] + s[3] + s[6])
2150 forget = sorted(s[0] + s[1] + s[3] + s[6])
1858 errs = 0
2151 errs = 0
1859
2152
1860 for f in m.files():
2153 for f in m.files():
1861 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2154 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1862 ui.warn(_('not removing %s: file is already untracked\n')
2155 ui.warn(_('not removing %s: file is already untracked\n')
1863 % m.rel(f))
2156 % m.rel(f))
1864 errs = 1
2157 errs = 1
1865
2158
1866 for f in forget:
2159 for f in forget:
1867 if ui.verbose or not m.exact(f):
2160 if ui.verbose or not m.exact(f):
1868 ui.status(_('removing %s\n') % m.rel(f))
2161 ui.status(_('removing %s\n') % m.rel(f))
1869
2162
1870 repo[None].remove(forget, unlink=False)
2163 repo[None].remove(forget, unlink=False)
1871 return errs
2164 return errs
1872
2165
2166 @command('grep',
2167 [('0', 'print0', None, _('end fields with NUL')),
2168 ('', 'all', None, _('print all revisions that match')),
2169 ('a', 'text', None, _('treat all files as text')),
2170 ('f', 'follow', None,
2171 _('follow changeset history,'
2172 ' or file history across copies and renames')),
2173 ('i', 'ignore-case', None, _('ignore case when matching')),
2174 ('l', 'files-with-matches', None,
2175 _('print only filenames and revisions that match')),
2176 ('n', 'line-number', None, _('print matching line numbers')),
2177 ('r', 'rev', [],
2178 _('only search files changed within revision range'), _('REV')),
2179 ('u', 'user', None, _('list the author (long with -v)')),
2180 ('d', 'date', None, _('list the date (short with -q)')),
2181 ] + walkopts,
2182 _('[OPTION]... PATTERN [FILE]...'))
1873 def grep(ui, repo, pattern, *pats, **opts):
2183 def grep(ui, repo, pattern, *pats, **opts):
1874 """search for a pattern in specified files and revisions
2184 """search for a pattern in specified files and revisions
1875
2185
1876 Search revisions of files for a regular expression.
2186 Search revisions of files for a regular expression.
1877
2187
1878 This command behaves differently than Unix grep. It only accepts
2188 This command behaves differently than Unix grep. It only accepts
1879 Python/Perl regexps. It searches repository history, not the
2189 Python/Perl regexps. It searches repository history, not the
1880 working directory. It always prints the revision number in which a
2190 working directory. It always prints the revision number in which a
1881 match appears.
2191 match appears.
1882
2192
1883 By default, grep only prints output for the first revision of a
2193 By default, grep only prints output for the first revision of a
1884 file in which it finds a match. To get it to print every revision
2194 file in which it finds a match. To get it to print every revision
1885 that contains a change in match status ("-" for a match that
2195 that contains a change in match status ("-" for a match that
1886 becomes a non-match, or "+" for a non-match that becomes a match),
2196 becomes a non-match, or "+" for a non-match that becomes a match),
1887 use the --all flag.
2197 use the --all flag.
1888
2198
1889 Returns 0 if a match is found, 1 otherwise.
2199 Returns 0 if a match is found, 1 otherwise.
1890 """
2200 """
1891 reflags = 0
2201 reflags = 0
1892 if opts.get('ignore_case'):
2202 if opts.get('ignore_case'):
1893 reflags |= re.I
2203 reflags |= re.I
1894 try:
2204 try:
1895 regexp = re.compile(pattern, reflags)
2205 regexp = re.compile(pattern, reflags)
1896 except re.error, inst:
2206 except re.error, inst:
1897 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2207 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1898 return 1
2208 return 1
1899 sep, eol = ':', '\n'
2209 sep, eol = ':', '\n'
1900 if opts.get('print0'):
2210 if opts.get('print0'):
1901 sep = eol = '\0'
2211 sep = eol = '\0'
1902
2212
1903 getfile = util.lrucachefunc(repo.file)
2213 getfile = util.lrucachefunc(repo.file)
1904
2214
1905 def matchlines(body):
2215 def matchlines(body):
1906 begin = 0
2216 begin = 0
1907 linenum = 0
2217 linenum = 0
1908 while True:
2218 while True:
1909 match = regexp.search(body, begin)
2219 match = regexp.search(body, begin)
1910 if not match:
2220 if not match:
1911 break
2221 break
1912 mstart, mend = match.span()
2222 mstart, mend = match.span()
1913 linenum += body.count('\n', begin, mstart) + 1
2223 linenum += body.count('\n', begin, mstart) + 1
1914 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2224 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1915 begin = body.find('\n', mend) + 1 or len(body)
2225 begin = body.find('\n', mend) + 1 or len(body)
1916 lend = begin - 1
2226 lend = begin - 1
1917 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2227 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1918
2228
1919 class linestate(object):
2229 class linestate(object):
1920 def __init__(self, line, linenum, colstart, colend):
2230 def __init__(self, line, linenum, colstart, colend):
1921 self.line = line
2231 self.line = line
1922 self.linenum = linenum
2232 self.linenum = linenum
1923 self.colstart = colstart
2233 self.colstart = colstart
1924 self.colend = colend
2234 self.colend = colend
1925
2235
1926 def __hash__(self):
2236 def __hash__(self):
1927 return hash((self.linenum, self.line))
2237 return hash((self.linenum, self.line))
1928
2238
1929 def __eq__(self, other):
2239 def __eq__(self, other):
1930 return self.line == other.line
2240 return self.line == other.line
1931
2241
1932 matches = {}
2242 matches = {}
1933 copies = {}
2243 copies = {}
1934 def grepbody(fn, rev, body):
2244 def grepbody(fn, rev, body):
1935 matches[rev].setdefault(fn, [])
2245 matches[rev].setdefault(fn, [])
1936 m = matches[rev][fn]
2246 m = matches[rev][fn]
1937 for lnum, cstart, cend, line in matchlines(body):
2247 for lnum, cstart, cend, line in matchlines(body):
1938 s = linestate(line, lnum, cstart, cend)
2248 s = linestate(line, lnum, cstart, cend)
1939 m.append(s)
2249 m.append(s)
1940
2250
1941 def difflinestates(a, b):
2251 def difflinestates(a, b):
1942 sm = difflib.SequenceMatcher(None, a, b)
2252 sm = difflib.SequenceMatcher(None, a, b)
1943 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2253 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1944 if tag == 'insert':
2254 if tag == 'insert':
1945 for i in xrange(blo, bhi):
2255 for i in xrange(blo, bhi):
1946 yield ('+', b[i])
2256 yield ('+', b[i])
1947 elif tag == 'delete':
2257 elif tag == 'delete':
1948 for i in xrange(alo, ahi):
2258 for i in xrange(alo, ahi):
1949 yield ('-', a[i])
2259 yield ('-', a[i])
1950 elif tag == 'replace':
2260 elif tag == 'replace':
1951 for i in xrange(alo, ahi):
2261 for i in xrange(alo, ahi):
1952 yield ('-', a[i])
2262 yield ('-', a[i])
1953 for i in xrange(blo, bhi):
2263 for i in xrange(blo, bhi):
1954 yield ('+', b[i])
2264 yield ('+', b[i])
1955
2265
1956 def display(fn, ctx, pstates, states):
2266 def display(fn, ctx, pstates, states):
1957 rev = ctx.rev()
2267 rev = ctx.rev()
1958 datefunc = ui.quiet and util.shortdate or util.datestr
2268 datefunc = ui.quiet and util.shortdate or util.datestr
1959 found = False
2269 found = False
1960 filerevmatches = {}
2270 filerevmatches = {}
1961 def binary():
2271 def binary():
1962 flog = getfile(fn)
2272 flog = getfile(fn)
1963 return util.binary(flog.read(ctx.filenode(fn)))
2273 return util.binary(flog.read(ctx.filenode(fn)))
1964
2274
1965 if opts.get('all'):
2275 if opts.get('all'):
1966 iter = difflinestates(pstates, states)
2276 iter = difflinestates(pstates, states)
1967 else:
2277 else:
1968 iter = [('', l) for l in states]
2278 iter = [('', l) for l in states]
1969 for change, l in iter:
2279 for change, l in iter:
1970 cols = [fn, str(rev)]
2280 cols = [fn, str(rev)]
1971 before, match, after = None, None, None
2281 before, match, after = None, None, None
1972 if opts.get('line_number'):
2282 if opts.get('line_number'):
1973 cols.append(str(l.linenum))
2283 cols.append(str(l.linenum))
1974 if opts.get('all'):
2284 if opts.get('all'):
1975 cols.append(change)
2285 cols.append(change)
1976 if opts.get('user'):
2286 if opts.get('user'):
1977 cols.append(ui.shortuser(ctx.user()))
2287 cols.append(ui.shortuser(ctx.user()))
1978 if opts.get('date'):
2288 if opts.get('date'):
1979 cols.append(datefunc(ctx.date()))
2289 cols.append(datefunc(ctx.date()))
1980 if opts.get('files_with_matches'):
2290 if opts.get('files_with_matches'):
1981 c = (fn, rev)
2291 c = (fn, rev)
1982 if c in filerevmatches:
2292 if c in filerevmatches:
1983 continue
2293 continue
1984 filerevmatches[c] = 1
2294 filerevmatches[c] = 1
1985 else:
2295 else:
1986 before = l.line[:l.colstart]
2296 before = l.line[:l.colstart]
1987 match = l.line[l.colstart:l.colend]
2297 match = l.line[l.colstart:l.colend]
1988 after = l.line[l.colend:]
2298 after = l.line[l.colend:]
1989 ui.write(sep.join(cols))
2299 ui.write(sep.join(cols))
1990 if before is not None:
2300 if before is not None:
1991 if not opts.get('text') and binary():
2301 if not opts.get('text') and binary():
1992 ui.write(sep + " Binary file matches")
2302 ui.write(sep + " Binary file matches")
1993 else:
2303 else:
1994 ui.write(sep + before)
2304 ui.write(sep + before)
1995 ui.write(match, label='grep.match')
2305 ui.write(match, label='grep.match')
1996 ui.write(after)
2306 ui.write(after)
1997 ui.write(eol)
2307 ui.write(eol)
1998 found = True
2308 found = True
1999 return found
2309 return found
2000
2310
2001 skip = {}
2311 skip = {}
2002 revfiles = {}
2312 revfiles = {}
2003 matchfn = cmdutil.match(repo, pats, opts)
2313 matchfn = cmdutil.match(repo, pats, opts)
2004 found = False
2314 found = False
2005 follow = opts.get('follow')
2315 follow = opts.get('follow')
2006
2316
2007 def prep(ctx, fns):
2317 def prep(ctx, fns):
2008 rev = ctx.rev()
2318 rev = ctx.rev()
2009 pctx = ctx.p1()
2319 pctx = ctx.p1()
2010 parent = pctx.rev()
2320 parent = pctx.rev()
2011 matches.setdefault(rev, {})
2321 matches.setdefault(rev, {})
2012 matches.setdefault(parent, {})
2322 matches.setdefault(parent, {})
2013 files = revfiles.setdefault(rev, [])
2323 files = revfiles.setdefault(rev, [])
2014 for fn in fns:
2324 for fn in fns:
2015 flog = getfile(fn)
2325 flog = getfile(fn)
2016 try:
2326 try:
2017 fnode = ctx.filenode(fn)
2327 fnode = ctx.filenode(fn)
2018 except error.LookupError:
2328 except error.LookupError:
2019 continue
2329 continue
2020
2330
2021 copied = flog.renamed(fnode)
2331 copied = flog.renamed(fnode)
2022 copy = follow and copied and copied[0]
2332 copy = follow and copied and copied[0]
2023 if copy:
2333 if copy:
2024 copies.setdefault(rev, {})[fn] = copy
2334 copies.setdefault(rev, {})[fn] = copy
2025 if fn in skip:
2335 if fn in skip:
2026 if copy:
2336 if copy:
2027 skip[copy] = True
2337 skip[copy] = True
2028 continue
2338 continue
2029 files.append(fn)
2339 files.append(fn)
2030
2340
2031 if fn not in matches[rev]:
2341 if fn not in matches[rev]:
2032 grepbody(fn, rev, flog.read(fnode))
2342 grepbody(fn, rev, flog.read(fnode))
2033
2343
2034 pfn = copy or fn
2344 pfn = copy or fn
2035 if pfn not in matches[parent]:
2345 if pfn not in matches[parent]:
2036 try:
2346 try:
2037 fnode = pctx.filenode(pfn)
2347 fnode = pctx.filenode(pfn)
2038 grepbody(pfn, parent, flog.read(fnode))
2348 grepbody(pfn, parent, flog.read(fnode))
2039 except error.LookupError:
2349 except error.LookupError:
2040 pass
2350 pass
2041
2351
2042 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2352 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2043 rev = ctx.rev()
2353 rev = ctx.rev()
2044 parent = ctx.p1().rev()
2354 parent = ctx.p1().rev()
2045 for fn in sorted(revfiles.get(rev, [])):
2355 for fn in sorted(revfiles.get(rev, [])):
2046 states = matches[rev][fn]
2356 states = matches[rev][fn]
2047 copy = copies.get(rev, {}).get(fn)
2357 copy = copies.get(rev, {}).get(fn)
2048 if fn in skip:
2358 if fn in skip:
2049 if copy:
2359 if copy:
2050 skip[copy] = True
2360 skip[copy] = True
2051 continue
2361 continue
2052 pstates = matches.get(parent, {}).get(copy or fn, [])
2362 pstates = matches.get(parent, {}).get(copy or fn, [])
2053 if pstates or states:
2363 if pstates or states:
2054 r = display(fn, ctx, pstates, states)
2364 r = display(fn, ctx, pstates, states)
2055 found = found or r
2365 found = found or r
2056 if r and not opts.get('all'):
2366 if r and not opts.get('all'):
2057 skip[fn] = True
2367 skip[fn] = True
2058 if copy:
2368 if copy:
2059 skip[copy] = True
2369 skip[copy] = True
2060 del matches[rev]
2370 del matches[rev]
2061 del revfiles[rev]
2371 del revfiles[rev]
2062
2372
2063 return not found
2373 return not found
2064
2374
2375 @command('heads',
2376 [('r', 'rev', '',
2377 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2378 ('t', 'topo', False, _('show topological heads only')),
2379 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2380 ('c', 'closed', False, _('show normal and closed branch heads')),
2381 ] + templateopts,
2382 _('[-ac] [-r STARTREV] [REV]...'))
2065 def heads(ui, repo, *branchrevs, **opts):
2383 def heads(ui, repo, *branchrevs, **opts):
2066 """show current repository heads or show branch heads
2384 """show current repository heads or show branch heads
2067
2385
2068 With no arguments, show all repository branch heads.
2386 With no arguments, show all repository branch heads.
2069
2387
2070 Repository "heads" are changesets with no child changesets. They are
2388 Repository "heads" are changesets with no child changesets. They are
2071 where development generally takes place and are the usual targets
2389 where development generally takes place and are the usual targets
2072 for update and merge operations. Branch heads are changesets that have
2390 for update and merge operations. Branch heads are changesets that have
2073 no child changeset on the same branch.
2391 no child changeset on the same branch.
2074
2392
2075 If one or more REVs are given, only branch heads on the branches
2393 If one or more REVs are given, only branch heads on the branches
2076 associated with the specified changesets are shown.
2394 associated with the specified changesets are shown.
2077
2395
2078 If -c/--closed is specified, also show branch heads marked closed
2396 If -c/--closed is specified, also show branch heads marked closed
2079 (see :hg:`commit --close-branch`).
2397 (see :hg:`commit --close-branch`).
2080
2398
2081 If STARTREV is specified, only those heads that are descendants of
2399 If STARTREV is specified, only those heads that are descendants of
2082 STARTREV will be displayed.
2400 STARTREV will be displayed.
2083
2401
2084 If -t/--topo is specified, named branch mechanics will be ignored and only
2402 If -t/--topo is specified, named branch mechanics will be ignored and only
2085 changesets without children will be shown.
2403 changesets without children will be shown.
2086
2404
2087 Returns 0 if matching heads are found, 1 if not.
2405 Returns 0 if matching heads are found, 1 if not.
2088 """
2406 """
2089
2407
2090 start = None
2408 start = None
2091 if 'rev' in opts:
2409 if 'rev' in opts:
2092 start = cmdutil.revsingle(repo, opts['rev'], None).node()
2410 start = cmdutil.revsingle(repo, opts['rev'], None).node()
2093
2411
2094 if opts.get('topo'):
2412 if opts.get('topo'):
2095 heads = [repo[h] for h in repo.heads(start)]
2413 heads = [repo[h] for h in repo.heads(start)]
2096 else:
2414 else:
2097 heads = []
2415 heads = []
2098 for b, ls in repo.branchmap().iteritems():
2416 for b, ls in repo.branchmap().iteritems():
2099 if start is None:
2417 if start is None:
2100 heads += [repo[h] for h in ls]
2418 heads += [repo[h] for h in ls]
2101 continue
2419 continue
2102 startrev = repo.changelog.rev(start)
2420 startrev = repo.changelog.rev(start)
2103 descendants = set(repo.changelog.descendants(startrev))
2421 descendants = set(repo.changelog.descendants(startrev))
2104 descendants.add(startrev)
2422 descendants.add(startrev)
2105 rev = repo.changelog.rev
2423 rev = repo.changelog.rev
2106 heads += [repo[h] for h in ls if rev(h) in descendants]
2424 heads += [repo[h] for h in ls if rev(h) in descendants]
2107
2425
2108 if branchrevs:
2426 if branchrevs:
2109 branches = set(repo[br].branch() for br in branchrevs)
2427 branches = set(repo[br].branch() for br in branchrevs)
2110 heads = [h for h in heads if h.branch() in branches]
2428 heads = [h for h in heads if h.branch() in branches]
2111
2429
2112 if not opts.get('closed'):
2430 if not opts.get('closed'):
2113 heads = [h for h in heads if not h.extra().get('close')]
2431 heads = [h for h in heads if not h.extra().get('close')]
2114
2432
2115 if opts.get('active') and branchrevs:
2433 if opts.get('active') and branchrevs:
2116 dagheads = repo.heads(start)
2434 dagheads = repo.heads(start)
2117 heads = [h for h in heads if h.node() in dagheads]
2435 heads = [h for h in heads if h.node() in dagheads]
2118
2436
2119 if branchrevs:
2437 if branchrevs:
2120 haveheads = set(h.branch() for h in heads)
2438 haveheads = set(h.branch() for h in heads)
2121 if branches - haveheads:
2439 if branches - haveheads:
2122 headless = ', '.join(b for b in branches - haveheads)
2440 headless = ', '.join(b for b in branches - haveheads)
2123 msg = _('no open branch heads found on branches %s')
2441 msg = _('no open branch heads found on branches %s')
2124 if opts.get('rev'):
2442 if opts.get('rev'):
2125 msg += _(' (started at %s)' % opts['rev'])
2443 msg += _(' (started at %s)' % opts['rev'])
2126 ui.warn((msg + '\n') % headless)
2444 ui.warn((msg + '\n') % headless)
2127
2445
2128 if not heads:
2446 if not heads:
2129 return 1
2447 return 1
2130
2448
2131 heads = sorted(heads, key=lambda x: -x.rev())
2449 heads = sorted(heads, key=lambda x: -x.rev())
2132 displayer = cmdutil.show_changeset(ui, repo, opts)
2450 displayer = cmdutil.show_changeset(ui, repo, opts)
2133 for ctx in heads:
2451 for ctx in heads:
2134 displayer.show(ctx)
2452 displayer.show(ctx)
2135 displayer.close()
2453 displayer.close()
2136
2454
2455 @command('help',
2456 [('e', 'extension', None, _('show only help for extensions')),
2457 ('c', 'command', None, _('show only help for commands'))],
2458 _('[-ec] [TOPIC]'))
2137 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2459 def help_(ui, name=None, with_version=False, unknowncmd=False, full=True, **opts):
2138 """show help for a given topic or a help overview
2460 """show help for a given topic or a help overview
2139
2461
2140 With no arguments, print a list of commands with short help messages.
2462 With no arguments, print a list of commands with short help messages.
2141
2463
2142 Given a topic, extension, or command name, print help for that
2464 Given a topic, extension, or command name, print help for that
2143 topic.
2465 topic.
2144
2466
2145 Returns 0 if successful.
2467 Returns 0 if successful.
2146 """
2468 """
2147 option_lists = []
2469 option_lists = []
2148 textwidth = min(ui.termwidth(), 80) - 2
2470 textwidth = min(ui.termwidth(), 80) - 2
2149
2471
2150 def addglobalopts(aliases):
2472 def addglobalopts(aliases):
2151 if ui.verbose:
2473 if ui.verbose:
2152 option_lists.append((_("global options:"), globalopts))
2474 option_lists.append((_("global options:"), globalopts))
2153 if name == 'shortlist':
2475 if name == 'shortlist':
2154 option_lists.append((_('use "hg help" for the full list '
2476 option_lists.append((_('use "hg help" for the full list '
2155 'of commands'), ()))
2477 'of commands'), ()))
2156 else:
2478 else:
2157 if name == 'shortlist':
2479 if name == 'shortlist':
2158 msg = _('use "hg help" for the full list of commands '
2480 msg = _('use "hg help" for the full list of commands '
2159 'or "hg -v" for details')
2481 'or "hg -v" for details')
2160 elif name and not full:
2482 elif name and not full:
2161 msg = _('use "hg help %s" to show the full help text' % name)
2483 msg = _('use "hg help %s" to show the full help text' % name)
2162 elif aliases:
2484 elif aliases:
2163 msg = _('use "hg -v help%s" to show builtin aliases and '
2485 msg = _('use "hg -v help%s" to show builtin aliases and '
2164 'global options') % (name and " " + name or "")
2486 'global options') % (name and " " + name or "")
2165 else:
2487 else:
2166 msg = _('use "hg -v help %s" to show global options') % name
2488 msg = _('use "hg -v help %s" to show global options') % name
2167 option_lists.append((msg, ()))
2489 option_lists.append((msg, ()))
2168
2490
2169 def helpcmd(name):
2491 def helpcmd(name):
2170 if with_version:
2492 if with_version:
2171 version_(ui)
2493 version_(ui)
2172 ui.write('\n')
2494 ui.write('\n')
2173
2495
2174 try:
2496 try:
2175 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2497 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2176 except error.AmbiguousCommand, inst:
2498 except error.AmbiguousCommand, inst:
2177 # py3k fix: except vars can't be used outside the scope of the
2499 # py3k fix: except vars can't be used outside the scope of the
2178 # except block, nor can be used inside a lambda. python issue4617
2500 # except block, nor can be used inside a lambda. python issue4617
2179 prefix = inst.args[0]
2501 prefix = inst.args[0]
2180 select = lambda c: c.lstrip('^').startswith(prefix)
2502 select = lambda c: c.lstrip('^').startswith(prefix)
2181 helplist(_('list of commands:\n\n'), select)
2503 helplist(_('list of commands:\n\n'), select)
2182 return
2504 return
2183
2505
2184 # check if it's an invalid alias and display its error if it is
2506 # check if it's an invalid alias and display its error if it is
2185 if getattr(entry[0], 'badalias', False):
2507 if getattr(entry[0], 'badalias', False):
2186 if not unknowncmd:
2508 if not unknowncmd:
2187 entry[0](ui)
2509 entry[0](ui)
2188 return
2510 return
2189
2511
2190 # synopsis
2512 # synopsis
2191 if len(entry) > 2:
2513 if len(entry) > 2:
2192 if entry[2].startswith('hg'):
2514 if entry[2].startswith('hg'):
2193 ui.write("%s\n" % entry[2])
2515 ui.write("%s\n" % entry[2])
2194 else:
2516 else:
2195 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2517 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2196 else:
2518 else:
2197 ui.write('hg %s\n' % aliases[0])
2519 ui.write('hg %s\n' % aliases[0])
2198
2520
2199 # aliases
2521 # aliases
2200 if full and not ui.quiet and len(aliases) > 1:
2522 if full and not ui.quiet and len(aliases) > 1:
2201 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2523 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2202
2524
2203 # description
2525 # description
2204 doc = gettext(entry[0].__doc__)
2526 doc = gettext(entry[0].__doc__)
2205 if not doc:
2527 if not doc:
2206 doc = _("(no help text available)")
2528 doc = _("(no help text available)")
2207 if hasattr(entry[0], 'definition'): # aliased command
2529 if hasattr(entry[0], 'definition'): # aliased command
2208 if entry[0].definition.startswith('!'): # shell alias
2530 if entry[0].definition.startswith('!'): # shell alias
2209 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2531 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2210 else:
2532 else:
2211 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2533 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2212 if ui.quiet or not full:
2534 if ui.quiet or not full:
2213 doc = doc.splitlines()[0]
2535 doc = doc.splitlines()[0]
2214 keep = ui.verbose and ['verbose'] or []
2536 keep = ui.verbose and ['verbose'] or []
2215 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2537 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2216 ui.write("\n%s\n" % formatted)
2538 ui.write("\n%s\n" % formatted)
2217 if pruned:
2539 if pruned:
2218 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2540 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2219
2541
2220 if not ui.quiet:
2542 if not ui.quiet:
2221 # options
2543 # options
2222 if entry[1]:
2544 if entry[1]:
2223 option_lists.append((_("options:\n"), entry[1]))
2545 option_lists.append((_("options:\n"), entry[1]))
2224
2546
2225 addglobalopts(False)
2547 addglobalopts(False)
2226
2548
2227 # check if this command shadows a non-trivial (multi-line)
2549 # check if this command shadows a non-trivial (multi-line)
2228 # extension help text
2550 # extension help text
2229 try:
2551 try:
2230 mod = extensions.find(name)
2552 mod = extensions.find(name)
2231 doc = gettext(mod.__doc__) or ''
2553 doc = gettext(mod.__doc__) or ''
2232 if '\n' in doc.strip():
2554 if '\n' in doc.strip():
2233 msg = _('use "hg help -e %s" to show help for '
2555 msg = _('use "hg help -e %s" to show help for '
2234 'the %s extension') % (name, name)
2556 'the %s extension') % (name, name)
2235 ui.write('\n%s\n' % msg)
2557 ui.write('\n%s\n' % msg)
2236 except KeyError:
2558 except KeyError:
2237 pass
2559 pass
2238
2560
2239 def helplist(header, select=None):
2561 def helplist(header, select=None):
2240 h = {}
2562 h = {}
2241 cmds = {}
2563 cmds = {}
2242 for c, e in table.iteritems():
2564 for c, e in table.iteritems():
2243 f = c.split("|", 1)[0]
2565 f = c.split("|", 1)[0]
2244 if select and not select(f):
2566 if select and not select(f):
2245 continue
2567 continue
2246 if (not select and name != 'shortlist' and
2568 if (not select and name != 'shortlist' and
2247 e[0].__module__ != __name__):
2569 e[0].__module__ != __name__):
2248 continue
2570 continue
2249 if name == "shortlist" and not f.startswith("^"):
2571 if name == "shortlist" and not f.startswith("^"):
2250 continue
2572 continue
2251 f = f.lstrip("^")
2573 f = f.lstrip("^")
2252 if not ui.debugflag and f.startswith("debug"):
2574 if not ui.debugflag and f.startswith("debug"):
2253 continue
2575 continue
2254 doc = e[0].__doc__
2576 doc = e[0].__doc__
2255 if doc and 'DEPRECATED' in doc and not ui.verbose:
2577 if doc and 'DEPRECATED' in doc and not ui.verbose:
2256 continue
2578 continue
2257 doc = gettext(doc)
2579 doc = gettext(doc)
2258 if not doc:
2580 if not doc:
2259 doc = _("(no help text available)")
2581 doc = _("(no help text available)")
2260 h[f] = doc.splitlines()[0].rstrip()
2582 h[f] = doc.splitlines()[0].rstrip()
2261 cmds[f] = c.lstrip("^")
2583 cmds[f] = c.lstrip("^")
2262
2584
2263 if not h:
2585 if not h:
2264 ui.status(_('no commands defined\n'))
2586 ui.status(_('no commands defined\n'))
2265 return
2587 return
2266
2588
2267 ui.status(header)
2589 ui.status(header)
2268 fns = sorted(h)
2590 fns = sorted(h)
2269 m = max(map(len, fns))
2591 m = max(map(len, fns))
2270 for f in fns:
2592 for f in fns:
2271 if ui.verbose:
2593 if ui.verbose:
2272 commands = cmds[f].replace("|",", ")
2594 commands = cmds[f].replace("|",", ")
2273 ui.write(" %s:\n %s\n"%(commands, h[f]))
2595 ui.write(" %s:\n %s\n"%(commands, h[f]))
2274 else:
2596 else:
2275 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2597 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2276 initindent=' %-*s ' % (m, f),
2598 initindent=' %-*s ' % (m, f),
2277 hangindent=' ' * (m + 4))))
2599 hangindent=' ' * (m + 4))))
2278
2600
2279 if not ui.quiet:
2601 if not ui.quiet:
2280 addglobalopts(True)
2602 addglobalopts(True)
2281
2603
2282 def helptopic(name):
2604 def helptopic(name):
2283 for names, header, doc in help.helptable:
2605 for names, header, doc in help.helptable:
2284 if name in names:
2606 if name in names:
2285 break
2607 break
2286 else:
2608 else:
2287 raise error.UnknownCommand(name)
2609 raise error.UnknownCommand(name)
2288
2610
2289 # description
2611 # description
2290 if not doc:
2612 if not doc:
2291 doc = _("(no help text available)")
2613 doc = _("(no help text available)")
2292 if hasattr(doc, '__call__'):
2614 if hasattr(doc, '__call__'):
2293 doc = doc()
2615 doc = doc()
2294
2616
2295 ui.write("%s\n\n" % header)
2617 ui.write("%s\n\n" % header)
2296 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2618 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2297 try:
2619 try:
2298 cmdutil.findcmd(name, table)
2620 cmdutil.findcmd(name, table)
2299 ui.write(_('\nuse "hg help -c %s" to see help for '
2621 ui.write(_('\nuse "hg help -c %s" to see help for '
2300 'the %s command\n') % (name, name))
2622 'the %s command\n') % (name, name))
2301 except error.UnknownCommand:
2623 except error.UnknownCommand:
2302 pass
2624 pass
2303
2625
2304 def helpext(name):
2626 def helpext(name):
2305 try:
2627 try:
2306 mod = extensions.find(name)
2628 mod = extensions.find(name)
2307 doc = gettext(mod.__doc__) or _('no help text available')
2629 doc = gettext(mod.__doc__) or _('no help text available')
2308 except KeyError:
2630 except KeyError:
2309 mod = None
2631 mod = None
2310 doc = extensions.disabledext(name)
2632 doc = extensions.disabledext(name)
2311 if not doc:
2633 if not doc:
2312 raise error.UnknownCommand(name)
2634 raise error.UnknownCommand(name)
2313
2635
2314 if '\n' not in doc:
2636 if '\n' not in doc:
2315 head, tail = doc, ""
2637 head, tail = doc, ""
2316 else:
2638 else:
2317 head, tail = doc.split('\n', 1)
2639 head, tail = doc.split('\n', 1)
2318 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2640 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2319 if tail:
2641 if tail:
2320 ui.write(minirst.format(tail, textwidth))
2642 ui.write(minirst.format(tail, textwidth))
2321 ui.status('\n\n')
2643 ui.status('\n\n')
2322
2644
2323 if mod:
2645 if mod:
2324 try:
2646 try:
2325 ct = mod.cmdtable
2647 ct = mod.cmdtable
2326 except AttributeError:
2648 except AttributeError:
2327 ct = {}
2649 ct = {}
2328 modcmds = set([c.split('|', 1)[0] for c in ct])
2650 modcmds = set([c.split('|', 1)[0] for c in ct])
2329 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2651 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2330 else:
2652 else:
2331 ui.write(_('use "hg help extensions" for information on enabling '
2653 ui.write(_('use "hg help extensions" for information on enabling '
2332 'extensions\n'))
2654 'extensions\n'))
2333
2655
2334 def helpextcmd(name):
2656 def helpextcmd(name):
2335 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2657 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2336 doc = gettext(mod.__doc__).splitlines()[0]
2658 doc = gettext(mod.__doc__).splitlines()[0]
2337
2659
2338 msg = help.listexts(_("'%s' is provided by the following "
2660 msg = help.listexts(_("'%s' is provided by the following "
2339 "extension:") % cmd, {ext: doc}, len(ext),
2661 "extension:") % cmd, {ext: doc}, len(ext),
2340 indent=4)
2662 indent=4)
2341 ui.write(minirst.format(msg, textwidth))
2663 ui.write(minirst.format(msg, textwidth))
2342 ui.write('\n\n')
2664 ui.write('\n\n')
2343 ui.write(_('use "hg help extensions" for information on enabling '
2665 ui.write(_('use "hg help extensions" for information on enabling '
2344 'extensions\n'))
2666 'extensions\n'))
2345
2667
2346 help.addtopichook('revsets', revset.makedoc)
2668 help.addtopichook('revsets', revset.makedoc)
2347 help.addtopichook('templates', templatekw.makedoc)
2669 help.addtopichook('templates', templatekw.makedoc)
2348 help.addtopichook('templates', templatefilters.makedoc)
2670 help.addtopichook('templates', templatefilters.makedoc)
2349
2671
2350 if name and name != 'shortlist':
2672 if name and name != 'shortlist':
2351 i = None
2673 i = None
2352 if unknowncmd:
2674 if unknowncmd:
2353 queries = (helpextcmd,)
2675 queries = (helpextcmd,)
2354 elif opts.get('extension'):
2676 elif opts.get('extension'):
2355 queries = (helpext,)
2677 queries = (helpext,)
2356 elif opts.get('command'):
2678 elif opts.get('command'):
2357 queries = (helpcmd,)
2679 queries = (helpcmd,)
2358 else:
2680 else:
2359 queries = (helptopic, helpcmd, helpext, helpextcmd)
2681 queries = (helptopic, helpcmd, helpext, helpextcmd)
2360 for f in queries:
2682 for f in queries:
2361 try:
2683 try:
2362 f(name)
2684 f(name)
2363 i = None
2685 i = None
2364 break
2686 break
2365 except error.UnknownCommand, inst:
2687 except error.UnknownCommand, inst:
2366 i = inst
2688 i = inst
2367 if i:
2689 if i:
2368 raise i
2690 raise i
2369
2691
2370 else:
2692 else:
2371 # program name
2693 # program name
2372 if ui.verbose or with_version:
2694 if ui.verbose or with_version:
2373 version_(ui)
2695 version_(ui)
2374 else:
2696 else:
2375 ui.status(_("Mercurial Distributed SCM\n"))
2697 ui.status(_("Mercurial Distributed SCM\n"))
2376 ui.status('\n')
2698 ui.status('\n')
2377
2699
2378 # list of commands
2700 # list of commands
2379 if name == "shortlist":
2701 if name == "shortlist":
2380 header = _('basic commands:\n\n')
2702 header = _('basic commands:\n\n')
2381 else:
2703 else:
2382 header = _('list of commands:\n\n')
2704 header = _('list of commands:\n\n')
2383
2705
2384 helplist(header)
2706 helplist(header)
2385 if name != 'shortlist':
2707 if name != 'shortlist':
2386 exts, maxlength = extensions.enabled()
2708 exts, maxlength = extensions.enabled()
2387 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2709 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2388 if text:
2710 if text:
2389 ui.write("\n%s\n" % minirst.format(text, textwidth))
2711 ui.write("\n%s\n" % minirst.format(text, textwidth))
2390
2712
2391 # list all option lists
2713 # list all option lists
2392 opt_output = []
2714 opt_output = []
2393 multioccur = False
2715 multioccur = False
2394 for title, options in option_lists:
2716 for title, options in option_lists:
2395 opt_output.append(("\n%s" % title, None))
2717 opt_output.append(("\n%s" % title, None))
2396 for option in options:
2718 for option in options:
2397 if len(option) == 5:
2719 if len(option) == 5:
2398 shortopt, longopt, default, desc, optlabel = option
2720 shortopt, longopt, default, desc, optlabel = option
2399 else:
2721 else:
2400 shortopt, longopt, default, desc = option
2722 shortopt, longopt, default, desc = option
2401 optlabel = _("VALUE") # default label
2723 optlabel = _("VALUE") # default label
2402
2724
2403 if _("DEPRECATED") in desc and not ui.verbose:
2725 if _("DEPRECATED") in desc and not ui.verbose:
2404 continue
2726 continue
2405 if isinstance(default, list):
2727 if isinstance(default, list):
2406 numqualifier = " %s [+]" % optlabel
2728 numqualifier = " %s [+]" % optlabel
2407 multioccur = True
2729 multioccur = True
2408 elif (default is not None) and not isinstance(default, bool):
2730 elif (default is not None) and not isinstance(default, bool):
2409 numqualifier = " %s" % optlabel
2731 numqualifier = " %s" % optlabel
2410 else:
2732 else:
2411 numqualifier = ""
2733 numqualifier = ""
2412 opt_output.append(("%2s%s" %
2734 opt_output.append(("%2s%s" %
2413 (shortopt and "-%s" % shortopt,
2735 (shortopt and "-%s" % shortopt,
2414 longopt and " --%s%s" %
2736 longopt and " --%s%s" %
2415 (longopt, numqualifier)),
2737 (longopt, numqualifier)),
2416 "%s%s" % (desc,
2738 "%s%s" % (desc,
2417 default
2739 default
2418 and _(" (default: %s)") % default
2740 and _(" (default: %s)") % default
2419 or "")))
2741 or "")))
2420 if multioccur:
2742 if multioccur:
2421 msg = _("\n[+] marked option can be specified multiple times")
2743 msg = _("\n[+] marked option can be specified multiple times")
2422 if ui.verbose and name != 'shortlist':
2744 if ui.verbose and name != 'shortlist':
2423 opt_output.append((msg, None))
2745 opt_output.append((msg, None))
2424 else:
2746 else:
2425 opt_output.insert(-1, (msg, None))
2747 opt_output.insert(-1, (msg, None))
2426
2748
2427 if not name:
2749 if not name:
2428 ui.write(_("\nadditional help topics:\n\n"))
2750 ui.write(_("\nadditional help topics:\n\n"))
2429 topics = []
2751 topics = []
2430 for names, header, doc in help.helptable:
2752 for names, header, doc in help.helptable:
2431 topics.append((sorted(names, key=len, reverse=True)[0], header))
2753 topics.append((sorted(names, key=len, reverse=True)[0], header))
2432 topics_len = max([len(s[0]) for s in topics])
2754 topics_len = max([len(s[0]) for s in topics])
2433 for t, desc in topics:
2755 for t, desc in topics:
2434 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2756 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2435
2757
2436 if opt_output:
2758 if opt_output:
2437 colwidth = encoding.colwidth
2759 colwidth = encoding.colwidth
2438 # normalize: (opt or message, desc or None, width of opt)
2760 # normalize: (opt or message, desc or None, width of opt)
2439 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2761 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2440 for opt, desc in opt_output]
2762 for opt, desc in opt_output]
2441 hanging = max([e[2] for e in entries])
2763 hanging = max([e[2] for e in entries])
2442 for opt, desc, width in entries:
2764 for opt, desc, width in entries:
2443 if desc:
2765 if desc:
2444 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2766 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2445 hangindent = ' ' * (hanging + 3)
2767 hangindent = ' ' * (hanging + 3)
2446 ui.write('%s\n' % (util.wrap(desc, textwidth,
2768 ui.write('%s\n' % (util.wrap(desc, textwidth,
2447 initindent=initindent,
2769 initindent=initindent,
2448 hangindent=hangindent)))
2770 hangindent=hangindent)))
2449 else:
2771 else:
2450 ui.write("%s\n" % opt)
2772 ui.write("%s\n" % opt)
2451
2773
2774 @command('identify|id',
2775 [('r', 'rev', '',
2776 _('identify the specified revision'), _('REV')),
2777 ('n', 'num', None, _('show local revision number')),
2778 ('i', 'id', None, _('show global revision id')),
2779 ('b', 'branch', None, _('show branch')),
2780 ('t', 'tags', None, _('show tags')),
2781 ('B', 'bookmarks', None, _('show bookmarks'))],
2782 _('[-nibtB] [-r REV] [SOURCE]'))
2452 def identify(ui, repo, source=None, rev=None,
2783 def identify(ui, repo, source=None, rev=None,
2453 num=None, id=None, branch=None, tags=None, bookmarks=None):
2784 num=None, id=None, branch=None, tags=None, bookmarks=None):
2454 """identify the working copy or specified revision
2785 """identify the working copy or specified revision
2455
2786
2456 Print a summary identifying the repository state at REV using one or
2787 Print a summary identifying the repository state at REV using one or
2457 two parent hash identifiers, followed by a "+" if the working
2788 two parent hash identifiers, followed by a "+" if the working
2458 directory has uncommitted changes, the branch name (if not default),
2789 directory has uncommitted changes, the branch name (if not default),
2459 a list of tags, and a list of bookmarks.
2790 a list of tags, and a list of bookmarks.
2460
2791
2461 When REV is not given, print a summary of the current state of the
2792 When REV is not given, print a summary of the current state of the
2462 repository.
2793 repository.
2463
2794
2464 Specifying a path to a repository root or Mercurial bundle will
2795 Specifying a path to a repository root or Mercurial bundle will
2465 cause lookup to operate on that repository/bundle.
2796 cause lookup to operate on that repository/bundle.
2466
2797
2467 Returns 0 if successful.
2798 Returns 0 if successful.
2468 """
2799 """
2469
2800
2470 if not repo and not source:
2801 if not repo and not source:
2471 raise util.Abort(_("there is no Mercurial repository here "
2802 raise util.Abort(_("there is no Mercurial repository here "
2472 "(.hg not found)"))
2803 "(.hg not found)"))
2473
2804
2474 hexfunc = ui.debugflag and hex or short
2805 hexfunc = ui.debugflag and hex or short
2475 default = not (num or id or branch or tags or bookmarks)
2806 default = not (num or id or branch or tags or bookmarks)
2476 output = []
2807 output = []
2477 revs = []
2808 revs = []
2478
2809
2479 if source:
2810 if source:
2480 source, branches = hg.parseurl(ui.expandpath(source))
2811 source, branches = hg.parseurl(ui.expandpath(source))
2481 repo = hg.repository(ui, source)
2812 repo = hg.repository(ui, source)
2482 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2813 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2483
2814
2484 if not repo.local():
2815 if not repo.local():
2485 if num or branch or tags:
2816 if num or branch or tags:
2486 raise util.Abort(
2817 raise util.Abort(
2487 _("can't query remote revision number, branch, or tags"))
2818 _("can't query remote revision number, branch, or tags"))
2488 if not rev and revs:
2819 if not rev and revs:
2489 rev = revs[0]
2820 rev = revs[0]
2490 if not rev:
2821 if not rev:
2491 rev = "tip"
2822 rev = "tip"
2492
2823
2493 remoterev = repo.lookup(rev)
2824 remoterev = repo.lookup(rev)
2494 if default or id:
2825 if default or id:
2495 output = [hexfunc(remoterev)]
2826 output = [hexfunc(remoterev)]
2496
2827
2497 def getbms():
2828 def getbms():
2498 bms = []
2829 bms = []
2499
2830
2500 if 'bookmarks' in repo.listkeys('namespaces'):
2831 if 'bookmarks' in repo.listkeys('namespaces'):
2501 hexremoterev = hex(remoterev)
2832 hexremoterev = hex(remoterev)
2502 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2833 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
2503 if bmr == hexremoterev]
2834 if bmr == hexremoterev]
2504
2835
2505 return bms
2836 return bms
2506
2837
2507 if bookmarks:
2838 if bookmarks:
2508 output.extend(getbms())
2839 output.extend(getbms())
2509 elif default and not ui.quiet:
2840 elif default and not ui.quiet:
2510 # multiple bookmarks for a single parent separated by '/'
2841 # multiple bookmarks for a single parent separated by '/'
2511 bm = '/'.join(getbms())
2842 bm = '/'.join(getbms())
2512 if bm:
2843 if bm:
2513 output.append(bm)
2844 output.append(bm)
2514 else:
2845 else:
2515 if not rev:
2846 if not rev:
2516 ctx = repo[None]
2847 ctx = repo[None]
2517 parents = ctx.parents()
2848 parents = ctx.parents()
2518 changed = ""
2849 changed = ""
2519 if default or id or num:
2850 if default or id or num:
2520 changed = util.any(repo.status()) and "+" or ""
2851 changed = util.any(repo.status()) and "+" or ""
2521 if default or id:
2852 if default or id:
2522 output = ["%s%s" %
2853 output = ["%s%s" %
2523 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2854 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2524 if num:
2855 if num:
2525 output.append("%s%s" %
2856 output.append("%s%s" %
2526 ('+'.join([str(p.rev()) for p in parents]), changed))
2857 ('+'.join([str(p.rev()) for p in parents]), changed))
2527 else:
2858 else:
2528 ctx = cmdutil.revsingle(repo, rev)
2859 ctx = cmdutil.revsingle(repo, rev)
2529 if default or id:
2860 if default or id:
2530 output = [hexfunc(ctx.node())]
2861 output = [hexfunc(ctx.node())]
2531 if num:
2862 if num:
2532 output.append(str(ctx.rev()))
2863 output.append(str(ctx.rev()))
2533
2864
2534 if default and not ui.quiet:
2865 if default and not ui.quiet:
2535 b = ctx.branch()
2866 b = ctx.branch()
2536 if b != 'default':
2867 if b != 'default':
2537 output.append("(%s)" % b)
2868 output.append("(%s)" % b)
2538
2869
2539 # multiple tags for a single parent separated by '/'
2870 # multiple tags for a single parent separated by '/'
2540 t = '/'.join(ctx.tags())
2871 t = '/'.join(ctx.tags())
2541 if t:
2872 if t:
2542 output.append(t)
2873 output.append(t)
2543
2874
2544 # multiple bookmarks for a single parent separated by '/'
2875 # multiple bookmarks for a single parent separated by '/'
2545 bm = '/'.join(ctx.bookmarks())
2876 bm = '/'.join(ctx.bookmarks())
2546 if bm:
2877 if bm:
2547 output.append(bm)
2878 output.append(bm)
2548 else:
2879 else:
2549 if branch:
2880 if branch:
2550 output.append(ctx.branch())
2881 output.append(ctx.branch())
2551
2882
2552 if tags:
2883 if tags:
2553 output.extend(ctx.tags())
2884 output.extend(ctx.tags())
2554
2885
2555 if bookmarks:
2886 if bookmarks:
2556 output.extend(ctx.bookmarks())
2887 output.extend(ctx.bookmarks())
2557
2888
2558 ui.write("%s\n" % ' '.join(output))
2889 ui.write("%s\n" % ' '.join(output))
2559
2890
2891 @command('import|patch',
2892 [('p', 'strip', 1,
2893 _('directory strip option for patch. This has the same '
2894 'meaning as the corresponding patch option'), _('NUM')),
2895 ('b', 'base', '', _('base path'), _('PATH')),
2896 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2897 ('', 'no-commit', None,
2898 _("don't commit, just update the working directory")),
2899 ('', 'exact', None,
2900 _('apply patch to the nodes from which it was generated')),
2901 ('', 'import-branch', None,
2902 _('use any branch information in patch (implied by --exact)'))] +
2903 commitopts + commitopts2 + similarityopts,
2904 _('[OPTION]... PATCH...'))
2560 def import_(ui, repo, patch1, *patches, **opts):
2905 def import_(ui, repo, patch1, *patches, **opts):
2561 """import an ordered set of patches
2906 """import an ordered set of patches
2562
2907
2563 Import a list of patches and commit them individually (unless
2908 Import a list of patches and commit them individually (unless
2564 --no-commit is specified).
2909 --no-commit is specified).
2565
2910
2566 If there are outstanding changes in the working directory, import
2911 If there are outstanding changes in the working directory, import
2567 will abort unless given the -f/--force flag.
2912 will abort unless given the -f/--force flag.
2568
2913
2569 You can import a patch straight from a mail message. Even patches
2914 You can import a patch straight from a mail message. Even patches
2570 as attachments work (to use the body part, it must have type
2915 as attachments work (to use the body part, it must have type
2571 text/plain or text/x-patch). From and Subject headers of email
2916 text/plain or text/x-patch). From and Subject headers of email
2572 message are used as default committer and commit message. All
2917 message are used as default committer and commit message. All
2573 text/plain body parts before first diff are added to commit
2918 text/plain body parts before first diff are added to commit
2574 message.
2919 message.
2575
2920
2576 If the imported patch was generated by :hg:`export`, user and
2921 If the imported patch was generated by :hg:`export`, user and
2577 description from patch override values from message headers and
2922 description from patch override values from message headers and
2578 body. Values given on command line with -m/--message and -u/--user
2923 body. Values given on command line with -m/--message and -u/--user
2579 override these.
2924 override these.
2580
2925
2581 If --exact is specified, import will set the working directory to
2926 If --exact is specified, import will set the working directory to
2582 the parent of each patch before applying it, and will abort if the
2927 the parent of each patch before applying it, and will abort if the
2583 resulting changeset has a different ID than the one recorded in
2928 resulting changeset has a different ID than the one recorded in
2584 the patch. This may happen due to character set problems or other
2929 the patch. This may happen due to character set problems or other
2585 deficiencies in the text patch format.
2930 deficiencies in the text patch format.
2586
2931
2587 With -s/--similarity, hg will attempt to discover renames and
2932 With -s/--similarity, hg will attempt to discover renames and
2588 copies in the patch in the same way as 'addremove'.
2933 copies in the patch in the same way as 'addremove'.
2589
2934
2590 To read a patch from standard input, use "-" as the patch name. If
2935 To read a patch from standard input, use "-" as the patch name. If
2591 a URL is specified, the patch will be downloaded from it.
2936 a URL is specified, the patch will be downloaded from it.
2592 See :hg:`help dates` for a list of formats valid for -d/--date.
2937 See :hg:`help dates` for a list of formats valid for -d/--date.
2593
2938
2594 Returns 0 on success.
2939 Returns 0 on success.
2595 """
2940 """
2596 patches = (patch1,) + patches
2941 patches = (patch1,) + patches
2597
2942
2598 date = opts.get('date')
2943 date = opts.get('date')
2599 if date:
2944 if date:
2600 opts['date'] = util.parsedate(date)
2945 opts['date'] = util.parsedate(date)
2601
2946
2602 try:
2947 try:
2603 sim = float(opts.get('similarity') or 0)
2948 sim = float(opts.get('similarity') or 0)
2604 except ValueError:
2949 except ValueError:
2605 raise util.Abort(_('similarity must be a number'))
2950 raise util.Abort(_('similarity must be a number'))
2606 if sim < 0 or sim > 100:
2951 if sim < 0 or sim > 100:
2607 raise util.Abort(_('similarity must be between 0 and 100'))
2952 raise util.Abort(_('similarity must be between 0 and 100'))
2608
2953
2609 if opts.get('exact') or not opts.get('force'):
2954 if opts.get('exact') or not opts.get('force'):
2610 cmdutil.bailifchanged(repo)
2955 cmdutil.bailifchanged(repo)
2611
2956
2612 d = opts["base"]
2957 d = opts["base"]
2613 strip = opts["strip"]
2958 strip = opts["strip"]
2614 wlock = lock = None
2959 wlock = lock = None
2615 msgs = []
2960 msgs = []
2616
2961
2617 def tryone(ui, hunk):
2962 def tryone(ui, hunk):
2618 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2963 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2619 patch.extract(ui, hunk)
2964 patch.extract(ui, hunk)
2620
2965
2621 if not tmpname:
2966 if not tmpname:
2622 return None
2967 return None
2623 commitid = _('to working directory')
2968 commitid = _('to working directory')
2624
2969
2625 try:
2970 try:
2626 cmdline_message = cmdutil.logmessage(opts)
2971 cmdline_message = cmdutil.logmessage(opts)
2627 if cmdline_message:
2972 if cmdline_message:
2628 # pickup the cmdline msg
2973 # pickup the cmdline msg
2629 message = cmdline_message
2974 message = cmdline_message
2630 elif message:
2975 elif message:
2631 # pickup the patch msg
2976 # pickup the patch msg
2632 message = message.strip()
2977 message = message.strip()
2633 else:
2978 else:
2634 # launch the editor
2979 # launch the editor
2635 message = None
2980 message = None
2636 ui.debug('message:\n%s\n' % message)
2981 ui.debug('message:\n%s\n' % message)
2637
2982
2638 wp = repo.parents()
2983 wp = repo.parents()
2639 if opts.get('exact'):
2984 if opts.get('exact'):
2640 if not nodeid or not p1:
2985 if not nodeid or not p1:
2641 raise util.Abort(_('not a Mercurial patch'))
2986 raise util.Abort(_('not a Mercurial patch'))
2642 p1 = repo.lookup(p1)
2987 p1 = repo.lookup(p1)
2643 p2 = repo.lookup(p2 or hex(nullid))
2988 p2 = repo.lookup(p2 or hex(nullid))
2644
2989
2645 if p1 != wp[0].node():
2990 if p1 != wp[0].node():
2646 hg.clean(repo, p1)
2991 hg.clean(repo, p1)
2647 repo.dirstate.setparents(p1, p2)
2992 repo.dirstate.setparents(p1, p2)
2648 elif p2:
2993 elif p2:
2649 try:
2994 try:
2650 p1 = repo.lookup(p1)
2995 p1 = repo.lookup(p1)
2651 p2 = repo.lookup(p2)
2996 p2 = repo.lookup(p2)
2652 if p1 == wp[0].node():
2997 if p1 == wp[0].node():
2653 repo.dirstate.setparents(p1, p2)
2998 repo.dirstate.setparents(p1, p2)
2654 except error.RepoError:
2999 except error.RepoError:
2655 pass
3000 pass
2656 if opts.get('exact') or opts.get('import_branch'):
3001 if opts.get('exact') or opts.get('import_branch'):
2657 repo.dirstate.setbranch(branch or 'default')
3002 repo.dirstate.setbranch(branch or 'default')
2658
3003
2659 files = {}
3004 files = {}
2660 patch.patch(ui, repo, tmpname, strip=strip, cwd=repo.root,
3005 patch.patch(ui, repo, tmpname, strip=strip, cwd=repo.root,
2661 files=files, eolmode=None, similarity=sim / 100.0)
3006 files=files, eolmode=None, similarity=sim / 100.0)
2662 files = list(files)
3007 files = list(files)
2663 if opts.get('no_commit'):
3008 if opts.get('no_commit'):
2664 if message:
3009 if message:
2665 msgs.append(message)
3010 msgs.append(message)
2666 else:
3011 else:
2667 if opts.get('exact'):
3012 if opts.get('exact'):
2668 m = None
3013 m = None
2669 else:
3014 else:
2670 m = cmdutil.matchfiles(repo, files or [])
3015 m = cmdutil.matchfiles(repo, files or [])
2671 n = repo.commit(message, opts.get('user') or user,
3016 n = repo.commit(message, opts.get('user') or user,
2672 opts.get('date') or date, match=m,
3017 opts.get('date') or date, match=m,
2673 editor=cmdutil.commiteditor)
3018 editor=cmdutil.commiteditor)
2674 if opts.get('exact'):
3019 if opts.get('exact'):
2675 if hex(n) != nodeid:
3020 if hex(n) != nodeid:
2676 repo.rollback()
3021 repo.rollback()
2677 raise util.Abort(_('patch is damaged'
3022 raise util.Abort(_('patch is damaged'
2678 ' or loses information'))
3023 ' or loses information'))
2679 # Force a dirstate write so that the next transaction
3024 # Force a dirstate write so that the next transaction
2680 # backups an up-do-date file.
3025 # backups an up-do-date file.
2681 repo.dirstate.write()
3026 repo.dirstate.write()
2682 if n:
3027 if n:
2683 commitid = short(n)
3028 commitid = short(n)
2684
3029
2685 return commitid
3030 return commitid
2686 finally:
3031 finally:
2687 os.unlink(tmpname)
3032 os.unlink(tmpname)
2688
3033
2689 try:
3034 try:
2690 wlock = repo.wlock()
3035 wlock = repo.wlock()
2691 lock = repo.lock()
3036 lock = repo.lock()
2692 lastcommit = None
3037 lastcommit = None
2693 for p in patches:
3038 for p in patches:
2694 pf = os.path.join(d, p)
3039 pf = os.path.join(d, p)
2695
3040
2696 if pf == '-':
3041 if pf == '-':
2697 ui.status(_("applying patch from stdin\n"))
3042 ui.status(_("applying patch from stdin\n"))
2698 pf = sys.stdin
3043 pf = sys.stdin
2699 else:
3044 else:
2700 ui.status(_("applying %s\n") % p)
3045 ui.status(_("applying %s\n") % p)
2701 pf = url.open(ui, pf)
3046 pf = url.open(ui, pf)
2702
3047
2703 haspatch = False
3048 haspatch = False
2704 for hunk in patch.split(pf):
3049 for hunk in patch.split(pf):
2705 commitid = tryone(ui, hunk)
3050 commitid = tryone(ui, hunk)
2706 if commitid:
3051 if commitid:
2707 haspatch = True
3052 haspatch = True
2708 if lastcommit:
3053 if lastcommit:
2709 ui.status(_('applied %s\n') % lastcommit)
3054 ui.status(_('applied %s\n') % lastcommit)
2710 lastcommit = commitid
3055 lastcommit = commitid
2711
3056
2712 if not haspatch:
3057 if not haspatch:
2713 raise util.Abort(_('no diffs found'))
3058 raise util.Abort(_('no diffs found'))
2714
3059
2715 if msgs:
3060 if msgs:
2716 repo.opener.write('last-message.txt', '\n* * *\n'.join(msgs))
3061 repo.opener.write('last-message.txt', '\n* * *\n'.join(msgs))
2717 finally:
3062 finally:
2718 release(lock, wlock)
3063 release(lock, wlock)
2719
3064
3065 @command('incoming|in',
3066 [('f', 'force', None,
3067 _('run even if remote repository is unrelated')),
3068 ('n', 'newest-first', None, _('show newest record first')),
3069 ('', 'bundle', '',
3070 _('file to store the bundles into'), _('FILE')),
3071 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3072 ('B', 'bookmarks', False, _("compare bookmarks")),
3073 ('b', 'branch', [],
3074 _('a specific branch you would like to pull'), _('BRANCH')),
3075 ] + logopts + remoteopts + subrepoopts,
3076 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
2720 def incoming(ui, repo, source="default", **opts):
3077 def incoming(ui, repo, source="default", **opts):
2721 """show new changesets found in source
3078 """show new changesets found in source
2722
3079
2723 Show new changesets found in the specified path/URL or the default
3080 Show new changesets found in the specified path/URL or the default
2724 pull location. These are the changesets that would have been pulled
3081 pull location. These are the changesets that would have been pulled
2725 if a pull at the time you issued this command.
3082 if a pull at the time you issued this command.
2726
3083
2727 For remote repository, using --bundle avoids downloading the
3084 For remote repository, using --bundle avoids downloading the
2728 changesets twice if the incoming is followed by a pull.
3085 changesets twice if the incoming is followed by a pull.
2729
3086
2730 See pull for valid source format details.
3087 See pull for valid source format details.
2731
3088
2732 Returns 0 if there are incoming changes, 1 otherwise.
3089 Returns 0 if there are incoming changes, 1 otherwise.
2733 """
3090 """
2734 if opts.get('bundle') and opts.get('subrepos'):
3091 if opts.get('bundle') and opts.get('subrepos'):
2735 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3092 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2736
3093
2737 if opts.get('bookmarks'):
3094 if opts.get('bookmarks'):
2738 source, branches = hg.parseurl(ui.expandpath(source),
3095 source, branches = hg.parseurl(ui.expandpath(source),
2739 opts.get('branch'))
3096 opts.get('branch'))
2740 other = hg.repository(hg.remoteui(repo, opts), source)
3097 other = hg.repository(hg.remoteui(repo, opts), source)
2741 if 'bookmarks' not in other.listkeys('namespaces'):
3098 if 'bookmarks' not in other.listkeys('namespaces'):
2742 ui.warn(_("remote doesn't support bookmarks\n"))
3099 ui.warn(_("remote doesn't support bookmarks\n"))
2743 return 0
3100 return 0
2744 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3101 ui.status(_('comparing with %s\n') % util.hidepassword(source))
2745 return bookmarks.diff(ui, repo, other)
3102 return bookmarks.diff(ui, repo, other)
2746
3103
2747 ret = hg.incoming(ui, repo, source, opts)
3104 ret = hg.incoming(ui, repo, source, opts)
2748 return ret
3105 return ret
2749
3106
3107 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
2750 def init(ui, dest=".", **opts):
3108 def init(ui, dest=".", **opts):
2751 """create a new repository in the given directory
3109 """create a new repository in the given directory
2752
3110
2753 Initialize a new repository in the given directory. If the given
3111 Initialize a new repository in the given directory. If the given
2754 directory does not exist, it will be created.
3112 directory does not exist, it will be created.
2755
3113
2756 If no directory is given, the current directory is used.
3114 If no directory is given, the current directory is used.
2757
3115
2758 It is possible to specify an ``ssh://`` URL as the destination.
3116 It is possible to specify an ``ssh://`` URL as the destination.
2759 See :hg:`help urls` for more information.
3117 See :hg:`help urls` for more information.
2760
3118
2761 Returns 0 on success.
3119 Returns 0 on success.
2762 """
3120 """
2763 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
3121 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2764
3122
3123 @command('locate',
3124 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3125 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3126 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3127 ] + walkopts,
3128 _('[OPTION]... [PATTERN]...'))
2765 def locate(ui, repo, *pats, **opts):
3129 def locate(ui, repo, *pats, **opts):
2766 """locate files matching specific patterns
3130 """locate files matching specific patterns
2767
3131
2768 Print files under Mercurial control in the working directory whose
3132 Print files under Mercurial control in the working directory whose
2769 names match the given patterns.
3133 names match the given patterns.
2770
3134
2771 By default, this command searches all directories in the working
3135 By default, this command searches all directories in the working
2772 directory. To search just the current directory and its
3136 directory. To search just the current directory and its
2773 subdirectories, use "--include .".
3137 subdirectories, use "--include .".
2774
3138
2775 If no patterns are given to match, this command prints the names
3139 If no patterns are given to match, this command prints the names
2776 of all files under Mercurial control in the working directory.
3140 of all files under Mercurial control in the working directory.
2777
3141
2778 If you want to feed the output of this command into the "xargs"
3142 If you want to feed the output of this command into the "xargs"
2779 command, use the -0 option to both this command and "xargs". This
3143 command, use the -0 option to both this command and "xargs". This
2780 will avoid the problem of "xargs" treating single filenames that
3144 will avoid the problem of "xargs" treating single filenames that
2781 contain whitespace as multiple filenames.
3145 contain whitespace as multiple filenames.
2782
3146
2783 Returns 0 if a match is found, 1 otherwise.
3147 Returns 0 if a match is found, 1 otherwise.
2784 """
3148 """
2785 end = opts.get('print0') and '\0' or '\n'
3149 end = opts.get('print0') and '\0' or '\n'
2786 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
3150 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2787
3151
2788 ret = 1
3152 ret = 1
2789 m = cmdutil.match(repo, pats, opts, default='relglob')
3153 m = cmdutil.match(repo, pats, opts, default='relglob')
2790 m.bad = lambda x, y: False
3154 m.bad = lambda x, y: False
2791 for abs in repo[rev].walk(m):
3155 for abs in repo[rev].walk(m):
2792 if not rev and abs not in repo.dirstate:
3156 if not rev and abs not in repo.dirstate:
2793 continue
3157 continue
2794 if opts.get('fullpath'):
3158 if opts.get('fullpath'):
2795 ui.write(repo.wjoin(abs), end)
3159 ui.write(repo.wjoin(abs), end)
2796 else:
3160 else:
2797 ui.write(((pats and m.rel(abs)) or abs), end)
3161 ui.write(((pats and m.rel(abs)) or abs), end)
2798 ret = 0
3162 ret = 0
2799
3163
2800 return ret
3164 return ret
2801
3165
3166 @command('^log|history',
3167 [('f', 'follow', None,
3168 _('follow changeset history, or file history across copies and renames')),
3169 ('', 'follow-first', None,
3170 _('only follow the first parent of merge changesets')),
3171 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3172 ('C', 'copies', None, _('show copied files')),
3173 ('k', 'keyword', [],
3174 _('do case-insensitive search for a given text'), _('TEXT')),
3175 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3176 ('', 'removed', None, _('include revisions where files were removed')),
3177 ('m', 'only-merges', None, _('show only merges')),
3178 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3179 ('', 'only-branch', [],
3180 _('show only changesets within the given named branch (DEPRECATED)'),
3181 _('BRANCH')),
3182 ('b', 'branch', [],
3183 _('show changesets within the given named branch'), _('BRANCH')),
3184 ('P', 'prune', [],
3185 _('do not display revision or any of its ancestors'), _('REV')),
3186 ] + logopts + walkopts,
3187 _('[OPTION]... [FILE]'))
2802 def log(ui, repo, *pats, **opts):
3188 def log(ui, repo, *pats, **opts):
2803 """show revision history of entire repository or files
3189 """show revision history of entire repository or files
2804
3190
2805 Print the revision history of the specified files or the entire
3191 Print the revision history of the specified files or the entire
2806 project.
3192 project.
2807
3193
2808 File history is shown without following rename or copy history of
3194 File history is shown without following rename or copy history of
2809 files. Use -f/--follow with a filename to follow history across
3195 files. Use -f/--follow with a filename to follow history across
2810 renames and copies. --follow without a filename will only show
3196 renames and copies. --follow without a filename will only show
2811 ancestors or descendants of the starting revision. --follow-first
3197 ancestors or descendants of the starting revision. --follow-first
2812 only follows the first parent of merge revisions.
3198 only follows the first parent of merge revisions.
2813
3199
2814 If no revision range is specified, the default is ``tip:0`` unless
3200 If no revision range is specified, the default is ``tip:0`` unless
2815 --follow is set, in which case the working directory parent is
3201 --follow is set, in which case the working directory parent is
2816 used as the starting revision. You can specify a revision set for
3202 used as the starting revision. You can specify a revision set for
2817 log, see :hg:`help revsets` for more information.
3203 log, see :hg:`help revsets` for more information.
2818
3204
2819 See :hg:`help dates` for a list of formats valid for -d/--date.
3205 See :hg:`help dates` for a list of formats valid for -d/--date.
2820
3206
2821 By default this command prints revision number and changeset id,
3207 By default this command prints revision number and changeset id,
2822 tags, non-trivial parents, user, date and time, and a summary for
3208 tags, non-trivial parents, user, date and time, and a summary for
2823 each commit. When the -v/--verbose switch is used, the list of
3209 each commit. When the -v/--verbose switch is used, the list of
2824 changed files and full commit message are shown.
3210 changed files and full commit message are shown.
2825
3211
2826 .. note::
3212 .. note::
2827 log -p/--patch may generate unexpected diff output for merge
3213 log -p/--patch may generate unexpected diff output for merge
2828 changesets, as it will only compare the merge changeset against
3214 changesets, as it will only compare the merge changeset against
2829 its first parent. Also, only files different from BOTH parents
3215 its first parent. Also, only files different from BOTH parents
2830 will appear in files:.
3216 will appear in files:.
2831
3217
2832 Returns 0 on success.
3218 Returns 0 on success.
2833 """
3219 """
2834
3220
2835 matchfn = cmdutil.match(repo, pats, opts)
3221 matchfn = cmdutil.match(repo, pats, opts)
2836 limit = cmdutil.loglimit(opts)
3222 limit = cmdutil.loglimit(opts)
2837 count = 0
3223 count = 0
2838
3224
2839 endrev = None
3225 endrev = None
2840 if opts.get('copies') and opts.get('rev'):
3226 if opts.get('copies') and opts.get('rev'):
2841 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
3227 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2842
3228
2843 df = False
3229 df = False
2844 if opts["date"]:
3230 if opts["date"]:
2845 df = util.matchdate(opts["date"])
3231 df = util.matchdate(opts["date"])
2846
3232
2847 branches = opts.get('branch', []) + opts.get('only_branch', [])
3233 branches = opts.get('branch', []) + opts.get('only_branch', [])
2848 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3234 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2849
3235
2850 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3236 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2851 def prep(ctx, fns):
3237 def prep(ctx, fns):
2852 rev = ctx.rev()
3238 rev = ctx.rev()
2853 parents = [p for p in repo.changelog.parentrevs(rev)
3239 parents = [p for p in repo.changelog.parentrevs(rev)
2854 if p != nullrev]
3240 if p != nullrev]
2855 if opts.get('no_merges') and len(parents) == 2:
3241 if opts.get('no_merges') and len(parents) == 2:
2856 return
3242 return
2857 if opts.get('only_merges') and len(parents) != 2:
3243 if opts.get('only_merges') and len(parents) != 2:
2858 return
3244 return
2859 if opts.get('branch') and ctx.branch() not in opts['branch']:
3245 if opts.get('branch') and ctx.branch() not in opts['branch']:
2860 return
3246 return
2861 if df and not df(ctx.date()[0]):
3247 if df and not df(ctx.date()[0]):
2862 return
3248 return
2863 if opts['user'] and not [k for k in opts['user']
3249 if opts['user'] and not [k for k in opts['user']
2864 if k.lower() in ctx.user().lower()]:
3250 if k.lower() in ctx.user().lower()]:
2865 return
3251 return
2866 if opts.get('keyword'):
3252 if opts.get('keyword'):
2867 for k in [kw.lower() for kw in opts['keyword']]:
3253 for k in [kw.lower() for kw in opts['keyword']]:
2868 if (k in ctx.user().lower() or
3254 if (k in ctx.user().lower() or
2869 k in ctx.description().lower() or
3255 k in ctx.description().lower() or
2870 k in " ".join(ctx.files()).lower()):
3256 k in " ".join(ctx.files()).lower()):
2871 break
3257 break
2872 else:
3258 else:
2873 return
3259 return
2874
3260
2875 copies = None
3261 copies = None
2876 if opts.get('copies') and rev:
3262 if opts.get('copies') and rev:
2877 copies = []
3263 copies = []
2878 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3264 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2879 for fn in ctx.files():
3265 for fn in ctx.files():
2880 rename = getrenamed(fn, rev)
3266 rename = getrenamed(fn, rev)
2881 if rename:
3267 if rename:
2882 copies.append((fn, rename[0]))
3268 copies.append((fn, rename[0]))
2883
3269
2884 revmatchfn = None
3270 revmatchfn = None
2885 if opts.get('patch') or opts.get('stat'):
3271 if opts.get('patch') or opts.get('stat'):
2886 if opts.get('follow') or opts.get('follow_first'):
3272 if opts.get('follow') or opts.get('follow_first'):
2887 # note: this might be wrong when following through merges
3273 # note: this might be wrong when following through merges
2888 revmatchfn = cmdutil.match(repo, fns, default='path')
3274 revmatchfn = cmdutil.match(repo, fns, default='path')
2889 else:
3275 else:
2890 revmatchfn = matchfn
3276 revmatchfn = matchfn
2891
3277
2892 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3278 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2893
3279
2894 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3280 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2895 if count == limit:
3281 if count == limit:
2896 break
3282 break
2897 if displayer.flush(ctx.rev()):
3283 if displayer.flush(ctx.rev()):
2898 count += 1
3284 count += 1
2899 displayer.close()
3285 displayer.close()
2900
3286
3287 @command('manifest',
3288 [('r', 'rev', '', _('revision to display'), _('REV'))],
3289 _('[-r REV]'))
2901 def manifest(ui, repo, node=None, rev=None):
3290 def manifest(ui, repo, node=None, rev=None):
2902 """output the current or given revision of the project manifest
3291 """output the current or given revision of the project manifest
2903
3292
2904 Print a list of version controlled files for the given revision.
3293 Print a list of version controlled files for the given revision.
2905 If no revision is given, the first parent of the working directory
3294 If no revision is given, the first parent of the working directory
2906 is used, or the null revision if no revision is checked out.
3295 is used, or the null revision if no revision is checked out.
2907
3296
2908 With -v, print file permissions, symlink and executable bits.
3297 With -v, print file permissions, symlink and executable bits.
2909 With --debug, print file revision hashes.
3298 With --debug, print file revision hashes.
2910
3299
2911 Returns 0 on success.
3300 Returns 0 on success.
2912 """
3301 """
2913
3302
2914 if rev and node:
3303 if rev and node:
2915 raise util.Abort(_("please specify just one revision"))
3304 raise util.Abort(_("please specify just one revision"))
2916
3305
2917 if not node:
3306 if not node:
2918 node = rev
3307 node = rev
2919
3308
2920 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3309 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2921 ctx = cmdutil.revsingle(repo, node)
3310 ctx = cmdutil.revsingle(repo, node)
2922 for f in ctx:
3311 for f in ctx:
2923 if ui.debugflag:
3312 if ui.debugflag:
2924 ui.write("%40s " % hex(ctx.manifest()[f]))
3313 ui.write("%40s " % hex(ctx.manifest()[f]))
2925 if ui.verbose:
3314 if ui.verbose:
2926 ui.write(decor[ctx.flags(f)])
3315 ui.write(decor[ctx.flags(f)])
2927 ui.write("%s\n" % f)
3316 ui.write("%s\n" % f)
2928
3317
3318 @command('^merge',
3319 [('f', 'force', None, _('force a merge with outstanding changes')),
3320 ('t', 'tool', '', _('specify merge tool')),
3321 ('r', 'rev', '', _('revision to merge'), _('REV')),
3322 ('P', 'preview', None,
3323 _('review revisions to merge (no merge is performed)'))],
3324 _('[-P] [-f] [[-r] REV]'))
2929 def merge(ui, repo, node=None, **opts):
3325 def merge(ui, repo, node=None, **opts):
2930 """merge working directory with another revision
3326 """merge working directory with another revision
2931
3327
2932 The current working directory is updated with all changes made in
3328 The current working directory is updated with all changes made in
2933 the requested revision since the last common predecessor revision.
3329 the requested revision since the last common predecessor revision.
2934
3330
2935 Files that changed between either parent are marked as changed for
3331 Files that changed between either parent are marked as changed for
2936 the next commit and a commit must be performed before any further
3332 the next commit and a commit must be performed before any further
2937 updates to the repository are allowed. The next commit will have
3333 updates to the repository are allowed. The next commit will have
2938 two parents.
3334 two parents.
2939
3335
2940 ``--tool`` can be used to specify the merge tool used for file
3336 ``--tool`` can be used to specify the merge tool used for file
2941 merges. It overrides the HGMERGE environment variable and your
3337 merges. It overrides the HGMERGE environment variable and your
2942 configuration files. See :hg:`help merge-tools` for options.
3338 configuration files. See :hg:`help merge-tools` for options.
2943
3339
2944 If no revision is specified, the working directory's parent is a
3340 If no revision is specified, the working directory's parent is a
2945 head revision, and the current branch contains exactly one other
3341 head revision, and the current branch contains exactly one other
2946 head, the other head is merged with by default. Otherwise, an
3342 head, the other head is merged with by default. Otherwise, an
2947 explicit revision with which to merge with must be provided.
3343 explicit revision with which to merge with must be provided.
2948
3344
2949 :hg:`resolve` must be used to resolve unresolved files.
3345 :hg:`resolve` must be used to resolve unresolved files.
2950
3346
2951 To undo an uncommitted merge, use :hg:`update --clean .` which
3347 To undo an uncommitted merge, use :hg:`update --clean .` which
2952 will check out a clean copy of the original merge parent, losing
3348 will check out a clean copy of the original merge parent, losing
2953 all changes.
3349 all changes.
2954
3350
2955 Returns 0 on success, 1 if there are unresolved files.
3351 Returns 0 on success, 1 if there are unresolved files.
2956 """
3352 """
2957
3353
2958 if opts.get('rev') and node:
3354 if opts.get('rev') and node:
2959 raise util.Abort(_("please specify just one revision"))
3355 raise util.Abort(_("please specify just one revision"))
2960 if not node:
3356 if not node:
2961 node = opts.get('rev')
3357 node = opts.get('rev')
2962
3358
2963 if not node:
3359 if not node:
2964 branch = repo[None].branch()
3360 branch = repo[None].branch()
2965 bheads = repo.branchheads(branch)
3361 bheads = repo.branchheads(branch)
2966 if len(bheads) > 2:
3362 if len(bheads) > 2:
2967 raise util.Abort(_("branch '%s' has %d heads - "
3363 raise util.Abort(_("branch '%s' has %d heads - "
2968 "please merge with an explicit rev")
3364 "please merge with an explicit rev")
2969 % (branch, len(bheads)),
3365 % (branch, len(bheads)),
2970 hint=_("run 'hg heads .' to see heads"))
3366 hint=_("run 'hg heads .' to see heads"))
2971
3367
2972 parent = repo.dirstate.p1()
3368 parent = repo.dirstate.p1()
2973 if len(bheads) == 1:
3369 if len(bheads) == 1:
2974 if len(repo.heads()) > 1:
3370 if len(repo.heads()) > 1:
2975 raise util.Abort(_("branch '%s' has one head - "
3371 raise util.Abort(_("branch '%s' has one head - "
2976 "please merge with an explicit rev")
3372 "please merge with an explicit rev")
2977 % branch,
3373 % branch,
2978 hint=_("run 'hg heads' to see all heads"))
3374 hint=_("run 'hg heads' to see all heads"))
2979 msg = _('there is nothing to merge')
3375 msg = _('there is nothing to merge')
2980 if parent != repo.lookup(repo[None].branch()):
3376 if parent != repo.lookup(repo[None].branch()):
2981 msg = _('%s - use "hg update" instead') % msg
3377 msg = _('%s - use "hg update" instead') % msg
2982 raise util.Abort(msg)
3378 raise util.Abort(msg)
2983
3379
2984 if parent not in bheads:
3380 if parent not in bheads:
2985 raise util.Abort(_('working directory not at a head revision'),
3381 raise util.Abort(_('working directory not at a head revision'),
2986 hint=_("use 'hg update' or merge with an "
3382 hint=_("use 'hg update' or merge with an "
2987 "explicit revision"))
3383 "explicit revision"))
2988 node = parent == bheads[0] and bheads[-1] or bheads[0]
3384 node = parent == bheads[0] and bheads[-1] or bheads[0]
2989 else:
3385 else:
2990 node = cmdutil.revsingle(repo, node).node()
3386 node = cmdutil.revsingle(repo, node).node()
2991
3387
2992 if opts.get('preview'):
3388 if opts.get('preview'):
2993 # find nodes that are ancestors of p2 but not of p1
3389 # find nodes that are ancestors of p2 but not of p1
2994 p1 = repo.lookup('.')
3390 p1 = repo.lookup('.')
2995 p2 = repo.lookup(node)
3391 p2 = repo.lookup(node)
2996 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3392 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2997
3393
2998 displayer = cmdutil.show_changeset(ui, repo, opts)
3394 displayer = cmdutil.show_changeset(ui, repo, opts)
2999 for node in nodes:
3395 for node in nodes:
3000 displayer.show(repo[node])
3396 displayer.show(repo[node])
3001 displayer.close()
3397 displayer.close()
3002 return 0
3398 return 0
3003
3399
3004 try:
3400 try:
3005 # ui.forcemerge is an internal variable, do not document
3401 # ui.forcemerge is an internal variable, do not document
3006 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3402 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3007 return hg.merge(repo, node, force=opts.get('force'))
3403 return hg.merge(repo, node, force=opts.get('force'))
3008 finally:
3404 finally:
3009 ui.setconfig('ui', 'forcemerge', '')
3405 ui.setconfig('ui', 'forcemerge', '')
3010
3406
3407 @command('outgoing|out',
3408 [('f', 'force', None, _('run even when the destination is unrelated')),
3409 ('r', 'rev', [],
3410 _('a changeset intended to be included in the destination'), _('REV')),
3411 ('n', 'newest-first', None, _('show newest record first')),
3412 ('B', 'bookmarks', False, _('compare bookmarks')),
3413 ('b', 'branch', [], _('a specific branch you would like to push'),
3414 _('BRANCH')),
3415 ] + logopts + remoteopts + subrepoopts,
3416 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3011 def outgoing(ui, repo, dest=None, **opts):
3417 def outgoing(ui, repo, dest=None, **opts):
3012 """show changesets not found in the destination
3418 """show changesets not found in the destination
3013
3419
3014 Show changesets not found in the specified destination repository
3420 Show changesets not found in the specified destination repository
3015 or the default push location. These are the changesets that would
3421 or the default push location. These are the changesets that would
3016 be pushed if a push was requested.
3422 be pushed if a push was requested.
3017
3423
3018 See pull for details of valid destination formats.
3424 See pull for details of valid destination formats.
3019
3425
3020 Returns 0 if there are outgoing changes, 1 otherwise.
3426 Returns 0 if there are outgoing changes, 1 otherwise.
3021 """
3427 """
3022
3428
3023 if opts.get('bookmarks'):
3429 if opts.get('bookmarks'):
3024 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3430 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3025 dest, branches = hg.parseurl(dest, opts.get('branch'))
3431 dest, branches = hg.parseurl(dest, opts.get('branch'))
3026 other = hg.repository(hg.remoteui(repo, opts), dest)
3432 other = hg.repository(hg.remoteui(repo, opts), dest)
3027 if 'bookmarks' not in other.listkeys('namespaces'):
3433 if 'bookmarks' not in other.listkeys('namespaces'):
3028 ui.warn(_("remote doesn't support bookmarks\n"))
3434 ui.warn(_("remote doesn't support bookmarks\n"))
3029 return 0
3435 return 0
3030 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3436 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3031 return bookmarks.diff(ui, other, repo)
3437 return bookmarks.diff(ui, other, repo)
3032
3438
3033 ret = hg.outgoing(ui, repo, dest, opts)
3439 ret = hg.outgoing(ui, repo, dest, opts)
3034 return ret
3440 return ret
3035
3441
3442 @command('parents',
3443 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3444 ] + templateopts,
3445 _('[-r REV] [FILE]'))
3036 def parents(ui, repo, file_=None, **opts):
3446 def parents(ui, repo, file_=None, **opts):
3037 """show the parents of the working directory or revision
3447 """show the parents of the working directory or revision
3038
3448
3039 Print the working directory's parent revisions. If a revision is
3449 Print the working directory's parent revisions. If a revision is
3040 given via -r/--rev, the parent of that revision will be printed.
3450 given via -r/--rev, the parent of that revision will be printed.
3041 If a file argument is given, the revision in which the file was
3451 If a file argument is given, the revision in which the file was
3042 last changed (before the working directory revision or the
3452 last changed (before the working directory revision or the
3043 argument to --rev if given) is printed.
3453 argument to --rev if given) is printed.
3044
3454
3045 Returns 0 on success.
3455 Returns 0 on success.
3046 """
3456 """
3047
3457
3048 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
3458 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
3049
3459
3050 if file_:
3460 if file_:
3051 m = cmdutil.match(repo, (file_,), opts)
3461 m = cmdutil.match(repo, (file_,), opts)
3052 if m.anypats() or len(m.files()) != 1:
3462 if m.anypats() or len(m.files()) != 1:
3053 raise util.Abort(_('can only specify an explicit filename'))
3463 raise util.Abort(_('can only specify an explicit filename'))
3054 file_ = m.files()[0]
3464 file_ = m.files()[0]
3055 filenodes = []
3465 filenodes = []
3056 for cp in ctx.parents():
3466 for cp in ctx.parents():
3057 if not cp:
3467 if not cp:
3058 continue
3468 continue
3059 try:
3469 try:
3060 filenodes.append(cp.filenode(file_))
3470 filenodes.append(cp.filenode(file_))
3061 except error.LookupError:
3471 except error.LookupError:
3062 pass
3472 pass
3063 if not filenodes:
3473 if not filenodes:
3064 raise util.Abort(_("'%s' not found in manifest!") % file_)
3474 raise util.Abort(_("'%s' not found in manifest!") % file_)
3065 fl = repo.file(file_)
3475 fl = repo.file(file_)
3066 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3476 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3067 else:
3477 else:
3068 p = [cp.node() for cp in ctx.parents()]
3478 p = [cp.node() for cp in ctx.parents()]
3069
3479
3070 displayer = cmdutil.show_changeset(ui, repo, opts)
3480 displayer = cmdutil.show_changeset(ui, repo, opts)
3071 for n in p:
3481 for n in p:
3072 if n != nullid:
3482 if n != nullid:
3073 displayer.show(repo[n])
3483 displayer.show(repo[n])
3074 displayer.close()
3484 displayer.close()
3075
3485
3486 @command('paths', [], _('[NAME]'))
3076 def paths(ui, repo, search=None):
3487 def paths(ui, repo, search=None):
3077 """show aliases for remote repositories
3488 """show aliases for remote repositories
3078
3489
3079 Show definition of symbolic path name NAME. If no name is given,
3490 Show definition of symbolic path name NAME. If no name is given,
3080 show definition of all available names.
3491 show definition of all available names.
3081
3492
3082 Path names are defined in the [paths] section of your
3493 Path names are defined in the [paths] section of your
3083 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3494 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3084 repository, ``.hg/hgrc`` is used, too.
3495 repository, ``.hg/hgrc`` is used, too.
3085
3496
3086 The path names ``default`` and ``default-push`` have a special
3497 The path names ``default`` and ``default-push`` have a special
3087 meaning. When performing a push or pull operation, they are used
3498 meaning. When performing a push or pull operation, they are used
3088 as fallbacks if no location is specified on the command-line.
3499 as fallbacks if no location is specified on the command-line.
3089 When ``default-push`` is set, it will be used for push and
3500 When ``default-push`` is set, it will be used for push and
3090 ``default`` will be used for pull; otherwise ``default`` is used
3501 ``default`` will be used for pull; otherwise ``default`` is used
3091 as the fallback for both. When cloning a repository, the clone
3502 as the fallback for both. When cloning a repository, the clone
3092 source is written as ``default`` in ``.hg/hgrc``. Note that
3503 source is written as ``default`` in ``.hg/hgrc``. Note that
3093 ``default`` and ``default-push`` apply to all inbound (e.g.
3504 ``default`` and ``default-push`` apply to all inbound (e.g.
3094 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3505 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3095 :hg:`bundle`) operations.
3506 :hg:`bundle`) operations.
3096
3507
3097 See :hg:`help urls` for more information.
3508 See :hg:`help urls` for more information.
3098
3509
3099 Returns 0 on success.
3510 Returns 0 on success.
3100 """
3511 """
3101 if search:
3512 if search:
3102 for name, path in ui.configitems("paths"):
3513 for name, path in ui.configitems("paths"):
3103 if name == search:
3514 if name == search:
3104 ui.write("%s\n" % util.hidepassword(path))
3515 ui.write("%s\n" % util.hidepassword(path))
3105 return
3516 return
3106 ui.warn(_("not found!\n"))
3517 ui.warn(_("not found!\n"))
3107 return 1
3518 return 1
3108 else:
3519 else:
3109 for name, path in ui.configitems("paths"):
3520 for name, path in ui.configitems("paths"):
3110 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3521 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3111
3522
3112 def postincoming(ui, repo, modheads, optupdate, checkout):
3523 def postincoming(ui, repo, modheads, optupdate, checkout):
3113 if modheads == 0:
3524 if modheads == 0:
3114 return
3525 return
3115 if optupdate:
3526 if optupdate:
3116 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
3527 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
3117 return hg.update(repo, checkout)
3528 return hg.update(repo, checkout)
3118 else:
3529 else:
3119 ui.status(_("not updating, since new heads added\n"))
3530 ui.status(_("not updating, since new heads added\n"))
3120 if modheads > 1:
3531 if modheads > 1:
3121 currentbranchheads = len(repo.branchheads())
3532 currentbranchheads = len(repo.branchheads())
3122 if currentbranchheads == modheads:
3533 if currentbranchheads == modheads:
3123 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3534 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3124 elif currentbranchheads > 1:
3535 elif currentbranchheads > 1:
3125 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3536 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3126 else:
3537 else:
3127 ui.status(_("(run 'hg heads' to see heads)\n"))
3538 ui.status(_("(run 'hg heads' to see heads)\n"))
3128 else:
3539 else:
3129 ui.status(_("(run 'hg update' to get a working copy)\n"))
3540 ui.status(_("(run 'hg update' to get a working copy)\n"))
3130
3541
3542 @command('^pull',
3543 [('u', 'update', None,
3544 _('update to new branch head if changesets were pulled')),
3545 ('f', 'force', None, _('run even when remote repository is unrelated')),
3546 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3547 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3548 ('b', 'branch', [], _('a specific branch you would like to pull'),
3549 _('BRANCH')),
3550 ] + remoteopts,
3551 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3131 def pull(ui, repo, source="default", **opts):
3552 def pull(ui, repo, source="default", **opts):
3132 """pull changes from the specified source
3553 """pull changes from the specified source
3133
3554
3134 Pull changes from a remote repository to a local one.
3555 Pull changes from a remote repository to a local one.
3135
3556
3136 This finds all changes from the repository at the specified path
3557 This finds all changes from the repository at the specified path
3137 or URL and adds them to a local repository (the current one unless
3558 or URL and adds them to a local repository (the current one unless
3138 -R is specified). By default, this does not update the copy of the
3559 -R is specified). By default, this does not update the copy of the
3139 project in the working directory.
3560 project in the working directory.
3140
3561
3141 Use :hg:`incoming` if you want to see what would have been added
3562 Use :hg:`incoming` if you want to see what would have been added
3142 by a pull at the time you issued this command. If you then decide
3563 by a pull at the time you issued this command. If you then decide
3143 to add those changes to the repository, you should use :hg:`pull
3564 to add those changes to the repository, you should use :hg:`pull
3144 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3565 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3145
3566
3146 If SOURCE is omitted, the 'default' path will be used.
3567 If SOURCE is omitted, the 'default' path will be used.
3147 See :hg:`help urls` for more information.
3568 See :hg:`help urls` for more information.
3148
3569
3149 Returns 0 on success, 1 if an update had unresolved files.
3570 Returns 0 on success, 1 if an update had unresolved files.
3150 """
3571 """
3151 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3572 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3152 other = hg.repository(hg.remoteui(repo, opts), source)
3573 other = hg.repository(hg.remoteui(repo, opts), source)
3153 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3574 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3154 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3575 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3155
3576
3156 if opts.get('bookmark'):
3577 if opts.get('bookmark'):
3157 if not revs:
3578 if not revs:
3158 revs = []
3579 revs = []
3159 rb = other.listkeys('bookmarks')
3580 rb = other.listkeys('bookmarks')
3160 for b in opts['bookmark']:
3581 for b in opts['bookmark']:
3161 if b not in rb:
3582 if b not in rb:
3162 raise util.Abort(_('remote bookmark %s not found!') % b)
3583 raise util.Abort(_('remote bookmark %s not found!') % b)
3163 revs.append(rb[b])
3584 revs.append(rb[b])
3164
3585
3165 if revs:
3586 if revs:
3166 try:
3587 try:
3167 revs = [other.lookup(rev) for rev in revs]
3588 revs = [other.lookup(rev) for rev in revs]
3168 except error.CapabilityError:
3589 except error.CapabilityError:
3169 err = _("other repository doesn't support revision lookup, "
3590 err = _("other repository doesn't support revision lookup, "
3170 "so a rev cannot be specified.")
3591 "so a rev cannot be specified.")
3171 raise util.Abort(err)
3592 raise util.Abort(err)
3172
3593
3173 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3594 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3174 bookmarks.updatefromremote(ui, repo, other)
3595 bookmarks.updatefromremote(ui, repo, other)
3175 if checkout:
3596 if checkout:
3176 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3597 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3177 repo._subtoppath = source
3598 repo._subtoppath = source
3178 try:
3599 try:
3179 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3600 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3180
3601
3181 finally:
3602 finally:
3182 del repo._subtoppath
3603 del repo._subtoppath
3183
3604
3184 # update specified bookmarks
3605 # update specified bookmarks
3185 if opts.get('bookmark'):
3606 if opts.get('bookmark'):
3186 for b in opts['bookmark']:
3607 for b in opts['bookmark']:
3187 # explicit pull overrides local bookmark if any
3608 # explicit pull overrides local bookmark if any
3188 ui.status(_("importing bookmark %s\n") % b)
3609 ui.status(_("importing bookmark %s\n") % b)
3189 repo._bookmarks[b] = repo[rb[b]].node()
3610 repo._bookmarks[b] = repo[rb[b]].node()
3190 bookmarks.write(repo)
3611 bookmarks.write(repo)
3191
3612
3192 return ret
3613 return ret
3193
3614
3615 @command('^push',
3616 [('f', 'force', None, _('force push')),
3617 ('r', 'rev', [],
3618 _('a changeset intended to be included in the destination'),
3619 _('REV')),
3620 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
3621 ('b', 'branch', [],
3622 _('a specific branch you would like to push'), _('BRANCH')),
3623 ('', 'new-branch', False, _('allow pushing a new branch')),
3624 ] + remoteopts,
3625 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
3194 def push(ui, repo, dest=None, **opts):
3626 def push(ui, repo, dest=None, **opts):
3195 """push changes to the specified destination
3627 """push changes to the specified destination
3196
3628
3197 Push changesets from the local repository to the specified
3629 Push changesets from the local repository to the specified
3198 destination.
3630 destination.
3199
3631
3200 This operation is symmetrical to pull: it is identical to a pull
3632 This operation is symmetrical to pull: it is identical to a pull
3201 in the destination repository from the current one.
3633 in the destination repository from the current one.
3202
3634
3203 By default, push will not allow creation of new heads at the
3635 By default, push will not allow creation of new heads at the
3204 destination, since multiple heads would make it unclear which head
3636 destination, since multiple heads would make it unclear which head
3205 to use. In this situation, it is recommended to pull and merge
3637 to use. In this situation, it is recommended to pull and merge
3206 before pushing.
3638 before pushing.
3207
3639
3208 Use --new-branch if you want to allow push to create a new named
3640 Use --new-branch if you want to allow push to create a new named
3209 branch that is not present at the destination. This allows you to
3641 branch that is not present at the destination. This allows you to
3210 only create a new branch without forcing other changes.
3642 only create a new branch without forcing other changes.
3211
3643
3212 Use -f/--force to override the default behavior and push all
3644 Use -f/--force to override the default behavior and push all
3213 changesets on all branches.
3645 changesets on all branches.
3214
3646
3215 If -r/--rev is used, the specified revision and all its ancestors
3647 If -r/--rev is used, the specified revision and all its ancestors
3216 will be pushed to the remote repository.
3648 will be pushed to the remote repository.
3217
3649
3218 Please see :hg:`help urls` for important details about ``ssh://``
3650 Please see :hg:`help urls` for important details about ``ssh://``
3219 URLs. If DESTINATION is omitted, a default path will be used.
3651 URLs. If DESTINATION is omitted, a default path will be used.
3220
3652
3221 Returns 0 if push was successful, 1 if nothing to push.
3653 Returns 0 if push was successful, 1 if nothing to push.
3222 """
3654 """
3223
3655
3224 if opts.get('bookmark'):
3656 if opts.get('bookmark'):
3225 for b in opts['bookmark']:
3657 for b in opts['bookmark']:
3226 # translate -B options to -r so changesets get pushed
3658 # translate -B options to -r so changesets get pushed
3227 if b in repo._bookmarks:
3659 if b in repo._bookmarks:
3228 opts.setdefault('rev', []).append(b)
3660 opts.setdefault('rev', []).append(b)
3229 else:
3661 else:
3230 # if we try to push a deleted bookmark, translate it to null
3662 # if we try to push a deleted bookmark, translate it to null
3231 # this lets simultaneous -r, -b options continue working
3663 # this lets simultaneous -r, -b options continue working
3232 opts.setdefault('rev', []).append("null")
3664 opts.setdefault('rev', []).append("null")
3233
3665
3234 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3666 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3235 dest, branches = hg.parseurl(dest, opts.get('branch'))
3667 dest, branches = hg.parseurl(dest, opts.get('branch'))
3236 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3668 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3237 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3669 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3238 other = hg.repository(hg.remoteui(repo, opts), dest)
3670 other = hg.repository(hg.remoteui(repo, opts), dest)
3239 if revs:
3671 if revs:
3240 revs = [repo.lookup(rev) for rev in revs]
3672 revs = [repo.lookup(rev) for rev in revs]
3241
3673
3242 repo._subtoppath = dest
3674 repo._subtoppath = dest
3243 try:
3675 try:
3244 # push subrepos depth-first for coherent ordering
3676 # push subrepos depth-first for coherent ordering
3245 c = repo['']
3677 c = repo['']
3246 subs = c.substate # only repos that are committed
3678 subs = c.substate # only repos that are committed
3247 for s in sorted(subs):
3679 for s in sorted(subs):
3248 if not c.sub(s).push(opts.get('force')):
3680 if not c.sub(s).push(opts.get('force')):
3249 return False
3681 return False
3250 finally:
3682 finally:
3251 del repo._subtoppath
3683 del repo._subtoppath
3252 result = repo.push(other, opts.get('force'), revs=revs,
3684 result = repo.push(other, opts.get('force'), revs=revs,
3253 newbranch=opts.get('new_branch'))
3685 newbranch=opts.get('new_branch'))
3254
3686
3255 result = (result == 0)
3687 result = (result == 0)
3256
3688
3257 if opts.get('bookmark'):
3689 if opts.get('bookmark'):
3258 rb = other.listkeys('bookmarks')
3690 rb = other.listkeys('bookmarks')
3259 for b in opts['bookmark']:
3691 for b in opts['bookmark']:
3260 # explicit push overrides remote bookmark if any
3692 # explicit push overrides remote bookmark if any
3261 if b in repo._bookmarks:
3693 if b in repo._bookmarks:
3262 ui.status(_("exporting bookmark %s\n") % b)
3694 ui.status(_("exporting bookmark %s\n") % b)
3263 new = repo[b].hex()
3695 new = repo[b].hex()
3264 elif b in rb:
3696 elif b in rb:
3265 ui.status(_("deleting remote bookmark %s\n") % b)
3697 ui.status(_("deleting remote bookmark %s\n") % b)
3266 new = '' # delete
3698 new = '' # delete
3267 else:
3699 else:
3268 ui.warn(_('bookmark %s does not exist on the local '
3700 ui.warn(_('bookmark %s does not exist on the local '
3269 'or remote repository!\n') % b)
3701 'or remote repository!\n') % b)
3270 return 2
3702 return 2
3271 old = rb.get(b, '')
3703 old = rb.get(b, '')
3272 r = other.pushkey('bookmarks', b, old, new)
3704 r = other.pushkey('bookmarks', b, old, new)
3273 if not r:
3705 if not r:
3274 ui.warn(_('updating bookmark %s failed!\n') % b)
3706 ui.warn(_('updating bookmark %s failed!\n') % b)
3275 if not result:
3707 if not result:
3276 result = 2
3708 result = 2
3277
3709
3278 return result
3710 return result
3279
3711
3712 @command('recover', [])
3280 def recover(ui, repo):
3713 def recover(ui, repo):
3281 """roll back an interrupted transaction
3714 """roll back an interrupted transaction
3282
3715
3283 Recover from an interrupted commit or pull.
3716 Recover from an interrupted commit or pull.
3284
3717
3285 This command tries to fix the repository status after an
3718 This command tries to fix the repository status after an
3286 interrupted operation. It should only be necessary when Mercurial
3719 interrupted operation. It should only be necessary when Mercurial
3287 suggests it.
3720 suggests it.
3288
3721
3289 Returns 0 if successful, 1 if nothing to recover or verify fails.
3722 Returns 0 if successful, 1 if nothing to recover or verify fails.
3290 """
3723 """
3291 if repo.recover():
3724 if repo.recover():
3292 return hg.verify(repo)
3725 return hg.verify(repo)
3293 return 1
3726 return 1
3294
3727
3728 @command('^remove|rm',
3729 [('A', 'after', None, _('record delete for missing files')),
3730 ('f', 'force', None,
3731 _('remove (and delete) file even if added or modified')),
3732 ] + walkopts,
3733 _('[OPTION]... FILE...'))
3295 def remove(ui, repo, *pats, **opts):
3734 def remove(ui, repo, *pats, **opts):
3296 """remove the specified files on the next commit
3735 """remove the specified files on the next commit
3297
3736
3298 Schedule the indicated files for removal from the repository.
3737 Schedule the indicated files for removal from the repository.
3299
3738
3300 This only removes files from the current branch, not from the
3739 This only removes files from the current branch, not from the
3301 entire project history. -A/--after can be used to remove only
3740 entire project history. -A/--after can be used to remove only
3302 files that have already been deleted, -f/--force can be used to
3741 files that have already been deleted, -f/--force can be used to
3303 force deletion, and -Af can be used to remove files from the next
3742 force deletion, and -Af can be used to remove files from the next
3304 revision without deleting them from the working directory.
3743 revision without deleting them from the working directory.
3305
3744
3306 The following table details the behavior of remove for different
3745 The following table details the behavior of remove for different
3307 file states (columns) and option combinations (rows). The file
3746 file states (columns) and option combinations (rows). The file
3308 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3747 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3309 reported by :hg:`status`). The actions are Warn, Remove (from
3748 reported by :hg:`status`). The actions are Warn, Remove (from
3310 branch) and Delete (from disk)::
3749 branch) and Delete (from disk)::
3311
3750
3312 A C M !
3751 A C M !
3313 none W RD W R
3752 none W RD W R
3314 -f R RD RD R
3753 -f R RD RD R
3315 -A W W W R
3754 -A W W W R
3316 -Af R R R R
3755 -Af R R R R
3317
3756
3318 This command schedules the files to be removed at the next commit.
3757 This command schedules the files to be removed at the next commit.
3319 To undo a remove before that, see :hg:`revert`.
3758 To undo a remove before that, see :hg:`revert`.
3320
3759
3321 Returns 0 on success, 1 if any warnings encountered.
3760 Returns 0 on success, 1 if any warnings encountered.
3322 """
3761 """
3323
3762
3324 ret = 0
3763 ret = 0
3325 after, force = opts.get('after'), opts.get('force')
3764 after, force = opts.get('after'), opts.get('force')
3326 if not pats and not after:
3765 if not pats and not after:
3327 raise util.Abort(_('no files specified'))
3766 raise util.Abort(_('no files specified'))
3328
3767
3329 m = cmdutil.match(repo, pats, opts)
3768 m = cmdutil.match(repo, pats, opts)
3330 s = repo.status(match=m, clean=True)
3769 s = repo.status(match=m, clean=True)
3331 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3770 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3332
3771
3333 for f in m.files():
3772 for f in m.files():
3334 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3773 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3335 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3774 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3336 ret = 1
3775 ret = 1
3337
3776
3338 if force:
3777 if force:
3339 remove, forget = modified + deleted + clean, added
3778 remove, forget = modified + deleted + clean, added
3340 elif after:
3779 elif after:
3341 remove, forget = deleted, []
3780 remove, forget = deleted, []
3342 for f in modified + added + clean:
3781 for f in modified + added + clean:
3343 ui.warn(_('not removing %s: file still exists (use -f'
3782 ui.warn(_('not removing %s: file still exists (use -f'
3344 ' to force removal)\n') % m.rel(f))
3783 ' to force removal)\n') % m.rel(f))
3345 ret = 1
3784 ret = 1
3346 else:
3785 else:
3347 remove, forget = deleted + clean, []
3786 remove, forget = deleted + clean, []
3348 for f in modified:
3787 for f in modified:
3349 ui.warn(_('not removing %s: file is modified (use -f'
3788 ui.warn(_('not removing %s: file is modified (use -f'
3350 ' to force removal)\n') % m.rel(f))
3789 ' to force removal)\n') % m.rel(f))
3351 ret = 1
3790 ret = 1
3352 for f in added:
3791 for f in added:
3353 ui.warn(_('not removing %s: file has been marked for add (use -f'
3792 ui.warn(_('not removing %s: file has been marked for add (use -f'
3354 ' to force removal)\n') % m.rel(f))
3793 ' to force removal)\n') % m.rel(f))
3355 ret = 1
3794 ret = 1
3356
3795
3357 for f in sorted(remove + forget):
3796 for f in sorted(remove + forget):
3358 if ui.verbose or not m.exact(f):
3797 if ui.verbose or not m.exact(f):
3359 ui.status(_('removing %s\n') % m.rel(f))
3798 ui.status(_('removing %s\n') % m.rel(f))
3360
3799
3361 repo[None].forget(forget)
3800 repo[None].forget(forget)
3362 repo[None].remove(remove, unlink=not after)
3801 repo[None].remove(remove, unlink=not after)
3363 return ret
3802 return ret
3364
3803
3804 @command('rename|move|mv',
3805 [('A', 'after', None, _('record a rename that has already occurred')),
3806 ('f', 'force', None, _('forcibly copy over an existing managed file')),
3807 ] + walkopts + dryrunopts,
3808 _('[OPTION]... SOURCE... DEST'))
3365 def rename(ui, repo, *pats, **opts):
3809 def rename(ui, repo, *pats, **opts):
3366 """rename files; equivalent of copy + remove
3810 """rename files; equivalent of copy + remove
3367
3811
3368 Mark dest as copies of sources; mark sources for deletion. If dest
3812 Mark dest as copies of sources; mark sources for deletion. If dest
3369 is a directory, copies are put in that directory. If dest is a
3813 is a directory, copies are put in that directory. If dest is a
3370 file, there can only be one source.
3814 file, there can only be one source.
3371
3815
3372 By default, this command copies the contents of files as they
3816 By default, this command copies the contents of files as they
3373 exist in the working directory. If invoked with -A/--after, the
3817 exist in the working directory. If invoked with -A/--after, the
3374 operation is recorded, but no copying is performed.
3818 operation is recorded, but no copying is performed.
3375
3819
3376 This command takes effect at the next commit. To undo a rename
3820 This command takes effect at the next commit. To undo a rename
3377 before that, see :hg:`revert`.
3821 before that, see :hg:`revert`.
3378
3822
3379 Returns 0 on success, 1 if errors are encountered.
3823 Returns 0 on success, 1 if errors are encountered.
3380 """
3824 """
3381 wlock = repo.wlock(False)
3825 wlock = repo.wlock(False)
3382 try:
3826 try:
3383 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3827 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3384 finally:
3828 finally:
3385 wlock.release()
3829 wlock.release()
3386
3830
3831 @command('resolve',
3832 [('a', 'all', None, _('select all unresolved files')),
3833 ('l', 'list', None, _('list state of files needing merge')),
3834 ('m', 'mark', None, _('mark files as resolved')),
3835 ('u', 'unmark', None, _('mark files as unresolved')),
3836 ('t', 'tool', '', _('specify merge tool')),
3837 ('n', 'no-status', None, _('hide status prefix'))]
3838 + walkopts,
3839 _('[OPTION]... [FILE]...'))
3387 def resolve(ui, repo, *pats, **opts):
3840 def resolve(ui, repo, *pats, **opts):
3388 """redo merges or set/view the merge status of files
3841 """redo merges or set/view the merge status of files
3389
3842
3390 Merges with unresolved conflicts are often the result of
3843 Merges with unresolved conflicts are often the result of
3391 non-interactive merging using the ``internal:merge`` configuration
3844 non-interactive merging using the ``internal:merge`` configuration
3392 setting, or a command-line merge tool like ``diff3``. The resolve
3845 setting, or a command-line merge tool like ``diff3``. The resolve
3393 command is used to manage the files involved in a merge, after
3846 command is used to manage the files involved in a merge, after
3394 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3847 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3395 working directory must have two parents).
3848 working directory must have two parents).
3396
3849
3397 The resolve command can be used in the following ways:
3850 The resolve command can be used in the following ways:
3398
3851
3399 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3852 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3400 files, discarding any previous merge attempts. Re-merging is not
3853 files, discarding any previous merge attempts. Re-merging is not
3401 performed for files already marked as resolved. Use ``--all/-a``
3854 performed for files already marked as resolved. Use ``--all/-a``
3402 to selects all unresolved files. ``--tool`` can be used to specify
3855 to selects all unresolved files. ``--tool`` can be used to specify
3403 the merge tool used for the given files. It overrides the HGMERGE
3856 the merge tool used for the given files. It overrides the HGMERGE
3404 environment variable and your configuration files.
3857 environment variable and your configuration files.
3405
3858
3406 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3859 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3407 (e.g. after having manually fixed-up the files). The default is
3860 (e.g. after having manually fixed-up the files). The default is
3408 to mark all unresolved files.
3861 to mark all unresolved files.
3409
3862
3410 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3863 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3411 default is to mark all resolved files.
3864 default is to mark all resolved files.
3412
3865
3413 - :hg:`resolve -l`: list files which had or still have conflicts.
3866 - :hg:`resolve -l`: list files which had or still have conflicts.
3414 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3867 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3415
3868
3416 Note that Mercurial will not let you commit files with unresolved
3869 Note that Mercurial will not let you commit files with unresolved
3417 merge conflicts. You must use :hg:`resolve -m ...` before you can
3870 merge conflicts. You must use :hg:`resolve -m ...` before you can
3418 commit after a conflicting merge.
3871 commit after a conflicting merge.
3419
3872
3420 Returns 0 on success, 1 if any files fail a resolve attempt.
3873 Returns 0 on success, 1 if any files fail a resolve attempt.
3421 """
3874 """
3422
3875
3423 all, mark, unmark, show, nostatus = \
3876 all, mark, unmark, show, nostatus = \
3424 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3877 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3425
3878
3426 if (show and (mark or unmark)) or (mark and unmark):
3879 if (show and (mark or unmark)) or (mark and unmark):
3427 raise util.Abort(_("too many options specified"))
3880 raise util.Abort(_("too many options specified"))
3428 if pats and all:
3881 if pats and all:
3429 raise util.Abort(_("can't specify --all and patterns"))
3882 raise util.Abort(_("can't specify --all and patterns"))
3430 if not (all or pats or show or mark or unmark):
3883 if not (all or pats or show or mark or unmark):
3431 raise util.Abort(_('no files or directories specified; '
3884 raise util.Abort(_('no files or directories specified; '
3432 'use --all to remerge all files'))
3885 'use --all to remerge all files'))
3433
3886
3434 ms = mergemod.mergestate(repo)
3887 ms = mergemod.mergestate(repo)
3435 m = cmdutil.match(repo, pats, opts)
3888 m = cmdutil.match(repo, pats, opts)
3436 ret = 0
3889 ret = 0
3437
3890
3438 for f in ms:
3891 for f in ms:
3439 if m(f):
3892 if m(f):
3440 if show:
3893 if show:
3441 if nostatus:
3894 if nostatus:
3442 ui.write("%s\n" % f)
3895 ui.write("%s\n" % f)
3443 else:
3896 else:
3444 ui.write("%s %s\n" % (ms[f].upper(), f),
3897 ui.write("%s %s\n" % (ms[f].upper(), f),
3445 label='resolve.' +
3898 label='resolve.' +
3446 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3899 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3447 elif mark:
3900 elif mark:
3448 ms.mark(f, "r")
3901 ms.mark(f, "r")
3449 elif unmark:
3902 elif unmark:
3450 ms.mark(f, "u")
3903 ms.mark(f, "u")
3451 else:
3904 else:
3452 wctx = repo[None]
3905 wctx = repo[None]
3453 mctx = wctx.parents()[-1]
3906 mctx = wctx.parents()[-1]
3454
3907
3455 # backup pre-resolve (merge uses .orig for its own purposes)
3908 # backup pre-resolve (merge uses .orig for its own purposes)
3456 a = repo.wjoin(f)
3909 a = repo.wjoin(f)
3457 util.copyfile(a, a + ".resolve")
3910 util.copyfile(a, a + ".resolve")
3458
3911
3459 try:
3912 try:
3460 # resolve file
3913 # resolve file
3461 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3914 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3462 if ms.resolve(f, wctx, mctx):
3915 if ms.resolve(f, wctx, mctx):
3463 ret = 1
3916 ret = 1
3464 finally:
3917 finally:
3465 ui.setconfig('ui', 'forcemerge', '')
3918 ui.setconfig('ui', 'forcemerge', '')
3466
3919
3467 # replace filemerge's .orig file with our resolve file
3920 # replace filemerge's .orig file with our resolve file
3468 util.rename(a + ".resolve", a + ".orig")
3921 util.rename(a + ".resolve", a + ".orig")
3469
3922
3470 ms.commit()
3923 ms.commit()
3471 return ret
3924 return ret
3472
3925
3926 @command('revert',
3927 [('a', 'all', None, _('revert all changes when no arguments given')),
3928 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
3929 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
3930 ('', 'no-backup', None, _('do not save backup copies of files')),
3931 ] + walkopts + dryrunopts,
3932 _('[OPTION]... [-r REV] [NAME]...'))
3473 def revert(ui, repo, *pats, **opts):
3933 def revert(ui, repo, *pats, **opts):
3474 """restore individual files or directories to an earlier state
3934 """restore individual files or directories to an earlier state
3475
3935
3476 .. note::
3936 .. note::
3477 This command is most likely not what you are looking for.
3937 This command is most likely not what you are looking for.
3478 Revert will partially overwrite content in the working
3938 Revert will partially overwrite content in the working
3479 directory without changing the working directory parents. Use
3939 directory without changing the working directory parents. Use
3480 :hg:`update -r rev` to check out earlier revisions, or
3940 :hg:`update -r rev` to check out earlier revisions, or
3481 :hg:`update --clean .` to undo a merge which has added another
3941 :hg:`update --clean .` to undo a merge which has added another
3482 parent.
3942 parent.
3483
3943
3484 With no revision specified, revert the named files or directories
3944 With no revision specified, revert the named files or directories
3485 to the contents they had in the parent of the working directory.
3945 to the contents they had in the parent of the working directory.
3486 This restores the contents of the affected files to an unmodified
3946 This restores the contents of the affected files to an unmodified
3487 state and unschedules adds, removes, copies, and renames. If the
3947 state and unschedules adds, removes, copies, and renames. If the
3488 working directory has two parents, you must explicitly specify a
3948 working directory has two parents, you must explicitly specify a
3489 revision.
3949 revision.
3490
3950
3491 Using the -r/--rev option, revert the given files or directories
3951 Using the -r/--rev option, revert the given files or directories
3492 to their contents as of a specific revision. This can be helpful
3952 to their contents as of a specific revision. This can be helpful
3493 to "roll back" some or all of an earlier change. See :hg:`help
3953 to "roll back" some or all of an earlier change. See :hg:`help
3494 dates` for a list of formats valid for -d/--date.
3954 dates` for a list of formats valid for -d/--date.
3495
3955
3496 Revert modifies the working directory. It does not commit any
3956 Revert modifies the working directory. It does not commit any
3497 changes, or change the parent of the working directory. If you
3957 changes, or change the parent of the working directory. If you
3498 revert to a revision other than the parent of the working
3958 revert to a revision other than the parent of the working
3499 directory, the reverted files will thus appear modified
3959 directory, the reverted files will thus appear modified
3500 afterwards.
3960 afterwards.
3501
3961
3502 If a file has been deleted, it is restored. Files scheduled for
3962 If a file has been deleted, it is restored. Files scheduled for
3503 addition are just unscheduled and left as they are. If the
3963 addition are just unscheduled and left as they are. If the
3504 executable mode of a file was changed, it is reset.
3964 executable mode of a file was changed, it is reset.
3505
3965
3506 If names are given, all files matching the names are reverted.
3966 If names are given, all files matching the names are reverted.
3507 If no arguments are given, no files are reverted.
3967 If no arguments are given, no files are reverted.
3508
3968
3509 Modified files are saved with a .orig suffix before reverting.
3969 Modified files are saved with a .orig suffix before reverting.
3510 To disable these backups, use --no-backup.
3970 To disable these backups, use --no-backup.
3511
3971
3512 Returns 0 on success.
3972 Returns 0 on success.
3513 """
3973 """
3514
3974
3515 if opts.get("date"):
3975 if opts.get("date"):
3516 if opts.get("rev"):
3976 if opts.get("rev"):
3517 raise util.Abort(_("you can't specify a revision and a date"))
3977 raise util.Abort(_("you can't specify a revision and a date"))
3518 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3978 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3519
3979
3520 parent, p2 = repo.dirstate.parents()
3980 parent, p2 = repo.dirstate.parents()
3521 if not opts.get('rev') and p2 != nullid:
3981 if not opts.get('rev') and p2 != nullid:
3522 raise util.Abort(_('uncommitted merge - '
3982 raise util.Abort(_('uncommitted merge - '
3523 'use "hg update", see "hg help revert"'))
3983 'use "hg update", see "hg help revert"'))
3524
3984
3525 if not pats and not opts.get('all'):
3985 if not pats and not opts.get('all'):
3526 raise util.Abort(_('no files or directories specified; '
3986 raise util.Abort(_('no files or directories specified; '
3527 'use --all to revert the whole repo'))
3987 'use --all to revert the whole repo'))
3528
3988
3529 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3989 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3530 node = ctx.node()
3990 node = ctx.node()
3531 mf = ctx.manifest()
3991 mf = ctx.manifest()
3532 if node == parent:
3992 if node == parent:
3533 pmf = mf
3993 pmf = mf
3534 else:
3994 else:
3535 pmf = None
3995 pmf = None
3536
3996
3537 # need all matching names in dirstate and manifest of target rev,
3997 # need all matching names in dirstate and manifest of target rev,
3538 # so have to walk both. do not print errors if files exist in one
3998 # so have to walk both. do not print errors if files exist in one
3539 # but not other.
3999 # but not other.
3540
4000
3541 names = {}
4001 names = {}
3542
4002
3543 wlock = repo.wlock()
4003 wlock = repo.wlock()
3544 try:
4004 try:
3545 # walk dirstate.
4005 # walk dirstate.
3546
4006
3547 m = cmdutil.match(repo, pats, opts)
4007 m = cmdutil.match(repo, pats, opts)
3548 m.bad = lambda x, y: False
4008 m.bad = lambda x, y: False
3549 for abs in repo.walk(m):
4009 for abs in repo.walk(m):
3550 names[abs] = m.rel(abs), m.exact(abs)
4010 names[abs] = m.rel(abs), m.exact(abs)
3551
4011
3552 # walk target manifest.
4012 # walk target manifest.
3553
4013
3554 def badfn(path, msg):
4014 def badfn(path, msg):
3555 if path in names:
4015 if path in names:
3556 return
4016 return
3557 path_ = path + '/'
4017 path_ = path + '/'
3558 for f in names:
4018 for f in names:
3559 if f.startswith(path_):
4019 if f.startswith(path_):
3560 return
4020 return
3561 ui.warn("%s: %s\n" % (m.rel(path), msg))
4021 ui.warn("%s: %s\n" % (m.rel(path), msg))
3562
4022
3563 m = cmdutil.match(repo, pats, opts)
4023 m = cmdutil.match(repo, pats, opts)
3564 m.bad = badfn
4024 m.bad = badfn
3565 for abs in repo[node].walk(m):
4025 for abs in repo[node].walk(m):
3566 if abs not in names:
4026 if abs not in names:
3567 names[abs] = m.rel(abs), m.exact(abs)
4027 names[abs] = m.rel(abs), m.exact(abs)
3568
4028
3569 m = cmdutil.matchfiles(repo, names)
4029 m = cmdutil.matchfiles(repo, names)
3570 changes = repo.status(match=m)[:4]
4030 changes = repo.status(match=m)[:4]
3571 modified, added, removed, deleted = map(set, changes)
4031 modified, added, removed, deleted = map(set, changes)
3572
4032
3573 # if f is a rename, also revert the source
4033 # if f is a rename, also revert the source
3574 cwd = repo.getcwd()
4034 cwd = repo.getcwd()
3575 for f in added:
4035 for f in added:
3576 src = repo.dirstate.copied(f)
4036 src = repo.dirstate.copied(f)
3577 if src and src not in names and repo.dirstate[src] == 'r':
4037 if src and src not in names and repo.dirstate[src] == 'r':
3578 removed.add(src)
4038 removed.add(src)
3579 names[src] = (repo.pathto(src, cwd), True)
4039 names[src] = (repo.pathto(src, cwd), True)
3580
4040
3581 def removeforget(abs):
4041 def removeforget(abs):
3582 if repo.dirstate[abs] == 'a':
4042 if repo.dirstate[abs] == 'a':
3583 return _('forgetting %s\n')
4043 return _('forgetting %s\n')
3584 return _('removing %s\n')
4044 return _('removing %s\n')
3585
4045
3586 revert = ([], _('reverting %s\n'))
4046 revert = ([], _('reverting %s\n'))
3587 add = ([], _('adding %s\n'))
4047 add = ([], _('adding %s\n'))
3588 remove = ([], removeforget)
4048 remove = ([], removeforget)
3589 undelete = ([], _('undeleting %s\n'))
4049 undelete = ([], _('undeleting %s\n'))
3590
4050
3591 disptable = (
4051 disptable = (
3592 # dispatch table:
4052 # dispatch table:
3593 # file state
4053 # file state
3594 # action if in target manifest
4054 # action if in target manifest
3595 # action if not in target manifest
4055 # action if not in target manifest
3596 # make backup if in target manifest
4056 # make backup if in target manifest
3597 # make backup if not in target manifest
4057 # make backup if not in target manifest
3598 (modified, revert, remove, True, True),
4058 (modified, revert, remove, True, True),
3599 (added, revert, remove, True, False),
4059 (added, revert, remove, True, False),
3600 (removed, undelete, None, False, False),
4060 (removed, undelete, None, False, False),
3601 (deleted, revert, remove, False, False),
4061 (deleted, revert, remove, False, False),
3602 )
4062 )
3603
4063
3604 for abs, (rel, exact) in sorted(names.items()):
4064 for abs, (rel, exact) in sorted(names.items()):
3605 mfentry = mf.get(abs)
4065 mfentry = mf.get(abs)
3606 target = repo.wjoin(abs)
4066 target = repo.wjoin(abs)
3607 def handle(xlist, dobackup):
4067 def handle(xlist, dobackup):
3608 xlist[0].append(abs)
4068 xlist[0].append(abs)
3609 if (dobackup and not opts.get('no_backup') and
4069 if (dobackup and not opts.get('no_backup') and
3610 os.path.lexists(target)):
4070 os.path.lexists(target)):
3611 bakname = "%s.orig" % rel
4071 bakname = "%s.orig" % rel
3612 ui.note(_('saving current version of %s as %s\n') %
4072 ui.note(_('saving current version of %s as %s\n') %
3613 (rel, bakname))
4073 (rel, bakname))
3614 if not opts.get('dry_run'):
4074 if not opts.get('dry_run'):
3615 util.rename(target, bakname)
4075 util.rename(target, bakname)
3616 if ui.verbose or not exact:
4076 if ui.verbose or not exact:
3617 msg = xlist[1]
4077 msg = xlist[1]
3618 if not isinstance(msg, basestring):
4078 if not isinstance(msg, basestring):
3619 msg = msg(abs)
4079 msg = msg(abs)
3620 ui.status(msg % rel)
4080 ui.status(msg % rel)
3621 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4081 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3622 if abs not in table:
4082 if abs not in table:
3623 continue
4083 continue
3624 # file has changed in dirstate
4084 # file has changed in dirstate
3625 if mfentry:
4085 if mfentry:
3626 handle(hitlist, backuphit)
4086 handle(hitlist, backuphit)
3627 elif misslist is not None:
4087 elif misslist is not None:
3628 handle(misslist, backupmiss)
4088 handle(misslist, backupmiss)
3629 break
4089 break
3630 else:
4090 else:
3631 if abs not in repo.dirstate:
4091 if abs not in repo.dirstate:
3632 if mfentry:
4092 if mfentry:
3633 handle(add, True)
4093 handle(add, True)
3634 elif exact:
4094 elif exact:
3635 ui.warn(_('file not managed: %s\n') % rel)
4095 ui.warn(_('file not managed: %s\n') % rel)
3636 continue
4096 continue
3637 # file has not changed in dirstate
4097 # file has not changed in dirstate
3638 if node == parent:
4098 if node == parent:
3639 if exact:
4099 if exact:
3640 ui.warn(_('no changes needed to %s\n') % rel)
4100 ui.warn(_('no changes needed to %s\n') % rel)
3641 continue
4101 continue
3642 if pmf is None:
4102 if pmf is None:
3643 # only need parent manifest in this unlikely case,
4103 # only need parent manifest in this unlikely case,
3644 # so do not read by default
4104 # so do not read by default
3645 pmf = repo[parent].manifest()
4105 pmf = repo[parent].manifest()
3646 if abs in pmf:
4106 if abs in pmf:
3647 if mfentry:
4107 if mfentry:
3648 # if version of file is same in parent and target
4108 # if version of file is same in parent and target
3649 # manifests, do nothing
4109 # manifests, do nothing
3650 if (pmf[abs] != mfentry or
4110 if (pmf[abs] != mfentry or
3651 pmf.flags(abs) != mf.flags(abs)):
4111 pmf.flags(abs) != mf.flags(abs)):
3652 handle(revert, False)
4112 handle(revert, False)
3653 else:
4113 else:
3654 handle(remove, False)
4114 handle(remove, False)
3655
4115
3656 if not opts.get('dry_run'):
4116 if not opts.get('dry_run'):
3657 def checkout(f):
4117 def checkout(f):
3658 fc = ctx[f]
4118 fc = ctx[f]
3659 repo.wwrite(f, fc.data(), fc.flags())
4119 repo.wwrite(f, fc.data(), fc.flags())
3660
4120
3661 audit_path = scmutil.pathauditor(repo.root)
4121 audit_path = scmutil.pathauditor(repo.root)
3662 for f in remove[0]:
4122 for f in remove[0]:
3663 if repo.dirstate[f] == 'a':
4123 if repo.dirstate[f] == 'a':
3664 repo.dirstate.forget(f)
4124 repo.dirstate.forget(f)
3665 continue
4125 continue
3666 audit_path(f)
4126 audit_path(f)
3667 try:
4127 try:
3668 util.unlinkpath(repo.wjoin(f))
4128 util.unlinkpath(repo.wjoin(f))
3669 except OSError:
4129 except OSError:
3670 pass
4130 pass
3671 repo.dirstate.remove(f)
4131 repo.dirstate.remove(f)
3672
4132
3673 normal = None
4133 normal = None
3674 if node == parent:
4134 if node == parent:
3675 # We're reverting to our parent. If possible, we'd like status
4135 # We're reverting to our parent. If possible, we'd like status
3676 # to report the file as clean. We have to use normallookup for
4136 # to report the file as clean. We have to use normallookup for
3677 # merges to avoid losing information about merged/dirty files.
4137 # merges to avoid losing information about merged/dirty files.
3678 if p2 != nullid:
4138 if p2 != nullid:
3679 normal = repo.dirstate.normallookup
4139 normal = repo.dirstate.normallookup
3680 else:
4140 else:
3681 normal = repo.dirstate.normal
4141 normal = repo.dirstate.normal
3682 for f in revert[0]:
4142 for f in revert[0]:
3683 checkout(f)
4143 checkout(f)
3684 if normal:
4144 if normal:
3685 normal(f)
4145 normal(f)
3686
4146
3687 for f in add[0]:
4147 for f in add[0]:
3688 checkout(f)
4148 checkout(f)
3689 repo.dirstate.add(f)
4149 repo.dirstate.add(f)
3690
4150
3691 normal = repo.dirstate.normallookup
4151 normal = repo.dirstate.normallookup
3692 if node == parent and p2 == nullid:
4152 if node == parent and p2 == nullid:
3693 normal = repo.dirstate.normal
4153 normal = repo.dirstate.normal
3694 for f in undelete[0]:
4154 for f in undelete[0]:
3695 checkout(f)
4155 checkout(f)
3696 normal(f)
4156 normal(f)
3697
4157
3698 finally:
4158 finally:
3699 wlock.release()
4159 wlock.release()
3700
4160
4161 @command('rollback', dryrunopts)
3701 def rollback(ui, repo, **opts):
4162 def rollback(ui, repo, **opts):
3702 """roll back the last transaction (dangerous)
4163 """roll back the last transaction (dangerous)
3703
4164
3704 This command should be used with care. There is only one level of
4165 This command should be used with care. There is only one level of
3705 rollback, and there is no way to undo a rollback. It will also
4166 rollback, and there is no way to undo a rollback. It will also
3706 restore the dirstate at the time of the last transaction, losing
4167 restore the dirstate at the time of the last transaction, losing
3707 any dirstate changes since that time. This command does not alter
4168 any dirstate changes since that time. This command does not alter
3708 the working directory.
4169 the working directory.
3709
4170
3710 Transactions are used to encapsulate the effects of all commands
4171 Transactions are used to encapsulate the effects of all commands
3711 that create new changesets or propagate existing changesets into a
4172 that create new changesets or propagate existing changesets into a
3712 repository. For example, the following commands are transactional,
4173 repository. For example, the following commands are transactional,
3713 and their effects can be rolled back:
4174 and their effects can be rolled back:
3714
4175
3715 - commit
4176 - commit
3716 - import
4177 - import
3717 - pull
4178 - pull
3718 - push (with this repository as the destination)
4179 - push (with this repository as the destination)
3719 - unbundle
4180 - unbundle
3720
4181
3721 This command is not intended for use on public repositories. Once
4182 This command is not intended for use on public repositories. Once
3722 changes are visible for pull by other users, rolling a transaction
4183 changes are visible for pull by other users, rolling a transaction
3723 back locally is ineffective (someone else may already have pulled
4184 back locally is ineffective (someone else may already have pulled
3724 the changes). Furthermore, a race is possible with readers of the
4185 the changes). Furthermore, a race is possible with readers of the
3725 repository; for example an in-progress pull from the repository
4186 repository; for example an in-progress pull from the repository
3726 may fail if a rollback is performed.
4187 may fail if a rollback is performed.
3727
4188
3728 Returns 0 on success, 1 if no rollback data is available.
4189 Returns 0 on success, 1 if no rollback data is available.
3729 """
4190 """
3730 return repo.rollback(opts.get('dry_run'))
4191 return repo.rollback(opts.get('dry_run'))
3731
4192
4193 @command('root', [])
3732 def root(ui, repo):
4194 def root(ui, repo):
3733 """print the root (top) of the current working directory
4195 """print the root (top) of the current working directory
3734
4196
3735 Print the root directory of the current repository.
4197 Print the root directory of the current repository.
3736
4198
3737 Returns 0 on success.
4199 Returns 0 on success.
3738 """
4200 """
3739 ui.write(repo.root + "\n")
4201 ui.write(repo.root + "\n")
3740
4202
4203 @command('^serve',
4204 [('A', 'accesslog', '', _('name of access log file to write to'),
4205 _('FILE')),
4206 ('d', 'daemon', None, _('run server in background')),
4207 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4208 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4209 # use string type, then we can check if something was passed
4210 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4211 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4212 _('ADDR')),
4213 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4214 _('PREFIX')),
4215 ('n', 'name', '',
4216 _('name to show in web pages (default: working directory)'), _('NAME')),
4217 ('', 'web-conf', '',
4218 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4219 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4220 _('FILE')),
4221 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4222 ('', 'stdio', None, _('for remote clients')),
4223 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4224 ('', 'style', '', _('template style to use'), _('STYLE')),
4225 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4226 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4227 _('[OPTION]...'))
3741 def serve(ui, repo, **opts):
4228 def serve(ui, repo, **opts):
3742 """start stand-alone webserver
4229 """start stand-alone webserver
3743
4230
3744 Start a local HTTP repository browser and pull server. You can use
4231 Start a local HTTP repository browser and pull server. You can use
3745 this for ad-hoc sharing and browsing of repositories. It is
4232 this for ad-hoc sharing and browsing of repositories. It is
3746 recommended to use a real web server to serve a repository for
4233 recommended to use a real web server to serve a repository for
3747 longer periods of time.
4234 longer periods of time.
3748
4235
3749 Please note that the server does not implement access control.
4236 Please note that the server does not implement access control.
3750 This means that, by default, anybody can read from the server and
4237 This means that, by default, anybody can read from the server and
3751 nobody can write to it by default. Set the ``web.allow_push``
4238 nobody can write to it by default. Set the ``web.allow_push``
3752 option to ``*`` to allow everybody to push to the server. You
4239 option to ``*`` to allow everybody to push to the server. You
3753 should use a real web server if you need to authenticate users.
4240 should use a real web server if you need to authenticate users.
3754
4241
3755 By default, the server logs accesses to stdout and errors to
4242 By default, the server logs accesses to stdout and errors to
3756 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4243 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3757 files.
4244 files.
3758
4245
3759 To have the server choose a free port number to listen on, specify
4246 To have the server choose a free port number to listen on, specify
3760 a port number of 0; in this case, the server will print the port
4247 a port number of 0; in this case, the server will print the port
3761 number it uses.
4248 number it uses.
3762
4249
3763 Returns 0 on success.
4250 Returns 0 on success.
3764 """
4251 """
3765
4252
3766 if opts["stdio"]:
4253 if opts["stdio"]:
3767 if repo is None:
4254 if repo is None:
3768 raise error.RepoError(_("There is no Mercurial repository here"
4255 raise error.RepoError(_("There is no Mercurial repository here"
3769 " (.hg not found)"))
4256 " (.hg not found)"))
3770 s = sshserver.sshserver(ui, repo)
4257 s = sshserver.sshserver(ui, repo)
3771 s.serve_forever()
4258 s.serve_forever()
3772
4259
3773 # this way we can check if something was given in the command-line
4260 # this way we can check if something was given in the command-line
3774 if opts.get('port'):
4261 if opts.get('port'):
3775 opts['port'] = util.getport(opts.get('port'))
4262 opts['port'] = util.getport(opts.get('port'))
3776
4263
3777 baseui = repo and repo.baseui or ui
4264 baseui = repo and repo.baseui or ui
3778 optlist = ("name templates style address port prefix ipv6"
4265 optlist = ("name templates style address port prefix ipv6"
3779 " accesslog errorlog certificate encoding")
4266 " accesslog errorlog certificate encoding")
3780 for o in optlist.split():
4267 for o in optlist.split():
3781 val = opts.get(o, '')
4268 val = opts.get(o, '')
3782 if val in (None, ''): # should check against default options instead
4269 if val in (None, ''): # should check against default options instead
3783 continue
4270 continue
3784 baseui.setconfig("web", o, val)
4271 baseui.setconfig("web", o, val)
3785 if repo and repo.ui != baseui:
4272 if repo and repo.ui != baseui:
3786 repo.ui.setconfig("web", o, val)
4273 repo.ui.setconfig("web", o, val)
3787
4274
3788 o = opts.get('web_conf') or opts.get('webdir_conf')
4275 o = opts.get('web_conf') or opts.get('webdir_conf')
3789 if not o:
4276 if not o:
3790 if not repo:
4277 if not repo:
3791 raise error.RepoError(_("There is no Mercurial repository"
4278 raise error.RepoError(_("There is no Mercurial repository"
3792 " here (.hg not found)"))
4279 " here (.hg not found)"))
3793 o = repo.root
4280 o = repo.root
3794
4281
3795 app = hgweb.hgweb(o, baseui=ui)
4282 app = hgweb.hgweb(o, baseui=ui)
3796
4283
3797 class service(object):
4284 class service(object):
3798 def init(self):
4285 def init(self):
3799 util.setsignalhandler()
4286 util.setsignalhandler()
3800 self.httpd = hgweb.server.create_server(ui, app)
4287 self.httpd = hgweb.server.create_server(ui, app)
3801
4288
3802 if opts['port'] and not ui.verbose:
4289 if opts['port'] and not ui.verbose:
3803 return
4290 return
3804
4291
3805 if self.httpd.prefix:
4292 if self.httpd.prefix:
3806 prefix = self.httpd.prefix.strip('/') + '/'
4293 prefix = self.httpd.prefix.strip('/') + '/'
3807 else:
4294 else:
3808 prefix = ''
4295 prefix = ''
3809
4296
3810 port = ':%d' % self.httpd.port
4297 port = ':%d' % self.httpd.port
3811 if port == ':80':
4298 if port == ':80':
3812 port = ''
4299 port = ''
3813
4300
3814 bindaddr = self.httpd.addr
4301 bindaddr = self.httpd.addr
3815 if bindaddr == '0.0.0.0':
4302 if bindaddr == '0.0.0.0':
3816 bindaddr = '*'
4303 bindaddr = '*'
3817 elif ':' in bindaddr: # IPv6
4304 elif ':' in bindaddr: # IPv6
3818 bindaddr = '[%s]' % bindaddr
4305 bindaddr = '[%s]' % bindaddr
3819
4306
3820 fqaddr = self.httpd.fqaddr
4307 fqaddr = self.httpd.fqaddr
3821 if ':' in fqaddr:
4308 if ':' in fqaddr:
3822 fqaddr = '[%s]' % fqaddr
4309 fqaddr = '[%s]' % fqaddr
3823 if opts['port']:
4310 if opts['port']:
3824 write = ui.status
4311 write = ui.status
3825 else:
4312 else:
3826 write = ui.write
4313 write = ui.write
3827 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4314 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3828 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4315 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3829
4316
3830 def run(self):
4317 def run(self):
3831 self.httpd.serve_forever()
4318 self.httpd.serve_forever()
3832
4319
3833 service = service()
4320 service = service()
3834
4321
3835 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4322 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3836
4323
4324 @command('^status|st',
4325 [('A', 'all', None, _('show status of all files')),
4326 ('m', 'modified', None, _('show only modified files')),
4327 ('a', 'added', None, _('show only added files')),
4328 ('r', 'removed', None, _('show only removed files')),
4329 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4330 ('c', 'clean', None, _('show only files without changes')),
4331 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4332 ('i', 'ignored', None, _('show only ignored files')),
4333 ('n', 'no-status', None, _('hide status prefix')),
4334 ('C', 'copies', None, _('show source of copied files')),
4335 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4336 ('', 'rev', [], _('show difference from revision'), _('REV')),
4337 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4338 ] + walkopts + subrepoopts,
4339 _('[OPTION]... [FILE]...'))
3837 def status(ui, repo, *pats, **opts):
4340 def status(ui, repo, *pats, **opts):
3838 """show changed files in the working directory
4341 """show changed files in the working directory
3839
4342
3840 Show status of files in the repository. If names are given, only
4343 Show status of files in the repository. If names are given, only
3841 files that match are shown. Files that are clean or ignored or
4344 files that match are shown. Files that are clean or ignored or
3842 the source of a copy/move operation, are not listed unless
4345 the source of a copy/move operation, are not listed unless
3843 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4346 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3844 Unless options described with "show only ..." are given, the
4347 Unless options described with "show only ..." are given, the
3845 options -mardu are used.
4348 options -mardu are used.
3846
4349
3847 Option -q/--quiet hides untracked (unknown and ignored) files
4350 Option -q/--quiet hides untracked (unknown and ignored) files
3848 unless explicitly requested with -u/--unknown or -i/--ignored.
4351 unless explicitly requested with -u/--unknown or -i/--ignored.
3849
4352
3850 .. note::
4353 .. note::
3851 status may appear to disagree with diff if permissions have
4354 status may appear to disagree with diff if permissions have
3852 changed or a merge has occurred. The standard diff format does
4355 changed or a merge has occurred. The standard diff format does
3853 not report permission changes and diff only reports changes
4356 not report permission changes and diff only reports changes
3854 relative to one merge parent.
4357 relative to one merge parent.
3855
4358
3856 If one revision is given, it is used as the base revision.
4359 If one revision is given, it is used as the base revision.
3857 If two revisions are given, the differences between them are
4360 If two revisions are given, the differences between them are
3858 shown. The --change option can also be used as a shortcut to list
4361 shown. The --change option can also be used as a shortcut to list
3859 the changed files of a revision from its first parent.
4362 the changed files of a revision from its first parent.
3860
4363
3861 The codes used to show the status of files are::
4364 The codes used to show the status of files are::
3862
4365
3863 M = modified
4366 M = modified
3864 A = added
4367 A = added
3865 R = removed
4368 R = removed
3866 C = clean
4369 C = clean
3867 ! = missing (deleted by non-hg command, but still tracked)
4370 ! = missing (deleted by non-hg command, but still tracked)
3868 ? = not tracked
4371 ? = not tracked
3869 I = ignored
4372 I = ignored
3870 = origin of the previous file listed as A (added)
4373 = origin of the previous file listed as A (added)
3871
4374
3872 Returns 0 on success.
4375 Returns 0 on success.
3873 """
4376 """
3874
4377
3875 revs = opts.get('rev')
4378 revs = opts.get('rev')
3876 change = opts.get('change')
4379 change = opts.get('change')
3877
4380
3878 if revs and change:
4381 if revs and change:
3879 msg = _('cannot specify --rev and --change at the same time')
4382 msg = _('cannot specify --rev and --change at the same time')
3880 raise util.Abort(msg)
4383 raise util.Abort(msg)
3881 elif change:
4384 elif change:
3882 node2 = repo.lookup(change)
4385 node2 = repo.lookup(change)
3883 node1 = repo[node2].p1().node()
4386 node1 = repo[node2].p1().node()
3884 else:
4387 else:
3885 node1, node2 = cmdutil.revpair(repo, revs)
4388 node1, node2 = cmdutil.revpair(repo, revs)
3886
4389
3887 cwd = (pats and repo.getcwd()) or ''
4390 cwd = (pats and repo.getcwd()) or ''
3888 end = opts.get('print0') and '\0' or '\n'
4391 end = opts.get('print0') and '\0' or '\n'
3889 copy = {}
4392 copy = {}
3890 states = 'modified added removed deleted unknown ignored clean'.split()
4393 states = 'modified added removed deleted unknown ignored clean'.split()
3891 show = [k for k in states if opts.get(k)]
4394 show = [k for k in states if opts.get(k)]
3892 if opts.get('all'):
4395 if opts.get('all'):
3893 show += ui.quiet and (states[:4] + ['clean']) or states
4396 show += ui.quiet and (states[:4] + ['clean']) or states
3894 if not show:
4397 if not show:
3895 show = ui.quiet and states[:4] or states[:5]
4398 show = ui.quiet and states[:4] or states[:5]
3896
4399
3897 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
4400 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3898 'ignored' in show, 'clean' in show, 'unknown' in show,
4401 'ignored' in show, 'clean' in show, 'unknown' in show,
3899 opts.get('subrepos'))
4402 opts.get('subrepos'))
3900 changestates = zip(states, 'MAR!?IC', stat)
4403 changestates = zip(states, 'MAR!?IC', stat)
3901
4404
3902 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4405 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3903 ctxn = repo[nullid]
4406 ctxn = repo[nullid]
3904 ctx1 = repo[node1]
4407 ctx1 = repo[node1]
3905 ctx2 = repo[node2]
4408 ctx2 = repo[node2]
3906 added = stat[1]
4409 added = stat[1]
3907 if node2 is None:
4410 if node2 is None:
3908 added = stat[0] + stat[1] # merged?
4411 added = stat[0] + stat[1] # merged?
3909
4412
3910 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4413 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3911 if k in added:
4414 if k in added:
3912 copy[k] = v
4415 copy[k] = v
3913 elif v in added:
4416 elif v in added:
3914 copy[v] = k
4417 copy[v] = k
3915
4418
3916 for state, char, files in changestates:
4419 for state, char, files in changestates:
3917 if state in show:
4420 if state in show:
3918 format = "%s %%s%s" % (char, end)
4421 format = "%s %%s%s" % (char, end)
3919 if opts.get('no_status'):
4422 if opts.get('no_status'):
3920 format = "%%s%s" % end
4423 format = "%%s%s" % end
3921
4424
3922 for f in files:
4425 for f in files:
3923 ui.write(format % repo.pathto(f, cwd),
4426 ui.write(format % repo.pathto(f, cwd),
3924 label='status.' + state)
4427 label='status.' + state)
3925 if f in copy:
4428 if f in copy:
3926 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4429 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3927 label='status.copied')
4430 label='status.copied')
3928
4431
4432 @command('^summary|sum',
4433 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
3929 def summary(ui, repo, **opts):
4434 def summary(ui, repo, **opts):
3930 """summarize working directory state
4435 """summarize working directory state
3931
4436
3932 This generates a brief summary of the working directory state,
4437 This generates a brief summary of the working directory state,
3933 including parents, branch, commit status, and available updates.
4438 including parents, branch, commit status, and available updates.
3934
4439
3935 With the --remote option, this will check the default paths for
4440 With the --remote option, this will check the default paths for
3936 incoming and outgoing changes. This can be time-consuming.
4441 incoming and outgoing changes. This can be time-consuming.
3937
4442
3938 Returns 0 on success.
4443 Returns 0 on success.
3939 """
4444 """
3940
4445
3941 ctx = repo[None]
4446 ctx = repo[None]
3942 parents = ctx.parents()
4447 parents = ctx.parents()
3943 pnode = parents[0].node()
4448 pnode = parents[0].node()
3944
4449
3945 for p in parents:
4450 for p in parents:
3946 # label with log.changeset (instead of log.parent) since this
4451 # label with log.changeset (instead of log.parent) since this
3947 # shows a working directory parent *changeset*:
4452 # shows a working directory parent *changeset*:
3948 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4453 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3949 label='log.changeset')
4454 label='log.changeset')
3950 ui.write(' '.join(p.tags()), label='log.tag')
4455 ui.write(' '.join(p.tags()), label='log.tag')
3951 if p.bookmarks():
4456 if p.bookmarks():
3952 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
4457 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
3953 if p.rev() == -1:
4458 if p.rev() == -1:
3954 if not len(repo):
4459 if not len(repo):
3955 ui.write(_(' (empty repository)'))
4460 ui.write(_(' (empty repository)'))
3956 else:
4461 else:
3957 ui.write(_(' (no revision checked out)'))
4462 ui.write(_(' (no revision checked out)'))
3958 ui.write('\n')
4463 ui.write('\n')
3959 if p.description():
4464 if p.description():
3960 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4465 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3961 label='log.summary')
4466 label='log.summary')
3962
4467
3963 branch = ctx.branch()
4468 branch = ctx.branch()
3964 bheads = repo.branchheads(branch)
4469 bheads = repo.branchheads(branch)
3965 m = _('branch: %s\n') % branch
4470 m = _('branch: %s\n') % branch
3966 if branch != 'default':
4471 if branch != 'default':
3967 ui.write(m, label='log.branch')
4472 ui.write(m, label='log.branch')
3968 else:
4473 else:
3969 ui.status(m, label='log.branch')
4474 ui.status(m, label='log.branch')
3970
4475
3971 st = list(repo.status(unknown=True))[:6]
4476 st = list(repo.status(unknown=True))[:6]
3972
4477
3973 c = repo.dirstate.copies()
4478 c = repo.dirstate.copies()
3974 copied, renamed = [], []
4479 copied, renamed = [], []
3975 for d, s in c.iteritems():
4480 for d, s in c.iteritems():
3976 if s in st[2]:
4481 if s in st[2]:
3977 st[2].remove(s)
4482 st[2].remove(s)
3978 renamed.append(d)
4483 renamed.append(d)
3979 else:
4484 else:
3980 copied.append(d)
4485 copied.append(d)
3981 if d in st[1]:
4486 if d in st[1]:
3982 st[1].remove(d)
4487 st[1].remove(d)
3983 st.insert(3, renamed)
4488 st.insert(3, renamed)
3984 st.insert(4, copied)
4489 st.insert(4, copied)
3985
4490
3986 ms = mergemod.mergestate(repo)
4491 ms = mergemod.mergestate(repo)
3987 st.append([f for f in ms if ms[f] == 'u'])
4492 st.append([f for f in ms if ms[f] == 'u'])
3988
4493
3989 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4494 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3990 st.append(subs)
4495 st.append(subs)
3991
4496
3992 labels = [ui.label(_('%d modified'), 'status.modified'),
4497 labels = [ui.label(_('%d modified'), 'status.modified'),
3993 ui.label(_('%d added'), 'status.added'),
4498 ui.label(_('%d added'), 'status.added'),
3994 ui.label(_('%d removed'), 'status.removed'),
4499 ui.label(_('%d removed'), 'status.removed'),
3995 ui.label(_('%d renamed'), 'status.copied'),
4500 ui.label(_('%d renamed'), 'status.copied'),
3996 ui.label(_('%d copied'), 'status.copied'),
4501 ui.label(_('%d copied'), 'status.copied'),
3997 ui.label(_('%d deleted'), 'status.deleted'),
4502 ui.label(_('%d deleted'), 'status.deleted'),
3998 ui.label(_('%d unknown'), 'status.unknown'),
4503 ui.label(_('%d unknown'), 'status.unknown'),
3999 ui.label(_('%d ignored'), 'status.ignored'),
4504 ui.label(_('%d ignored'), 'status.ignored'),
4000 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4505 ui.label(_('%d unresolved'), 'resolve.unresolved'),
4001 ui.label(_('%d subrepos'), 'status.modified')]
4506 ui.label(_('%d subrepos'), 'status.modified')]
4002 t = []
4507 t = []
4003 for s, l in zip(st, labels):
4508 for s, l in zip(st, labels):
4004 if s:
4509 if s:
4005 t.append(l % len(s))
4510 t.append(l % len(s))
4006
4511
4007 t = ', '.join(t)
4512 t = ', '.join(t)
4008 cleanworkdir = False
4513 cleanworkdir = False
4009
4514
4010 if len(parents) > 1:
4515 if len(parents) > 1:
4011 t += _(' (merge)')
4516 t += _(' (merge)')
4012 elif branch != parents[0].branch():
4517 elif branch != parents[0].branch():
4013 t += _(' (new branch)')
4518 t += _(' (new branch)')
4014 elif (parents[0].extra().get('close') and
4519 elif (parents[0].extra().get('close') and
4015 pnode in repo.branchheads(branch, closed=True)):
4520 pnode in repo.branchheads(branch, closed=True)):
4016 t += _(' (head closed)')
4521 t += _(' (head closed)')
4017 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4522 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
4018 t += _(' (clean)')
4523 t += _(' (clean)')
4019 cleanworkdir = True
4524 cleanworkdir = True
4020 elif pnode not in bheads:
4525 elif pnode not in bheads:
4021 t += _(' (new branch head)')
4526 t += _(' (new branch head)')
4022
4527
4023 if cleanworkdir:
4528 if cleanworkdir:
4024 ui.status(_('commit: %s\n') % t.strip())
4529 ui.status(_('commit: %s\n') % t.strip())
4025 else:
4530 else:
4026 ui.write(_('commit: %s\n') % t.strip())
4531 ui.write(_('commit: %s\n') % t.strip())
4027
4532
4028 # all ancestors of branch heads - all ancestors of parent = new csets
4533 # all ancestors of branch heads - all ancestors of parent = new csets
4029 new = [0] * len(repo)
4534 new = [0] * len(repo)
4030 cl = repo.changelog
4535 cl = repo.changelog
4031 for a in [cl.rev(n) for n in bheads]:
4536 for a in [cl.rev(n) for n in bheads]:
4032 new[a] = 1
4537 new[a] = 1
4033 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4538 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
4034 new[a] = 1
4539 new[a] = 1
4035 for a in [p.rev() for p in parents]:
4540 for a in [p.rev() for p in parents]:
4036 if a >= 0:
4541 if a >= 0:
4037 new[a] = 0
4542 new[a] = 0
4038 for a in cl.ancestors(*[p.rev() for p in parents]):
4543 for a in cl.ancestors(*[p.rev() for p in parents]):
4039 new[a] = 0
4544 new[a] = 0
4040 new = sum(new)
4545 new = sum(new)
4041
4546
4042 if new == 0:
4547 if new == 0:
4043 ui.status(_('update: (current)\n'))
4548 ui.status(_('update: (current)\n'))
4044 elif pnode not in bheads:
4549 elif pnode not in bheads:
4045 ui.write(_('update: %d new changesets (update)\n') % new)
4550 ui.write(_('update: %d new changesets (update)\n') % new)
4046 else:
4551 else:
4047 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4552 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4048 (new, len(bheads)))
4553 (new, len(bheads)))
4049
4554
4050 if opts.get('remote'):
4555 if opts.get('remote'):
4051 t = []
4556 t = []
4052 source, branches = hg.parseurl(ui.expandpath('default'))
4557 source, branches = hg.parseurl(ui.expandpath('default'))
4053 other = hg.repository(hg.remoteui(repo, {}), source)
4558 other = hg.repository(hg.remoteui(repo, {}), source)
4054 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4559 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4055 ui.debug('comparing with %s\n' % util.hidepassword(source))
4560 ui.debug('comparing with %s\n' % util.hidepassword(source))
4056 repo.ui.pushbuffer()
4561 repo.ui.pushbuffer()
4057 commoninc = discovery.findcommonincoming(repo, other)
4562 commoninc = discovery.findcommonincoming(repo, other)
4058 _common, incoming, _rheads = commoninc
4563 _common, incoming, _rheads = commoninc
4059 repo.ui.popbuffer()
4564 repo.ui.popbuffer()
4060 if incoming:
4565 if incoming:
4061 t.append(_('1 or more incoming'))
4566 t.append(_('1 or more incoming'))
4062
4567
4063 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4568 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
4064 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4569 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
4065 if source != dest:
4570 if source != dest:
4066 other = hg.repository(hg.remoteui(repo, {}), dest)
4571 other = hg.repository(hg.remoteui(repo, {}), dest)
4067 commoninc = None
4572 commoninc = None
4068 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4573 ui.debug('comparing with %s\n' % util.hidepassword(dest))
4069 repo.ui.pushbuffer()
4574 repo.ui.pushbuffer()
4070 common, outheads = discovery.findcommonoutgoing(repo, other,
4575 common, outheads = discovery.findcommonoutgoing(repo, other,
4071 commoninc=commoninc)
4576 commoninc=commoninc)
4072 repo.ui.popbuffer()
4577 repo.ui.popbuffer()
4073 o = repo.changelog.findmissing(common=common, heads=outheads)
4578 o = repo.changelog.findmissing(common=common, heads=outheads)
4074 if o:
4579 if o:
4075 t.append(_('%d outgoing') % len(o))
4580 t.append(_('%d outgoing') % len(o))
4076 if 'bookmarks' in other.listkeys('namespaces'):
4581 if 'bookmarks' in other.listkeys('namespaces'):
4077 lmarks = repo.listkeys('bookmarks')
4582 lmarks = repo.listkeys('bookmarks')
4078 rmarks = other.listkeys('bookmarks')
4583 rmarks = other.listkeys('bookmarks')
4079 diff = set(rmarks) - set(lmarks)
4584 diff = set(rmarks) - set(lmarks)
4080 if len(diff) > 0:
4585 if len(diff) > 0:
4081 t.append(_('%d incoming bookmarks') % len(diff))
4586 t.append(_('%d incoming bookmarks') % len(diff))
4082 diff = set(lmarks) - set(rmarks)
4587 diff = set(lmarks) - set(rmarks)
4083 if len(diff) > 0:
4588 if len(diff) > 0:
4084 t.append(_('%d outgoing bookmarks') % len(diff))
4589 t.append(_('%d outgoing bookmarks') % len(diff))
4085
4590
4086 if t:
4591 if t:
4087 ui.write(_('remote: %s\n') % (', '.join(t)))
4592 ui.write(_('remote: %s\n') % (', '.join(t)))
4088 else:
4593 else:
4089 ui.status(_('remote: (synced)\n'))
4594 ui.status(_('remote: (synced)\n'))
4090
4595
4596 @command('tag',
4597 [('f', 'force', None, _('force tag')),
4598 ('l', 'local', None, _('make the tag local')),
4599 ('r', 'rev', '', _('revision to tag'), _('REV')),
4600 ('', 'remove', None, _('remove a tag')),
4601 # -l/--local is already there, commitopts cannot be used
4602 ('e', 'edit', None, _('edit commit message')),
4603 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
4604 ] + commitopts2,
4605 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
4091 def tag(ui, repo, name1, *names, **opts):
4606 def tag(ui, repo, name1, *names, **opts):
4092 """add one or more tags for the current or given revision
4607 """add one or more tags for the current or given revision
4093
4608
4094 Name a particular revision using <name>.
4609 Name a particular revision using <name>.
4095
4610
4096 Tags are used to name particular revisions of the repository and are
4611 Tags are used to name particular revisions of the repository and are
4097 very useful to compare different revisions, to go back to significant
4612 very useful to compare different revisions, to go back to significant
4098 earlier versions or to mark branch points as releases, etc. Changing
4613 earlier versions or to mark branch points as releases, etc. Changing
4099 an existing tag is normally disallowed; use -f/--force to override.
4614 an existing tag is normally disallowed; use -f/--force to override.
4100
4615
4101 If no revision is given, the parent of the working directory is
4616 If no revision is given, the parent of the working directory is
4102 used, or tip if no revision is checked out.
4617 used, or tip if no revision is checked out.
4103
4618
4104 To facilitate version control, distribution, and merging of tags,
4619 To facilitate version control, distribution, and merging of tags,
4105 they are stored as a file named ".hgtags" which is managed similarly
4620 they are stored as a file named ".hgtags" which is managed similarly
4106 to other project files and can be hand-edited if necessary. This
4621 to other project files and can be hand-edited if necessary. This
4107 also means that tagging creates a new commit. The file
4622 also means that tagging creates a new commit. The file
4108 ".hg/localtags" is used for local tags (not shared among
4623 ".hg/localtags" is used for local tags (not shared among
4109 repositories).
4624 repositories).
4110
4625
4111 Tag commits are usually made at the head of a branch. If the parent
4626 Tag commits are usually made at the head of a branch. If the parent
4112 of the working directory is not a branch head, :hg:`tag` aborts; use
4627 of the working directory is not a branch head, :hg:`tag` aborts; use
4113 -f/--force to force the tag commit to be based on a non-head
4628 -f/--force to force the tag commit to be based on a non-head
4114 changeset.
4629 changeset.
4115
4630
4116 See :hg:`help dates` for a list of formats valid for -d/--date.
4631 See :hg:`help dates` for a list of formats valid for -d/--date.
4117
4632
4118 Since tag names have priority over branch names during revision
4633 Since tag names have priority over branch names during revision
4119 lookup, using an existing branch name as a tag name is discouraged.
4634 lookup, using an existing branch name as a tag name is discouraged.
4120
4635
4121 Returns 0 on success.
4636 Returns 0 on success.
4122 """
4637 """
4123
4638
4124 rev_ = "."
4639 rev_ = "."
4125 names = [t.strip() for t in (name1,) + names]
4640 names = [t.strip() for t in (name1,) + names]
4126 if len(names) != len(set(names)):
4641 if len(names) != len(set(names)):
4127 raise util.Abort(_('tag names must be unique'))
4642 raise util.Abort(_('tag names must be unique'))
4128 for n in names:
4643 for n in names:
4129 if n in ['tip', '.', 'null']:
4644 if n in ['tip', '.', 'null']:
4130 raise util.Abort(_("the name '%s' is reserved") % n)
4645 raise util.Abort(_("the name '%s' is reserved") % n)
4131 if not n:
4646 if not n:
4132 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4647 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4133 if opts.get('rev') and opts.get('remove'):
4648 if opts.get('rev') and opts.get('remove'):
4134 raise util.Abort(_("--rev and --remove are incompatible"))
4649 raise util.Abort(_("--rev and --remove are incompatible"))
4135 if opts.get('rev'):
4650 if opts.get('rev'):
4136 rev_ = opts['rev']
4651 rev_ = opts['rev']
4137 message = opts.get('message')
4652 message = opts.get('message')
4138 if opts.get('remove'):
4653 if opts.get('remove'):
4139 expectedtype = opts.get('local') and 'local' or 'global'
4654 expectedtype = opts.get('local') and 'local' or 'global'
4140 for n in names:
4655 for n in names:
4141 if not repo.tagtype(n):
4656 if not repo.tagtype(n):
4142 raise util.Abort(_("tag '%s' does not exist") % n)
4657 raise util.Abort(_("tag '%s' does not exist") % n)
4143 if repo.tagtype(n) != expectedtype:
4658 if repo.tagtype(n) != expectedtype:
4144 if expectedtype == 'global':
4659 if expectedtype == 'global':
4145 raise util.Abort(_("tag '%s' is not a global tag") % n)
4660 raise util.Abort(_("tag '%s' is not a global tag") % n)
4146 else:
4661 else:
4147 raise util.Abort(_("tag '%s' is not a local tag") % n)
4662 raise util.Abort(_("tag '%s' is not a local tag") % n)
4148 rev_ = nullid
4663 rev_ = nullid
4149 if not message:
4664 if not message:
4150 # we don't translate commit messages
4665 # we don't translate commit messages
4151 message = 'Removed tag %s' % ', '.join(names)
4666 message = 'Removed tag %s' % ', '.join(names)
4152 elif not opts.get('force'):
4667 elif not opts.get('force'):
4153 for n in names:
4668 for n in names:
4154 if n in repo.tags():
4669 if n in repo.tags():
4155 raise util.Abort(_("tag '%s' already exists "
4670 raise util.Abort(_("tag '%s' already exists "
4156 "(use -f to force)") % n)
4671 "(use -f to force)") % n)
4157 if not opts.get('local'):
4672 if not opts.get('local'):
4158 p1, p2 = repo.dirstate.parents()
4673 p1, p2 = repo.dirstate.parents()
4159 if p2 != nullid:
4674 if p2 != nullid:
4160 raise util.Abort(_('uncommitted merge'))
4675 raise util.Abort(_('uncommitted merge'))
4161 bheads = repo.branchheads()
4676 bheads = repo.branchheads()
4162 if not opts.get('force') and bheads and p1 not in bheads:
4677 if not opts.get('force') and bheads and p1 not in bheads:
4163 raise util.Abort(_('not at a branch head (use -f to force)'))
4678 raise util.Abort(_('not at a branch head (use -f to force)'))
4164 r = cmdutil.revsingle(repo, rev_).node()
4679 r = cmdutil.revsingle(repo, rev_).node()
4165
4680
4166 if not message:
4681 if not message:
4167 # we don't translate commit messages
4682 # we don't translate commit messages
4168 message = ('Added tag %s for changeset %s' %
4683 message = ('Added tag %s for changeset %s' %
4169 (', '.join(names), short(r)))
4684 (', '.join(names), short(r)))
4170
4685
4171 date = opts.get('date')
4686 date = opts.get('date')
4172 if date:
4687 if date:
4173 date = util.parsedate(date)
4688 date = util.parsedate(date)
4174
4689
4175 if opts.get('edit'):
4690 if opts.get('edit'):
4176 message = ui.edit(message, ui.username())
4691 message = ui.edit(message, ui.username())
4177
4692
4178 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4693 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4179
4694
4695 @command('tags', [], '')
4180 def tags(ui, repo):
4696 def tags(ui, repo):
4181 """list repository tags
4697 """list repository tags
4182
4698
4183 This lists both regular and local tags. When the -v/--verbose
4699 This lists both regular and local tags. When the -v/--verbose
4184 switch is used, a third column "local" is printed for local tags.
4700 switch is used, a third column "local" is printed for local tags.
4185
4701
4186 Returns 0 on success.
4702 Returns 0 on success.
4187 """
4703 """
4188
4704
4189 hexfunc = ui.debugflag and hex or short
4705 hexfunc = ui.debugflag and hex or short
4190 tagtype = ""
4706 tagtype = ""
4191
4707
4192 for t, n in reversed(repo.tagslist()):
4708 for t, n in reversed(repo.tagslist()):
4193 if ui.quiet:
4709 if ui.quiet:
4194 ui.write("%s\n" % t)
4710 ui.write("%s\n" % t)
4195 continue
4711 continue
4196
4712
4197 hn = hexfunc(n)
4713 hn = hexfunc(n)
4198 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4714 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4199 spaces = " " * (30 - encoding.colwidth(t))
4715 spaces = " " * (30 - encoding.colwidth(t))
4200
4716
4201 if ui.verbose:
4717 if ui.verbose:
4202 if repo.tagtype(t) == 'local':
4718 if repo.tagtype(t) == 'local':
4203 tagtype = " local"
4719 tagtype = " local"
4204 else:
4720 else:
4205 tagtype = ""
4721 tagtype = ""
4206 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4722 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4207
4723
4724 @command('tip',
4725 [('p', 'patch', None, _('show patch')),
4726 ('g', 'git', None, _('use git extended diff format')),
4727 ] + templateopts,
4728 _('[-p] [-g]'))
4208 def tip(ui, repo, **opts):
4729 def tip(ui, repo, **opts):
4209 """show the tip revision
4730 """show the tip revision
4210
4731
4211 The tip revision (usually just called the tip) is the changeset
4732 The tip revision (usually just called the tip) is the changeset
4212 most recently added to the repository (and therefore the most
4733 most recently added to the repository (and therefore the most
4213 recently changed head).
4734 recently changed head).
4214
4735
4215 If you have just made a commit, that commit will be the tip. If
4736 If you have just made a commit, that commit will be the tip. If
4216 you have just pulled changes from another repository, the tip of
4737 you have just pulled changes from another repository, the tip of
4217 that repository becomes the current tip. The "tip" tag is special
4738 that repository becomes the current tip. The "tip" tag is special
4218 and cannot be renamed or assigned to a different changeset.
4739 and cannot be renamed or assigned to a different changeset.
4219
4740
4220 Returns 0 on success.
4741 Returns 0 on success.
4221 """
4742 """
4222 displayer = cmdutil.show_changeset(ui, repo, opts)
4743 displayer = cmdutil.show_changeset(ui, repo, opts)
4223 displayer.show(repo[len(repo) - 1])
4744 displayer.show(repo[len(repo) - 1])
4224 displayer.close()
4745 displayer.close()
4225
4746
4747 @command('unbundle',
4748 [('u', 'update', None,
4749 _('update to new branch head if changesets were unbundled'))],
4750 _('[-u] FILE...'))
4226 def unbundle(ui, repo, fname1, *fnames, **opts):
4751 def unbundle(ui, repo, fname1, *fnames, **opts):
4227 """apply one or more changegroup files
4752 """apply one or more changegroup files
4228
4753
4229 Apply one or more compressed changegroup files generated by the
4754 Apply one or more compressed changegroup files generated by the
4230 bundle command.
4755 bundle command.
4231
4756
4232 Returns 0 on success, 1 if an update has unresolved files.
4757 Returns 0 on success, 1 if an update has unresolved files.
4233 """
4758 """
4234 fnames = (fname1,) + fnames
4759 fnames = (fname1,) + fnames
4235
4760
4236 lock = repo.lock()
4761 lock = repo.lock()
4237 wc = repo['.']
4762 wc = repo['.']
4238 try:
4763 try:
4239 for fname in fnames:
4764 for fname in fnames:
4240 f = url.open(ui, fname)
4765 f = url.open(ui, fname)
4241 gen = changegroup.readbundle(f, fname)
4766 gen = changegroup.readbundle(f, fname)
4242 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4767 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4243 lock=lock)
4768 lock=lock)
4244 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4769 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4245 finally:
4770 finally:
4246 lock.release()
4771 lock.release()
4247 return postincoming(ui, repo, modheads, opts.get('update'), None)
4772 return postincoming(ui, repo, modheads, opts.get('update'), None)
4248
4773
4774 @command('^update|up|checkout|co',
4775 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4776 ('c', 'check', None,
4777 _('update across branches if no uncommitted changes')),
4778 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4779 ('r', 'rev', '', _('revision'), _('REV'))],
4780 _('[-c] [-C] [-d DATE] [[-r] REV]'))
4249 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4781 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4250 """update working directory (or switch revisions)
4782 """update working directory (or switch revisions)
4251
4783
4252 Update the repository's working directory to the specified
4784 Update the repository's working directory to the specified
4253 changeset. If no changeset is specified, update to the tip of the
4785 changeset. If no changeset is specified, update to the tip of the
4254 current named branch.
4786 current named branch.
4255
4787
4256 If the changeset is not a descendant of the working directory's
4788 If the changeset is not a descendant of the working directory's
4257 parent, the update is aborted. With the -c/--check option, the
4789 parent, the update is aborted. With the -c/--check option, the
4258 working directory is checked for uncommitted changes; if none are
4790 working directory is checked for uncommitted changes; if none are
4259 found, the working directory is updated to the specified
4791 found, the working directory is updated to the specified
4260 changeset.
4792 changeset.
4261
4793
4262 The following rules apply when the working directory contains
4794 The following rules apply when the working directory contains
4263 uncommitted changes:
4795 uncommitted changes:
4264
4796
4265 1. If neither -c/--check nor -C/--clean is specified, and if
4797 1. If neither -c/--check nor -C/--clean is specified, and if
4266 the requested changeset is an ancestor or descendant of
4798 the requested changeset is an ancestor or descendant of
4267 the working directory's parent, the uncommitted changes
4799 the working directory's parent, the uncommitted changes
4268 are merged into the requested changeset and the merged
4800 are merged into the requested changeset and the merged
4269 result is left uncommitted. If the requested changeset is
4801 result is left uncommitted. If the requested changeset is
4270 not an ancestor or descendant (that is, it is on another
4802 not an ancestor or descendant (that is, it is on another
4271 branch), the update is aborted and the uncommitted changes
4803 branch), the update is aborted and the uncommitted changes
4272 are preserved.
4804 are preserved.
4273
4805
4274 2. With the -c/--check option, the update is aborted and the
4806 2. With the -c/--check option, the update is aborted and the
4275 uncommitted changes are preserved.
4807 uncommitted changes are preserved.
4276
4808
4277 3. With the -C/--clean option, uncommitted changes are discarded and
4809 3. With the -C/--clean option, uncommitted changes are discarded and
4278 the working directory is updated to the requested changeset.
4810 the working directory is updated to the requested changeset.
4279
4811
4280 Use null as the changeset to remove the working directory (like
4812 Use null as the changeset to remove the working directory (like
4281 :hg:`clone -U`).
4813 :hg:`clone -U`).
4282
4814
4283 If you want to update just one file to an older changeset, use
4815 If you want to update just one file to an older changeset, use
4284 :hg:`revert`.
4816 :hg:`revert`.
4285
4817
4286 See :hg:`help dates` for a list of formats valid for -d/--date.
4818 See :hg:`help dates` for a list of formats valid for -d/--date.
4287
4819
4288 Returns 0 on success, 1 if there are unresolved files.
4820 Returns 0 on success, 1 if there are unresolved files.
4289 """
4821 """
4290 if rev and node:
4822 if rev and node:
4291 raise util.Abort(_("please specify just one revision"))
4823 raise util.Abort(_("please specify just one revision"))
4292
4824
4293 if rev is None or rev == '':
4825 if rev is None or rev == '':
4294 rev = node
4826 rev = node
4295
4827
4296 # if we defined a bookmark, we have to remember the original bookmark name
4828 # if we defined a bookmark, we have to remember the original bookmark name
4297 brev = rev
4829 brev = rev
4298 rev = cmdutil.revsingle(repo, rev, rev).rev()
4830 rev = cmdutil.revsingle(repo, rev, rev).rev()
4299
4831
4300 if check and clean:
4832 if check and clean:
4301 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4833 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4302
4834
4303 if check:
4835 if check:
4304 # we could use dirty() but we can ignore merge and branch trivia
4836 # we could use dirty() but we can ignore merge and branch trivia
4305 c = repo[None]
4837 c = repo[None]
4306 if c.modified() or c.added() or c.removed():
4838 if c.modified() or c.added() or c.removed():
4307 raise util.Abort(_("uncommitted local changes"))
4839 raise util.Abort(_("uncommitted local changes"))
4308
4840
4309 if date:
4841 if date:
4310 if rev is not None:
4842 if rev is not None:
4311 raise util.Abort(_("you can't specify a revision and a date"))
4843 raise util.Abort(_("you can't specify a revision and a date"))
4312 rev = cmdutil.finddate(ui, repo, date)
4844 rev = cmdutil.finddate(ui, repo, date)
4313
4845
4314 if clean or check:
4846 if clean or check:
4315 ret = hg.clean(repo, rev)
4847 ret = hg.clean(repo, rev)
4316 else:
4848 else:
4317 ret = hg.update(repo, rev)
4849 ret = hg.update(repo, rev)
4318
4850
4319 if brev in repo._bookmarks:
4851 if brev in repo._bookmarks:
4320 bookmarks.setcurrent(repo, brev)
4852 bookmarks.setcurrent(repo, brev)
4321
4853
4322 return ret
4854 return ret
4323
4855
4856 @command('verify', [])
4324 def verify(ui, repo):
4857 def verify(ui, repo):
4325 """verify the integrity of the repository
4858 """verify the integrity of the repository
4326
4859
4327 Verify the integrity of the current repository.
4860 Verify the integrity of the current repository.
4328
4861
4329 This will perform an extensive check of the repository's
4862 This will perform an extensive check of the repository's
4330 integrity, validating the hashes and checksums of each entry in
4863 integrity, validating the hashes and checksums of each entry in
4331 the changelog, manifest, and tracked files, as well as the
4864 the changelog, manifest, and tracked files, as well as the
4332 integrity of their crosslinks and indices.
4865 integrity of their crosslinks and indices.
4333
4866
4334 Returns 0 on success, 1 if errors are encountered.
4867 Returns 0 on success, 1 if errors are encountered.
4335 """
4868 """
4336 return hg.verify(repo)
4869 return hg.verify(repo)
4337
4870
4871 @command('version', [])
4338 def version_(ui):
4872 def version_(ui):
4339 """output version and copyright information"""
4873 """output version and copyright information"""
4340 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4874 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4341 % util.version())
4875 % util.version())
4342 ui.status(_(
4876 ui.status(_(
4343 "(see http://mercurial.selenic.com for more information)\n"
4877 "(see http://mercurial.selenic.com for more information)\n"
4344 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4878 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4345 "This is free software; see the source for copying conditions. "
4879 "This is free software; see the source for copying conditions. "
4346 "There is NO\nwarranty; "
4880 "There is NO\nwarranty; "
4347 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4881 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4348 ))
4882 ))
4349
4883
4350 # Command options and aliases are listed here, alphabetically
4351
4352 globalopts = [
4353 ('R', 'repository', '',
4354 _('repository root directory or name of overlay bundle file'),
4355 _('REPO')),
4356 ('', 'cwd', '',
4357 _('change working directory'), _('DIR')),
4358 ('y', 'noninteractive', None,
4359 _('do not prompt, assume \'yes\' for any required answers')),
4360 ('q', 'quiet', None, _('suppress output')),
4361 ('v', 'verbose', None, _('enable additional output')),
4362 ('', 'config', [],
4363 _('set/override config option (use \'section.name=value\')'),
4364 _('CONFIG')),
4365 ('', 'debug', None, _('enable debugging output')),
4366 ('', 'debugger', None, _('start debugger')),
4367 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4368 _('ENCODE')),
4369 ('', 'encodingmode', encoding.encodingmode,
4370 _('set the charset encoding mode'), _('MODE')),
4371 ('', 'traceback', None, _('always print a traceback on exception')),
4372 ('', 'time', None, _('time how long the command takes')),
4373 ('', 'profile', None, _('print command execution profile')),
4374 ('', 'version', None, _('output version information and exit')),
4375 ('h', 'help', None, _('display help and exit')),
4376 ]
4377
4378 dryrunopts = [('n', 'dry-run', None,
4379 _('do not perform actions, just print output'))]
4380
4381 remoteopts = [
4382 ('e', 'ssh', '',
4383 _('specify ssh command to use'), _('CMD')),
4384 ('', 'remotecmd', '',
4385 _('specify hg command to run on the remote side'), _('CMD')),
4386 ('', 'insecure', None,
4387 _('do not verify server certificate (ignoring web.cacerts config)')),
4388 ]
4389
4390 walkopts = [
4391 ('I', 'include', [],
4392 _('include names matching the given patterns'), _('PATTERN')),
4393 ('X', 'exclude', [],
4394 _('exclude names matching the given patterns'), _('PATTERN')),
4395 ]
4396
4397 commitopts = [
4398 ('m', 'message', '',
4399 _('use text as commit message'), _('TEXT')),
4400 ('l', 'logfile', '',
4401 _('read commit message from file'), _('FILE')),
4402 ]
4403
4404 commitopts2 = [
4405 ('d', 'date', '',
4406 _('record the specified date as commit date'), _('DATE')),
4407 ('u', 'user', '',
4408 _('record the specified user as committer'), _('USER')),
4409 ]
4410
4411 templateopts = [
4412 ('', 'style', '',
4413 _('display using template map file'), _('STYLE')),
4414 ('', 'template', '',
4415 _('display with template'), _('TEMPLATE')),
4416 ]
4417
4418 logopts = [
4419 ('p', 'patch', None, _('show patch')),
4420 ('g', 'git', None, _('use git extended diff format')),
4421 ('l', 'limit', '',
4422 _('limit number of changes displayed'), _('NUM')),
4423 ('M', 'no-merges', None, _('do not show merges')),
4424 ('', 'stat', None, _('output diffstat-style summary of changes')),
4425 ] + templateopts
4426
4427 diffopts = [
4428 ('a', 'text', None, _('treat all files as text')),
4429 ('g', 'git', None, _('use git extended diff format')),
4430 ('', 'nodates', None, _('omit dates from diff headers'))
4431 ]
4432
4433 diffopts2 = [
4434 ('p', 'show-function', None, _('show which function each change is in')),
4435 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4436 ('w', 'ignore-all-space', None,
4437 _('ignore white space when comparing lines')),
4438 ('b', 'ignore-space-change', None,
4439 _('ignore changes in the amount of white space')),
4440 ('B', 'ignore-blank-lines', None,
4441 _('ignore changes whose lines are all blank')),
4442 ('U', 'unified', '',
4443 _('number of lines of context to show'), _('NUM')),
4444 ('', 'stat', None, _('output diffstat-style summary of changes')),
4445 ]
4446
4447 similarityopts = [
4448 ('s', 'similarity', '',
4449 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4450 ]
4451
4452 subrepoopts = [
4453 ('S', 'subrepos', None,
4454 _('recurse into subrepositories'))
4455 ]
4456
4457 table = {
4458 "^add": (add, walkopts + subrepoopts + dryrunopts,
4459 _('[OPTION]... [FILE]...')),
4460 "addremove":
4461 (addremove, similarityopts + walkopts + dryrunopts,
4462 _('[OPTION]... [FILE]...')),
4463 "^annotate|blame":
4464 (annotate,
4465 [('r', 'rev', '',
4466 _('annotate the specified revision'), _('REV')),
4467 ('', 'follow', None,
4468 _('follow copies/renames and list the filename (DEPRECATED)')),
4469 ('', 'no-follow', None, _("don't follow copies and renames")),
4470 ('a', 'text', None, _('treat all files as text')),
4471 ('u', 'user', None, _('list the author (long with -v)')),
4472 ('f', 'file', None, _('list the filename')),
4473 ('d', 'date', None, _('list the date (short with -q)')),
4474 ('n', 'number', None, _('list the revision number (default)')),
4475 ('c', 'changeset', None, _('list the changeset')),
4476 ('l', 'line-number', None,
4477 _('show line number at the first appearance'))
4478 ] + walkopts,
4479 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4480 "archive":
4481 (archive,
4482 [('', 'no-decode', None, _('do not pass files through decoders')),
4483 ('p', 'prefix', '',
4484 _('directory prefix for files in archive'), _('PREFIX')),
4485 ('r', 'rev', '',
4486 _('revision to distribute'), _('REV')),
4487 ('t', 'type', '',
4488 _('type of distribution to create'), _('TYPE')),
4489 ] + subrepoopts + walkopts,
4490 _('[OPTION]... DEST')),
4491 "backout":
4492 (backout,
4493 [('', 'merge', None,
4494 _('merge with old dirstate parent after backout')),
4495 ('', 'parent', '',
4496 _('parent to choose when backing out merge'), _('REV')),
4497 ('t', 'tool', '',
4498 _('specify merge tool')),
4499 ('r', 'rev', '',
4500 _('revision to backout'), _('REV')),
4501 ] + walkopts + commitopts + commitopts2,
4502 _('[OPTION]... [-r] REV')),
4503 "bisect":
4504 (bisect,
4505 [('r', 'reset', False, _('reset bisect state')),
4506 ('g', 'good', False, _('mark changeset good')),
4507 ('b', 'bad', False, _('mark changeset bad')),
4508 ('s', 'skip', False, _('skip testing changeset')),
4509 ('e', 'extend', False, _('extend the bisect range')),
4510 ('c', 'command', '',
4511 _('use command to check changeset state'), _('CMD')),
4512 ('U', 'noupdate', False, _('do not update to target'))],
4513 _("[-gbsr] [-U] [-c CMD] [REV]")),
4514 "bookmarks":
4515 (bookmark,
4516 [('f', 'force', False, _('force')),
4517 ('r', 'rev', '', _('revision'), _('REV')),
4518 ('d', 'delete', False, _('delete a given bookmark')),
4519 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
4520 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
4521 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]')),
4522 "branch":
4523 (branch,
4524 [('f', 'force', None,
4525 _('set branch name even if it shadows an existing branch')),
4526 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4527 _('[-fC] [NAME]')),
4528 "branches":
4529 (branches,
4530 [('a', 'active', False,
4531 _('show only branches that have unmerged heads')),
4532 ('c', 'closed', False,
4533 _('show normal and closed branches'))],
4534 _('[-ac]')),
4535 "bundle":
4536 (bundle,
4537 [('f', 'force', None,
4538 _('run even when the destination is unrelated')),
4539 ('r', 'rev', [],
4540 _('a changeset intended to be added to the destination'),
4541 _('REV')),
4542 ('b', 'branch', [],
4543 _('a specific branch you would like to bundle'),
4544 _('BRANCH')),
4545 ('', 'base', [],
4546 _('a base changeset assumed to be available at the destination'),
4547 _('REV')),
4548 ('a', 'all', None, _('bundle all changesets in the repository')),
4549 ('t', 'type', 'bzip2',
4550 _('bundle compression type to use'), _('TYPE')),
4551 ] + remoteopts,
4552 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4553 "cat":
4554 (cat,
4555 [('o', 'output', '',
4556 _('print output to file with formatted name'), _('FORMAT')),
4557 ('r', 'rev', '',
4558 _('print the given revision'), _('REV')),
4559 ('', 'decode', None, _('apply any matching decode filter')),
4560 ] + walkopts,
4561 _('[OPTION]... FILE...')),
4562 "^clone":
4563 (clone,
4564 [('U', 'noupdate', None,
4565 _('the clone will include an empty working copy (only a repository)')),
4566 ('u', 'updaterev', '',
4567 _('revision, tag or branch to check out'), _('REV')),
4568 ('r', 'rev', [],
4569 _('include the specified changeset'), _('REV')),
4570 ('b', 'branch', [],
4571 _('clone only the specified branch'), _('BRANCH')),
4572 ('', 'pull', None, _('use pull protocol to copy metadata')),
4573 ('', 'uncompressed', None,
4574 _('use uncompressed transfer (fast over LAN)')),
4575 ] + remoteopts,
4576 _('[OPTION]... SOURCE [DEST]')),
4577 "^commit|ci":
4578 (commit,
4579 [('A', 'addremove', None,
4580 _('mark new/missing files as added/removed before committing')),
4581 ('', 'close-branch', None,
4582 _('mark a branch as closed, hiding it from the branch list')),
4583 ] + walkopts + commitopts + commitopts2,
4584 _('[OPTION]... [FILE]...')),
4585 "copy|cp":
4586 (copy,
4587 [('A', 'after', None, _('record a copy that has already occurred')),
4588 ('f', 'force', None,
4589 _('forcibly copy over an existing managed file')),
4590 ] + walkopts + dryrunopts,
4591 _('[OPTION]... [SOURCE]... DEST')),
4592 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4593 "debugbuilddag":
4594 (debugbuilddag,
4595 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4596 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4597 ('n', 'new-file', None, _('add new file at each rev')),
4598 ],
4599 _('[OPTION]... [TEXT]')),
4600 "debugbundle":
4601 (debugbundle,
4602 [('a', 'all', None, _('show all details')),
4603 ],
4604 _('FILE')),
4605 "debugcheckstate": (debugcheckstate, [], ''),
4606 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4607 "debugcomplete":
4608 (debugcomplete,
4609 [('o', 'options', None, _('show the command options'))],
4610 _('[-o] CMD')),
4611 "debugdag":
4612 (debugdag,
4613 [('t', 'tags', None, _('use tags as labels')),
4614 ('b', 'branches', None, _('annotate with branch names')),
4615 ('', 'dots', None, _('use dots for runs')),
4616 ('s', 'spaces', None, _('separate elements by spaces')),
4617 ],
4618 _('[OPTION]... [FILE [REV]...]')),
4619 "debugdate":
4620 (debugdate,
4621 [('e', 'extended', None, _('try extended date formats'))],
4622 _('[-e] DATE [RANGE]')),
4623 "debugdata": (debugdata, [], _('FILE REV')),
4624 "debugdiscovery": (debugdiscovery,
4625 [('', 'old', None,
4626 _('use old-style discovery')),
4627 ('', 'nonheads', None,
4628 _('use old-style discovery with non-heads included')),
4629 ] + remoteopts,
4630 _('[-l REV] [-r REV] [-b BRANCH]...'
4631 ' [OTHER]')),
4632 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4633 "debuggetbundle":
4634 (debuggetbundle,
4635 [('H', 'head', [], _('id of head node'), _('ID')),
4636 ('C', 'common', [], _('id of common node'), _('ID')),
4637 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
4638 ],
4639 _('REPO FILE [-H|-C ID]...')),
4640 "debugignore": (debugignore, [], ''),
4641 "debugindex": (debugindex,
4642 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4643 _('FILE')),
4644 "debugindexdot": (debugindexdot, [], _('FILE')),
4645 "debuginstall": (debuginstall, [], ''),
4646 "debugknown": (debugknown, [], _('REPO ID...')),
4647 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4648 "debugrebuildstate":
4649 (debugrebuildstate,
4650 [('r', 'rev', '',
4651 _('revision to rebuild to'), _('REV'))],
4652 _('[-r REV] [REV]')),
4653 "debugrename":
4654 (debugrename,
4655 [('r', 'rev', '',
4656 _('revision to debug'), _('REV'))],
4657 _('[-r REV] FILE')),
4658 "debugrevspec":
4659 (debugrevspec, [], ('REVSPEC')),
4660 "debugsetparents":
4661 (debugsetparents, [], _('REV1 [REV2]')),
4662 "debugstate":
4663 (debugstate,
4664 [('', 'nodates', None, _('do not display the saved mtime')),
4665 ('', 'datesort', None, _('sort by saved mtime'))],
4666 _('[OPTION]...')),
4667 "debugsub":
4668 (debugsub,
4669 [('r', 'rev', '',
4670 _('revision to check'), _('REV'))],
4671 _('[-r REV] [REV]')),
4672 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4673 "debugwireargs":
4674 (debugwireargs,
4675 [('', 'three', '', 'three'),
4676 ('', 'four', '', 'four'),
4677 ('', 'five', '', 'five'),
4678 ] + remoteopts,
4679 _('REPO [OPTIONS]... [ONE [TWO]]')),
4680 "^diff":
4681 (diff,
4682 [('r', 'rev', [],
4683 _('revision'), _('REV')),
4684 ('c', 'change', '',
4685 _('change made by revision'), _('REV'))
4686 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4687 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4688 "^export":
4689 (export,
4690 [('o', 'output', '',
4691 _('print output to file with formatted name'), _('FORMAT')),
4692 ('', 'switch-parent', None, _('diff against the second parent')),
4693 ('r', 'rev', [],
4694 _('revisions to export'), _('REV')),
4695 ] + diffopts,
4696 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4697 "^forget":
4698 (forget,
4699 [] + walkopts,
4700 _('[OPTION]... FILE...')),
4701 "grep":
4702 (grep,
4703 [('0', 'print0', None, _('end fields with NUL')),
4704 ('', 'all', None, _('print all revisions that match')),
4705 ('a', 'text', None, _('treat all files as text')),
4706 ('f', 'follow', None,
4707 _('follow changeset history,'
4708 ' or file history across copies and renames')),
4709 ('i', 'ignore-case', None, _('ignore case when matching')),
4710 ('l', 'files-with-matches', None,
4711 _('print only filenames and revisions that match')),
4712 ('n', 'line-number', None, _('print matching line numbers')),
4713 ('r', 'rev', [],
4714 _('only search files changed within revision range'), _('REV')),
4715 ('u', 'user', None, _('list the author (long with -v)')),
4716 ('d', 'date', None, _('list the date (short with -q)')),
4717 ] + walkopts,
4718 _('[OPTION]... PATTERN [FILE]...')),
4719 "heads":
4720 (heads,
4721 [('r', 'rev', '',
4722 _('show only heads which are descendants of STARTREV'),
4723 _('STARTREV')),
4724 ('t', 'topo', False, _('show topological heads only')),
4725 ('a', 'active', False,
4726 _('show active branchheads only (DEPRECATED)')),
4727 ('c', 'closed', False,
4728 _('show normal and closed branch heads')),
4729 ] + templateopts,
4730 _('[-ac] [-r STARTREV] [REV]...')),
4731 "help": (help_,
4732 [('e', 'extension', None, _('show only help for extensions')),
4733 ('c', 'command', None, _('show only help for commands'))],
4734 _('[-ec] [TOPIC]')),
4735 "identify|id":
4736 (identify,
4737 [('r', 'rev', '',
4738 _('identify the specified revision'), _('REV')),
4739 ('n', 'num', None, _('show local revision number')),
4740 ('i', 'id', None, _('show global revision id')),
4741 ('b', 'branch', None, _('show branch')),
4742 ('t', 'tags', None, _('show tags')),
4743 ('B', 'bookmarks', None, _('show bookmarks'))],
4744 _('[-nibtB] [-r REV] [SOURCE]')),
4745 "import|patch":
4746 (import_,
4747 [('p', 'strip', 1,
4748 _('directory strip option for patch. This has the same '
4749 'meaning as the corresponding patch option'),
4750 _('NUM')),
4751 ('b', 'base', '',
4752 _('base path'), _('PATH')),
4753 ('f', 'force', None,
4754 _('skip check for outstanding uncommitted changes')),
4755 ('', 'no-commit', None,
4756 _("don't commit, just update the working directory")),
4757 ('', 'exact', None,
4758 _('apply patch to the nodes from which it was generated')),
4759 ('', 'import-branch', None,
4760 _('use any branch information in patch (implied by --exact)'))] +
4761 commitopts + commitopts2 + similarityopts,
4762 _('[OPTION]... PATCH...')),
4763 "incoming|in":
4764 (incoming,
4765 [('f', 'force', None,
4766 _('run even if remote repository is unrelated')),
4767 ('n', 'newest-first', None, _('show newest record first')),
4768 ('', 'bundle', '',
4769 _('file to store the bundles into'), _('FILE')),
4770 ('r', 'rev', [],
4771 _('a remote changeset intended to be added'), _('REV')),
4772 ('B', 'bookmarks', False, _("compare bookmarks")),
4773 ('b', 'branch', [],
4774 _('a specific branch you would like to pull'), _('BRANCH')),
4775 ] + logopts + remoteopts + subrepoopts,
4776 _('[-p] [-n] [-M] [-f] [-r REV]...'
4777 ' [--bundle FILENAME] [SOURCE]')),
4778 "^init":
4779 (init,
4780 remoteopts,
4781 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4782 "locate":
4783 (locate,
4784 [('r', 'rev', '',
4785 _('search the repository as it is in REV'), _('REV')),
4786 ('0', 'print0', None,
4787 _('end filenames with NUL, for use with xargs')),
4788 ('f', 'fullpath', None,
4789 _('print complete paths from the filesystem root')),
4790 ] + walkopts,
4791 _('[OPTION]... [PATTERN]...')),
4792 "^log|history":
4793 (log,
4794 [('f', 'follow', None,
4795 _('follow changeset history,'
4796 ' or file history across copies and renames')),
4797 ('', 'follow-first', None,
4798 _('only follow the first parent of merge changesets')),
4799 ('d', 'date', '',
4800 _('show revisions matching date spec'), _('DATE')),
4801 ('C', 'copies', None, _('show copied files')),
4802 ('k', 'keyword', [],
4803 _('do case-insensitive search for a given text'), _('TEXT')),
4804 ('r', 'rev', [],
4805 _('show the specified revision or range'), _('REV')),
4806 ('', 'removed', None, _('include revisions where files were removed')),
4807 ('m', 'only-merges', None, _('show only merges')),
4808 ('u', 'user', [],
4809 _('revisions committed by user'), _('USER')),
4810 ('', 'only-branch', [],
4811 _('show only changesets within the given named branch (DEPRECATED)'),
4812 _('BRANCH')),
4813 ('b', 'branch', [],
4814 _('show changesets within the given named branch'), _('BRANCH')),
4815 ('P', 'prune', [],
4816 _('do not display revision or any of its ancestors'), _('REV')),
4817 ] + logopts + walkopts,
4818 _('[OPTION]... [FILE]')),
4819 "manifest":
4820 (manifest,
4821 [('r', 'rev', '',
4822 _('revision to display'), _('REV'))],
4823 _('[-r REV]')),
4824 "^merge":
4825 (merge,
4826 [('f', 'force', None, _('force a merge with outstanding changes')),
4827 ('t', 'tool', '', _('specify merge tool')),
4828 ('r', 'rev', '',
4829 _('revision to merge'), _('REV')),
4830 ('P', 'preview', None,
4831 _('review revisions to merge (no merge is performed)'))],
4832 _('[-P] [-f] [[-r] REV]')),
4833 "outgoing|out":
4834 (outgoing,
4835 [('f', 'force', None,
4836 _('run even when the destination is unrelated')),
4837 ('r', 'rev', [],
4838 _('a changeset intended to be included in the destination'),
4839 _('REV')),
4840 ('n', 'newest-first', None, _('show newest record first')),
4841 ('B', 'bookmarks', False, _("compare bookmarks")),
4842 ('b', 'branch', [],
4843 _('a specific branch you would like to push'), _('BRANCH')),
4844 ] + logopts + remoteopts + subrepoopts,
4845 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4846 "parents":
4847 (parents,
4848 [('r', 'rev', '',
4849 _('show parents of the specified revision'), _('REV')),
4850 ] + templateopts,
4851 _('[-r REV] [FILE]')),
4852 "paths": (paths, [], _('[NAME]')),
4853 "^pull":
4854 (pull,
4855 [('u', 'update', None,
4856 _('update to new branch head if changesets were pulled')),
4857 ('f', 'force', None,
4858 _('run even when remote repository is unrelated')),
4859 ('r', 'rev', [],
4860 _('a remote changeset intended to be added'), _('REV')),
4861 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4862 ('b', 'branch', [],
4863 _('a specific branch you would like to pull'), _('BRANCH')),
4864 ] + remoteopts,
4865 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4866 "^push":
4867 (push,
4868 [('f', 'force', None, _('force push')),
4869 ('r', 'rev', [],
4870 _('a changeset intended to be included in the destination'),
4871 _('REV')),
4872 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4873 ('b', 'branch', [],
4874 _('a specific branch you would like to push'), _('BRANCH')),
4875 ('', 'new-branch', False, _('allow pushing a new branch')),
4876 ] + remoteopts,
4877 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4878 "recover": (recover, []),
4879 "^remove|rm":
4880 (remove,
4881 [('A', 'after', None, _('record delete for missing files')),
4882 ('f', 'force', None,
4883 _('remove (and delete) file even if added or modified')),
4884 ] + walkopts,
4885 _('[OPTION]... FILE...')),
4886 "rename|move|mv":
4887 (rename,
4888 [('A', 'after', None, _('record a rename that has already occurred')),
4889 ('f', 'force', None,
4890 _('forcibly copy over an existing managed file')),
4891 ] + walkopts + dryrunopts,
4892 _('[OPTION]... SOURCE... DEST')),
4893 "resolve":
4894 (resolve,
4895 [('a', 'all', None, _('select all unresolved files')),
4896 ('l', 'list', None, _('list state of files needing merge')),
4897 ('m', 'mark', None, _('mark files as resolved')),
4898 ('u', 'unmark', None, _('mark files as unresolved')),
4899 ('t', 'tool', '', _('specify merge tool')),
4900 ('n', 'no-status', None, _('hide status prefix'))]
4901 + walkopts,
4902 _('[OPTION]... [FILE]...')),
4903 "revert":
4904 (revert,
4905 [('a', 'all', None, _('revert all changes when no arguments given')),
4906 ('d', 'date', '',
4907 _('tipmost revision matching date'), _('DATE')),
4908 ('r', 'rev', '',
4909 _('revert to the specified revision'), _('REV')),
4910 ('', 'no-backup', None, _('do not save backup copies of files')),
4911 ] + walkopts + dryrunopts,
4912 _('[OPTION]... [-r REV] [NAME]...')),
4913 "rollback": (rollback, dryrunopts),
4914 "root": (root, []),
4915 "^serve":
4916 (serve,
4917 [('A', 'accesslog', '',
4918 _('name of access log file to write to'), _('FILE')),
4919 ('d', 'daemon', None, _('run server in background')),
4920 ('', 'daemon-pipefds', '',
4921 _('used internally by daemon mode'), _('NUM')),
4922 ('E', 'errorlog', '',
4923 _('name of error log file to write to'), _('FILE')),
4924 # use string type, then we can check if something was passed
4925 ('p', 'port', '',
4926 _('port to listen on (default: 8000)'), _('PORT')),
4927 ('a', 'address', '',
4928 _('address to listen on (default: all interfaces)'), _('ADDR')),
4929 ('', 'prefix', '',
4930 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4931 ('n', 'name', '',
4932 _('name to show in web pages (default: working directory)'),
4933 _('NAME')),
4934 ('', 'web-conf', '',
4935 _('name of the hgweb config file (see "hg help hgweb")'),
4936 _('FILE')),
4937 ('', 'webdir-conf', '',
4938 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4939 ('', 'pid-file', '',
4940 _('name of file to write process ID to'), _('FILE')),
4941 ('', 'stdio', None, _('for remote clients')),
4942 ('t', 'templates', '',
4943 _('web templates to use'), _('TEMPLATE')),
4944 ('', 'style', '',
4945 _('template style to use'), _('STYLE')),
4946 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4947 ('', 'certificate', '',
4948 _('SSL certificate file'), _('FILE'))],
4949 _('[OPTION]...')),
4950 "showconfig|debugconfig":
4951 (showconfig,
4952 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4953 _('[-u] [NAME]...')),
4954 "^summary|sum":
4955 (summary,
4956 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4957 "^status|st":
4958 (status,
4959 [('A', 'all', None, _('show status of all files')),
4960 ('m', 'modified', None, _('show only modified files')),
4961 ('a', 'added', None, _('show only added files')),
4962 ('r', 'removed', None, _('show only removed files')),
4963 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4964 ('c', 'clean', None, _('show only files without changes')),
4965 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4966 ('i', 'ignored', None, _('show only ignored files')),
4967 ('n', 'no-status', None, _('hide status prefix')),
4968 ('C', 'copies', None, _('show source of copied files')),
4969 ('0', 'print0', None,
4970 _('end filenames with NUL, for use with xargs')),
4971 ('', 'rev', [],
4972 _('show difference from revision'), _('REV')),
4973 ('', 'change', '',
4974 _('list the changed files of a revision'), _('REV')),
4975 ] + walkopts + subrepoopts,
4976 _('[OPTION]... [FILE]...')),
4977 "tag":
4978 (tag,
4979 [('f', 'force', None, _('force tag')),
4980 ('l', 'local', None, _('make the tag local')),
4981 ('r', 'rev', '',
4982 _('revision to tag'), _('REV')),
4983 ('', 'remove', None, _('remove a tag')),
4984 # -l/--local is already there, commitopts cannot be used
4985 ('e', 'edit', None, _('edit commit message')),
4986 ('m', 'message', '',
4987 _('use <text> as commit message'), _('TEXT')),
4988 ] + commitopts2,
4989 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4990 "tags": (tags, [], ''),
4991 "tip":
4992 (tip,
4993 [('p', 'patch', None, _('show patch')),
4994 ('g', 'git', None, _('use git extended diff format')),
4995 ] + templateopts,
4996 _('[-p] [-g]')),
4997 "unbundle":
4998 (unbundle,
4999 [('u', 'update', None,
5000 _('update to new branch head if changesets were unbundled'))],
5001 _('[-u] FILE...')),
5002 "^update|up|checkout|co":
5003 (update,
5004 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5005 ('c', 'check', None,
5006 _('update across branches if no uncommitted changes')),
5007 ('d', 'date', '',
5008 _('tipmost revision matching date'), _('DATE')),
5009 ('r', 'rev', '',
5010 _('revision'), _('REV'))],
5011 _('[-c] [-C] [-d DATE] [[-r] REV]')),
5012 "verify": (verify, []),
5013 "version": (version_, []),
5014 }
5015
5016 norepo = ("clone init version help debugcommands debugcomplete"
4884 norepo = ("clone init version help debugcommands debugcomplete"
5017 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
4885 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5018 " debugknown debuggetbundle debugbundle")
4886 " debugknown debuggetbundle debugbundle")
5019 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4887 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5020 " debugdata debugindex debugindexdot")
4888 " debugdata debugindex debugindexdot")
General Comments 0
You need to be logged in to leave comments. Login now