##// END OF EJS Templates
log: follow filenames through renames (issue647)...
Mads Kiilerich -
r11488:f786fc4b 1.6 stable
parent child Browse files
Show More
@@ -1,1241 +1,1243
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from i18n import _
9 from i18n import _
10 import os, sys, errno, re, glob, tempfile
10 import os, sys, errno, re, glob, tempfile
11 import util, templater, patch, error, encoding, templatekw
11 import util, templater, patch, error, encoding, templatekw
12 import match as _match
12 import match as _match
13 import similar, revset
13 import similar, revset
14
14
15 revrangesep = ':'
15 revrangesep = ':'
16
16
17 def parsealiases(cmd):
17 def parsealiases(cmd):
18 return cmd.lstrip("^").split("|")
18 return cmd.lstrip("^").split("|")
19
19
20 def findpossible(cmd, table, strict=False):
20 def findpossible(cmd, table, strict=False):
21 """
21 """
22 Return cmd -> (aliases, command table entry)
22 Return cmd -> (aliases, command table entry)
23 for each matching command.
23 for each matching command.
24 Return debug commands (or their aliases) only if no normal command matches.
24 Return debug commands (or their aliases) only if no normal command matches.
25 """
25 """
26 choice = {}
26 choice = {}
27 debugchoice = {}
27 debugchoice = {}
28 for e in table.keys():
28 for e in table.keys():
29 aliases = parsealiases(e)
29 aliases = parsealiases(e)
30 found = None
30 found = None
31 if cmd in aliases:
31 if cmd in aliases:
32 found = cmd
32 found = cmd
33 elif not strict:
33 elif not strict:
34 for a in aliases:
34 for a in aliases:
35 if a.startswith(cmd):
35 if a.startswith(cmd):
36 found = a
36 found = a
37 break
37 break
38 if found is not None:
38 if found is not None:
39 if aliases[0].startswith("debug") or found.startswith("debug"):
39 if aliases[0].startswith("debug") or found.startswith("debug"):
40 debugchoice[found] = (aliases, table[e])
40 debugchoice[found] = (aliases, table[e])
41 else:
41 else:
42 choice[found] = (aliases, table[e])
42 choice[found] = (aliases, table[e])
43
43
44 if not choice and debugchoice:
44 if not choice and debugchoice:
45 choice = debugchoice
45 choice = debugchoice
46
46
47 return choice
47 return choice
48
48
49 def findcmd(cmd, table, strict=True):
49 def findcmd(cmd, table, strict=True):
50 """Return (aliases, command table entry) for command string."""
50 """Return (aliases, command table entry) for command string."""
51 choice = findpossible(cmd, table, strict)
51 choice = findpossible(cmd, table, strict)
52
52
53 if cmd in choice:
53 if cmd in choice:
54 return choice[cmd]
54 return choice[cmd]
55
55
56 if len(choice) > 1:
56 if len(choice) > 1:
57 clist = choice.keys()
57 clist = choice.keys()
58 clist.sort()
58 clist.sort()
59 raise error.AmbiguousCommand(cmd, clist)
59 raise error.AmbiguousCommand(cmd, clist)
60
60
61 if choice:
61 if choice:
62 return choice.values()[0]
62 return choice.values()[0]
63
63
64 raise error.UnknownCommand(cmd)
64 raise error.UnknownCommand(cmd)
65
65
66 def findrepo(p):
66 def findrepo(p):
67 while not os.path.isdir(os.path.join(p, ".hg")):
67 while not os.path.isdir(os.path.join(p, ".hg")):
68 oldp, p = p, os.path.dirname(p)
68 oldp, p = p, os.path.dirname(p)
69 if p == oldp:
69 if p == oldp:
70 return None
70 return None
71
71
72 return p
72 return p
73
73
74 def bail_if_changed(repo):
74 def bail_if_changed(repo):
75 if repo.dirstate.parents()[1] != nullid:
75 if repo.dirstate.parents()[1] != nullid:
76 raise util.Abort(_('outstanding uncommitted merge'))
76 raise util.Abort(_('outstanding uncommitted merge'))
77 modified, added, removed, deleted = repo.status()[:4]
77 modified, added, removed, deleted = repo.status()[:4]
78 if modified or added or removed or deleted:
78 if modified or added or removed or deleted:
79 raise util.Abort(_("outstanding uncommitted changes"))
79 raise util.Abort(_("outstanding uncommitted changes"))
80
80
81 def logmessage(opts):
81 def logmessage(opts):
82 """ get the log message according to -m and -l option """
82 """ get the log message according to -m and -l option """
83 message = opts.get('message')
83 message = opts.get('message')
84 logfile = opts.get('logfile')
84 logfile = opts.get('logfile')
85
85
86 if message and logfile:
86 if message and logfile:
87 raise util.Abort(_('options --message and --logfile are mutually '
87 raise util.Abort(_('options --message and --logfile are mutually '
88 'exclusive'))
88 'exclusive'))
89 if not message and logfile:
89 if not message and logfile:
90 try:
90 try:
91 if logfile == '-':
91 if logfile == '-':
92 message = sys.stdin.read()
92 message = sys.stdin.read()
93 else:
93 else:
94 message = open(logfile).read()
94 message = open(logfile).read()
95 except IOError, inst:
95 except IOError, inst:
96 raise util.Abort(_("can't read commit message '%s': %s") %
96 raise util.Abort(_("can't read commit message '%s': %s") %
97 (logfile, inst.strerror))
97 (logfile, inst.strerror))
98 return message
98 return message
99
99
100 def loglimit(opts):
100 def loglimit(opts):
101 """get the log limit according to option -l/--limit"""
101 """get the log limit according to option -l/--limit"""
102 limit = opts.get('limit')
102 limit = opts.get('limit')
103 if limit:
103 if limit:
104 try:
104 try:
105 limit = int(limit)
105 limit = int(limit)
106 except ValueError:
106 except ValueError:
107 raise util.Abort(_('limit must be a positive integer'))
107 raise util.Abort(_('limit must be a positive integer'))
108 if limit <= 0:
108 if limit <= 0:
109 raise util.Abort(_('limit must be positive'))
109 raise util.Abort(_('limit must be positive'))
110 else:
110 else:
111 limit = None
111 limit = None
112 return limit
112 return limit
113
113
114 def revpair(repo, revs):
114 def revpair(repo, revs):
115 '''return pair of nodes, given list of revisions. second item can
115 '''return pair of nodes, given list of revisions. second item can
116 be None, meaning use working dir.'''
116 be None, meaning use working dir.'''
117
117
118 def revfix(repo, val, defval):
118 def revfix(repo, val, defval):
119 if not val and val != 0 and defval is not None:
119 if not val and val != 0 and defval is not None:
120 val = defval
120 val = defval
121 return repo.lookup(val)
121 return repo.lookup(val)
122
122
123 if not revs:
123 if not revs:
124 return repo.dirstate.parents()[0], None
124 return repo.dirstate.parents()[0], None
125 end = None
125 end = None
126 if len(revs) == 1:
126 if len(revs) == 1:
127 if revrangesep in revs[0]:
127 if revrangesep in revs[0]:
128 start, end = revs[0].split(revrangesep, 1)
128 start, end = revs[0].split(revrangesep, 1)
129 start = revfix(repo, start, 0)
129 start = revfix(repo, start, 0)
130 end = revfix(repo, end, len(repo) - 1)
130 end = revfix(repo, end, len(repo) - 1)
131 else:
131 else:
132 start = revfix(repo, revs[0], None)
132 start = revfix(repo, revs[0], None)
133 elif len(revs) == 2:
133 elif len(revs) == 2:
134 if revrangesep in revs[0] or revrangesep in revs[1]:
134 if revrangesep in revs[0] or revrangesep in revs[1]:
135 raise util.Abort(_('too many revisions specified'))
135 raise util.Abort(_('too many revisions specified'))
136 start = revfix(repo, revs[0], None)
136 start = revfix(repo, revs[0], None)
137 end = revfix(repo, revs[1], None)
137 end = revfix(repo, revs[1], None)
138 else:
138 else:
139 raise util.Abort(_('too many revisions specified'))
139 raise util.Abort(_('too many revisions specified'))
140 return start, end
140 return start, end
141
141
142 def revrange(repo, revs):
142 def revrange(repo, revs):
143 """Yield revision as strings from a list of revision specifications."""
143 """Yield revision as strings from a list of revision specifications."""
144
144
145 def revfix(repo, val, defval):
145 def revfix(repo, val, defval):
146 if not val and val != 0 and defval is not None:
146 if not val and val != 0 and defval is not None:
147 return defval
147 return defval
148 return repo.changelog.rev(repo.lookup(val))
148 return repo.changelog.rev(repo.lookup(val))
149
149
150 seen, l = set(), []
150 seen, l = set(), []
151 for spec in revs:
151 for spec in revs:
152 # attempt to parse old-style ranges first to deal with
152 # attempt to parse old-style ranges first to deal with
153 # things like old-tag which contain query metacharacters
153 # things like old-tag which contain query metacharacters
154 try:
154 try:
155 if revrangesep in spec:
155 if revrangesep in spec:
156 start, end = spec.split(revrangesep, 1)
156 start, end = spec.split(revrangesep, 1)
157 start = revfix(repo, start, 0)
157 start = revfix(repo, start, 0)
158 end = revfix(repo, end, len(repo) - 1)
158 end = revfix(repo, end, len(repo) - 1)
159 step = start > end and -1 or 1
159 step = start > end and -1 or 1
160 for rev in xrange(start, end + step, step):
160 for rev in xrange(start, end + step, step):
161 if rev in seen:
161 if rev in seen:
162 continue
162 continue
163 seen.add(rev)
163 seen.add(rev)
164 l.append(rev)
164 l.append(rev)
165 continue
165 continue
166 elif spec and spec in repo: # single unquoted rev
166 elif spec and spec in repo: # single unquoted rev
167 rev = revfix(repo, spec, None)
167 rev = revfix(repo, spec, None)
168 if rev in seen:
168 if rev in seen:
169 continue
169 continue
170 seen.add(rev)
170 seen.add(rev)
171 l.append(rev)
171 l.append(rev)
172 continue
172 continue
173 except error.RepoLookupError:
173 except error.RepoLookupError:
174 pass
174 pass
175
175
176 # fall through to new-style queries if old-style fails
176 # fall through to new-style queries if old-style fails
177 m = revset.match(spec)
177 m = revset.match(spec)
178 for r in m(repo, range(len(repo))):
178 for r in m(repo, range(len(repo))):
179 if r not in seen:
179 if r not in seen:
180 l.append(r)
180 l.append(r)
181 seen.update(l)
181 seen.update(l)
182
182
183 return l
183 return l
184
184
185 def make_filename(repo, pat, node,
185 def make_filename(repo, pat, node,
186 total=None, seqno=None, revwidth=None, pathname=None):
186 total=None, seqno=None, revwidth=None, pathname=None):
187 node_expander = {
187 node_expander = {
188 'H': lambda: hex(node),
188 'H': lambda: hex(node),
189 'R': lambda: str(repo.changelog.rev(node)),
189 'R': lambda: str(repo.changelog.rev(node)),
190 'h': lambda: short(node),
190 'h': lambda: short(node),
191 }
191 }
192 expander = {
192 expander = {
193 '%': lambda: '%',
193 '%': lambda: '%',
194 'b': lambda: os.path.basename(repo.root),
194 'b': lambda: os.path.basename(repo.root),
195 }
195 }
196
196
197 try:
197 try:
198 if node:
198 if node:
199 expander.update(node_expander)
199 expander.update(node_expander)
200 if node:
200 if node:
201 expander['r'] = (lambda:
201 expander['r'] = (lambda:
202 str(repo.changelog.rev(node)).zfill(revwidth or 0))
202 str(repo.changelog.rev(node)).zfill(revwidth or 0))
203 if total is not None:
203 if total is not None:
204 expander['N'] = lambda: str(total)
204 expander['N'] = lambda: str(total)
205 if seqno is not None:
205 if seqno is not None:
206 expander['n'] = lambda: str(seqno)
206 expander['n'] = lambda: str(seqno)
207 if total is not None and seqno is not None:
207 if total is not None and seqno is not None:
208 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
208 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
209 if pathname is not None:
209 if pathname is not None:
210 expander['s'] = lambda: os.path.basename(pathname)
210 expander['s'] = lambda: os.path.basename(pathname)
211 expander['d'] = lambda: os.path.dirname(pathname) or '.'
211 expander['d'] = lambda: os.path.dirname(pathname) or '.'
212 expander['p'] = lambda: pathname
212 expander['p'] = lambda: pathname
213
213
214 newname = []
214 newname = []
215 patlen = len(pat)
215 patlen = len(pat)
216 i = 0
216 i = 0
217 while i < patlen:
217 while i < patlen:
218 c = pat[i]
218 c = pat[i]
219 if c == '%':
219 if c == '%':
220 i += 1
220 i += 1
221 c = pat[i]
221 c = pat[i]
222 c = expander[c]()
222 c = expander[c]()
223 newname.append(c)
223 newname.append(c)
224 i += 1
224 i += 1
225 return ''.join(newname)
225 return ''.join(newname)
226 except KeyError, inst:
226 except KeyError, inst:
227 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
227 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
228 inst.args[0])
228 inst.args[0])
229
229
230 def make_file(repo, pat, node=None,
230 def make_file(repo, pat, node=None,
231 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
231 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
232
232
233 writable = 'w' in mode or 'a' in mode
233 writable = 'w' in mode or 'a' in mode
234
234
235 if not pat or pat == '-':
235 if not pat or pat == '-':
236 return writable and sys.stdout or sys.stdin
236 return writable and sys.stdout or sys.stdin
237 if hasattr(pat, 'write') and writable:
237 if hasattr(pat, 'write') and writable:
238 return pat
238 return pat
239 if hasattr(pat, 'read') and 'r' in mode:
239 if hasattr(pat, 'read') and 'r' in mode:
240 return pat
240 return pat
241 return open(make_filename(repo, pat, node, total, seqno, revwidth,
241 return open(make_filename(repo, pat, node, total, seqno, revwidth,
242 pathname),
242 pathname),
243 mode)
243 mode)
244
244
245 def expandpats(pats):
245 def expandpats(pats):
246 if not util.expandglobs:
246 if not util.expandglobs:
247 return list(pats)
247 return list(pats)
248 ret = []
248 ret = []
249 for p in pats:
249 for p in pats:
250 kind, name = _match._patsplit(p, None)
250 kind, name = _match._patsplit(p, None)
251 if kind is None:
251 if kind is None:
252 try:
252 try:
253 globbed = glob.glob(name)
253 globbed = glob.glob(name)
254 except re.error:
254 except re.error:
255 globbed = [name]
255 globbed = [name]
256 if globbed:
256 if globbed:
257 ret.extend(globbed)
257 ret.extend(globbed)
258 continue
258 continue
259 ret.append(p)
259 ret.append(p)
260 return ret
260 return ret
261
261
262 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
262 def match(repo, pats=[], opts={}, globbed=False, default='relpath'):
263 if not globbed and default == 'relpath':
263 if not globbed and default == 'relpath':
264 pats = expandpats(pats or [])
264 pats = expandpats(pats or [])
265 m = _match.match(repo.root, repo.getcwd(), pats,
265 m = _match.match(repo.root, repo.getcwd(), pats,
266 opts.get('include'), opts.get('exclude'), default)
266 opts.get('include'), opts.get('exclude'), default)
267 def badfn(f, msg):
267 def badfn(f, msg):
268 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
268 repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
269 m.bad = badfn
269 m.bad = badfn
270 return m
270 return m
271
271
272 def matchall(repo):
272 def matchall(repo):
273 return _match.always(repo.root, repo.getcwd())
273 return _match.always(repo.root, repo.getcwd())
274
274
275 def matchfiles(repo, files):
275 def matchfiles(repo, files):
276 return _match.exact(repo.root, repo.getcwd(), files)
276 return _match.exact(repo.root, repo.getcwd(), files)
277
277
278 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
278 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
279 if dry_run is None:
279 if dry_run is None:
280 dry_run = opts.get('dry_run')
280 dry_run = opts.get('dry_run')
281 if similarity is None:
281 if similarity is None:
282 similarity = float(opts.get('similarity') or 0)
282 similarity = float(opts.get('similarity') or 0)
283 # we'd use status here, except handling of symlinks and ignore is tricky
283 # we'd use status here, except handling of symlinks and ignore is tricky
284 added, unknown, deleted, removed = [], [], [], []
284 added, unknown, deleted, removed = [], [], [], []
285 audit_path = util.path_auditor(repo.root)
285 audit_path = util.path_auditor(repo.root)
286 m = match(repo, pats, opts)
286 m = match(repo, pats, opts)
287 for abs in repo.walk(m):
287 for abs in repo.walk(m):
288 target = repo.wjoin(abs)
288 target = repo.wjoin(abs)
289 good = True
289 good = True
290 try:
290 try:
291 audit_path(abs)
291 audit_path(abs)
292 except:
292 except:
293 good = False
293 good = False
294 rel = m.rel(abs)
294 rel = m.rel(abs)
295 exact = m.exact(abs)
295 exact = m.exact(abs)
296 if good and abs not in repo.dirstate:
296 if good and abs not in repo.dirstate:
297 unknown.append(abs)
297 unknown.append(abs)
298 if repo.ui.verbose or not exact:
298 if repo.ui.verbose or not exact:
299 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
299 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
300 elif repo.dirstate[abs] != 'r' and (not good or not util.lexists(target)
300 elif repo.dirstate[abs] != 'r' and (not good or not util.lexists(target)
301 or (os.path.isdir(target) and not os.path.islink(target))):
301 or (os.path.isdir(target) and not os.path.islink(target))):
302 deleted.append(abs)
302 deleted.append(abs)
303 if repo.ui.verbose or not exact:
303 if repo.ui.verbose or not exact:
304 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
304 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
305 # for finding renames
305 # for finding renames
306 elif repo.dirstate[abs] == 'r':
306 elif repo.dirstate[abs] == 'r':
307 removed.append(abs)
307 removed.append(abs)
308 elif repo.dirstate[abs] == 'a':
308 elif repo.dirstate[abs] == 'a':
309 added.append(abs)
309 added.append(abs)
310 copies = {}
310 copies = {}
311 if similarity > 0:
311 if similarity > 0:
312 for old, new, score in similar.findrenames(repo,
312 for old, new, score in similar.findrenames(repo,
313 added + unknown, removed + deleted, similarity):
313 added + unknown, removed + deleted, similarity):
314 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
314 if repo.ui.verbose or not m.exact(old) or not m.exact(new):
315 repo.ui.status(_('recording removal of %s as rename to %s '
315 repo.ui.status(_('recording removal of %s as rename to %s '
316 '(%d%% similar)\n') %
316 '(%d%% similar)\n') %
317 (m.rel(old), m.rel(new), score * 100))
317 (m.rel(old), m.rel(new), score * 100))
318 copies[new] = old
318 copies[new] = old
319
319
320 if not dry_run:
320 if not dry_run:
321 wctx = repo[None]
321 wctx = repo[None]
322 wlock = repo.wlock()
322 wlock = repo.wlock()
323 try:
323 try:
324 wctx.remove(deleted)
324 wctx.remove(deleted)
325 wctx.add(unknown)
325 wctx.add(unknown)
326 for new, old in copies.iteritems():
326 for new, old in copies.iteritems():
327 wctx.copy(old, new)
327 wctx.copy(old, new)
328 finally:
328 finally:
329 wlock.release()
329 wlock.release()
330
330
331 def copy(ui, repo, pats, opts, rename=False):
331 def copy(ui, repo, pats, opts, rename=False):
332 # called with the repo lock held
332 # called with the repo lock held
333 #
333 #
334 # hgsep => pathname that uses "/" to separate directories
334 # hgsep => pathname that uses "/" to separate directories
335 # ossep => pathname that uses os.sep to separate directories
335 # ossep => pathname that uses os.sep to separate directories
336 cwd = repo.getcwd()
336 cwd = repo.getcwd()
337 targets = {}
337 targets = {}
338 after = opts.get("after")
338 after = opts.get("after")
339 dryrun = opts.get("dry_run")
339 dryrun = opts.get("dry_run")
340 wctx = repo[None]
340 wctx = repo[None]
341
341
342 def walkpat(pat):
342 def walkpat(pat):
343 srcs = []
343 srcs = []
344 badstates = after and '?' or '?r'
344 badstates = after and '?' or '?r'
345 m = match(repo, [pat], opts, globbed=True)
345 m = match(repo, [pat], opts, globbed=True)
346 for abs in repo.walk(m):
346 for abs in repo.walk(m):
347 state = repo.dirstate[abs]
347 state = repo.dirstate[abs]
348 rel = m.rel(abs)
348 rel = m.rel(abs)
349 exact = m.exact(abs)
349 exact = m.exact(abs)
350 if state in badstates:
350 if state in badstates:
351 if exact and state == '?':
351 if exact and state == '?':
352 ui.warn(_('%s: not copying - file is not managed\n') % rel)
352 ui.warn(_('%s: not copying - file is not managed\n') % rel)
353 if exact and state == 'r':
353 if exact and state == 'r':
354 ui.warn(_('%s: not copying - file has been marked for'
354 ui.warn(_('%s: not copying - file has been marked for'
355 ' remove\n') % rel)
355 ' remove\n') % rel)
356 continue
356 continue
357 # abs: hgsep
357 # abs: hgsep
358 # rel: ossep
358 # rel: ossep
359 srcs.append((abs, rel, exact))
359 srcs.append((abs, rel, exact))
360 return srcs
360 return srcs
361
361
362 # abssrc: hgsep
362 # abssrc: hgsep
363 # relsrc: ossep
363 # relsrc: ossep
364 # otarget: ossep
364 # otarget: ossep
365 def copyfile(abssrc, relsrc, otarget, exact):
365 def copyfile(abssrc, relsrc, otarget, exact):
366 abstarget = util.canonpath(repo.root, cwd, otarget)
366 abstarget = util.canonpath(repo.root, cwd, otarget)
367 reltarget = repo.pathto(abstarget, cwd)
367 reltarget = repo.pathto(abstarget, cwd)
368 target = repo.wjoin(abstarget)
368 target = repo.wjoin(abstarget)
369 src = repo.wjoin(abssrc)
369 src = repo.wjoin(abssrc)
370 state = repo.dirstate[abstarget]
370 state = repo.dirstate[abstarget]
371
371
372 # check for collisions
372 # check for collisions
373 prevsrc = targets.get(abstarget)
373 prevsrc = targets.get(abstarget)
374 if prevsrc is not None:
374 if prevsrc is not None:
375 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
375 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
376 (reltarget, repo.pathto(abssrc, cwd),
376 (reltarget, repo.pathto(abssrc, cwd),
377 repo.pathto(prevsrc, cwd)))
377 repo.pathto(prevsrc, cwd)))
378 return
378 return
379
379
380 # check for overwrites
380 # check for overwrites
381 exists = os.path.exists(target)
381 exists = os.path.exists(target)
382 if not after and exists or after and state in 'mn':
382 if not after and exists or after and state in 'mn':
383 if not opts['force']:
383 if not opts['force']:
384 ui.warn(_('%s: not overwriting - file exists\n') %
384 ui.warn(_('%s: not overwriting - file exists\n') %
385 reltarget)
385 reltarget)
386 return
386 return
387
387
388 if after:
388 if after:
389 if not exists:
389 if not exists:
390 if rename:
390 if rename:
391 ui.warn(_('%s: not recording move - %s does not exist\n') %
391 ui.warn(_('%s: not recording move - %s does not exist\n') %
392 (relsrc, reltarget))
392 (relsrc, reltarget))
393 else:
393 else:
394 ui.warn(_('%s: not recording copy - %s does not exist\n') %
394 ui.warn(_('%s: not recording copy - %s does not exist\n') %
395 (relsrc, reltarget))
395 (relsrc, reltarget))
396 return
396 return
397 elif not dryrun:
397 elif not dryrun:
398 try:
398 try:
399 if exists:
399 if exists:
400 os.unlink(target)
400 os.unlink(target)
401 targetdir = os.path.dirname(target) or '.'
401 targetdir = os.path.dirname(target) or '.'
402 if not os.path.isdir(targetdir):
402 if not os.path.isdir(targetdir):
403 os.makedirs(targetdir)
403 os.makedirs(targetdir)
404 util.copyfile(src, target)
404 util.copyfile(src, target)
405 except IOError, inst:
405 except IOError, inst:
406 if inst.errno == errno.ENOENT:
406 if inst.errno == errno.ENOENT:
407 ui.warn(_('%s: deleted in working copy\n') % relsrc)
407 ui.warn(_('%s: deleted in working copy\n') % relsrc)
408 else:
408 else:
409 ui.warn(_('%s: cannot copy - %s\n') %
409 ui.warn(_('%s: cannot copy - %s\n') %
410 (relsrc, inst.strerror))
410 (relsrc, inst.strerror))
411 return True # report a failure
411 return True # report a failure
412
412
413 if ui.verbose or not exact:
413 if ui.verbose or not exact:
414 if rename:
414 if rename:
415 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
415 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
416 else:
416 else:
417 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
417 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
418
418
419 targets[abstarget] = abssrc
419 targets[abstarget] = abssrc
420
420
421 # fix up dirstate
421 # fix up dirstate
422 origsrc = repo.dirstate.copied(abssrc) or abssrc
422 origsrc = repo.dirstate.copied(abssrc) or abssrc
423 if abstarget == origsrc: # copying back a copy?
423 if abstarget == origsrc: # copying back a copy?
424 if state not in 'mn' and not dryrun:
424 if state not in 'mn' and not dryrun:
425 repo.dirstate.normallookup(abstarget)
425 repo.dirstate.normallookup(abstarget)
426 else:
426 else:
427 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
427 if repo.dirstate[origsrc] == 'a' and origsrc == abssrc:
428 if not ui.quiet:
428 if not ui.quiet:
429 ui.warn(_("%s has not been committed yet, so no copy "
429 ui.warn(_("%s has not been committed yet, so no copy "
430 "data will be stored for %s.\n")
430 "data will be stored for %s.\n")
431 % (repo.pathto(origsrc, cwd), reltarget))
431 % (repo.pathto(origsrc, cwd), reltarget))
432 if repo.dirstate[abstarget] in '?r' and not dryrun:
432 if repo.dirstate[abstarget] in '?r' and not dryrun:
433 wctx.add([abstarget])
433 wctx.add([abstarget])
434 elif not dryrun:
434 elif not dryrun:
435 wctx.copy(origsrc, abstarget)
435 wctx.copy(origsrc, abstarget)
436
436
437 if rename and not dryrun:
437 if rename and not dryrun:
438 wctx.remove([abssrc], not after)
438 wctx.remove([abssrc], not after)
439
439
440 # pat: ossep
440 # pat: ossep
441 # dest ossep
441 # dest ossep
442 # srcs: list of (hgsep, hgsep, ossep, bool)
442 # srcs: list of (hgsep, hgsep, ossep, bool)
443 # return: function that takes hgsep and returns ossep
443 # return: function that takes hgsep and returns ossep
444 def targetpathfn(pat, dest, srcs):
444 def targetpathfn(pat, dest, srcs):
445 if os.path.isdir(pat):
445 if os.path.isdir(pat):
446 abspfx = util.canonpath(repo.root, cwd, pat)
446 abspfx = util.canonpath(repo.root, cwd, pat)
447 abspfx = util.localpath(abspfx)
447 abspfx = util.localpath(abspfx)
448 if destdirexists:
448 if destdirexists:
449 striplen = len(os.path.split(abspfx)[0])
449 striplen = len(os.path.split(abspfx)[0])
450 else:
450 else:
451 striplen = len(abspfx)
451 striplen = len(abspfx)
452 if striplen:
452 if striplen:
453 striplen += len(os.sep)
453 striplen += len(os.sep)
454 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
454 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
455 elif destdirexists:
455 elif destdirexists:
456 res = lambda p: os.path.join(dest,
456 res = lambda p: os.path.join(dest,
457 os.path.basename(util.localpath(p)))
457 os.path.basename(util.localpath(p)))
458 else:
458 else:
459 res = lambda p: dest
459 res = lambda p: dest
460 return res
460 return res
461
461
462 # pat: ossep
462 # pat: ossep
463 # dest ossep
463 # dest ossep
464 # srcs: list of (hgsep, hgsep, ossep, bool)
464 # srcs: list of (hgsep, hgsep, ossep, bool)
465 # return: function that takes hgsep and returns ossep
465 # return: function that takes hgsep and returns ossep
466 def targetpathafterfn(pat, dest, srcs):
466 def targetpathafterfn(pat, dest, srcs):
467 if _match.patkind(pat):
467 if _match.patkind(pat):
468 # a mercurial pattern
468 # a mercurial pattern
469 res = lambda p: os.path.join(dest,
469 res = lambda p: os.path.join(dest,
470 os.path.basename(util.localpath(p)))
470 os.path.basename(util.localpath(p)))
471 else:
471 else:
472 abspfx = util.canonpath(repo.root, cwd, pat)
472 abspfx = util.canonpath(repo.root, cwd, pat)
473 if len(abspfx) < len(srcs[0][0]):
473 if len(abspfx) < len(srcs[0][0]):
474 # A directory. Either the target path contains the last
474 # A directory. Either the target path contains the last
475 # component of the source path or it does not.
475 # component of the source path or it does not.
476 def evalpath(striplen):
476 def evalpath(striplen):
477 score = 0
477 score = 0
478 for s in srcs:
478 for s in srcs:
479 t = os.path.join(dest, util.localpath(s[0])[striplen:])
479 t = os.path.join(dest, util.localpath(s[0])[striplen:])
480 if os.path.exists(t):
480 if os.path.exists(t):
481 score += 1
481 score += 1
482 return score
482 return score
483
483
484 abspfx = util.localpath(abspfx)
484 abspfx = util.localpath(abspfx)
485 striplen = len(abspfx)
485 striplen = len(abspfx)
486 if striplen:
486 if striplen:
487 striplen += len(os.sep)
487 striplen += len(os.sep)
488 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
488 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
489 score = evalpath(striplen)
489 score = evalpath(striplen)
490 striplen1 = len(os.path.split(abspfx)[0])
490 striplen1 = len(os.path.split(abspfx)[0])
491 if striplen1:
491 if striplen1:
492 striplen1 += len(os.sep)
492 striplen1 += len(os.sep)
493 if evalpath(striplen1) > score:
493 if evalpath(striplen1) > score:
494 striplen = striplen1
494 striplen = striplen1
495 res = lambda p: os.path.join(dest,
495 res = lambda p: os.path.join(dest,
496 util.localpath(p)[striplen:])
496 util.localpath(p)[striplen:])
497 else:
497 else:
498 # a file
498 # a file
499 if destdirexists:
499 if destdirexists:
500 res = lambda p: os.path.join(dest,
500 res = lambda p: os.path.join(dest,
501 os.path.basename(util.localpath(p)))
501 os.path.basename(util.localpath(p)))
502 else:
502 else:
503 res = lambda p: dest
503 res = lambda p: dest
504 return res
504 return res
505
505
506
506
507 pats = expandpats(pats)
507 pats = expandpats(pats)
508 if not pats:
508 if not pats:
509 raise util.Abort(_('no source or destination specified'))
509 raise util.Abort(_('no source or destination specified'))
510 if len(pats) == 1:
510 if len(pats) == 1:
511 raise util.Abort(_('no destination specified'))
511 raise util.Abort(_('no destination specified'))
512 dest = pats.pop()
512 dest = pats.pop()
513 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
513 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
514 if not destdirexists:
514 if not destdirexists:
515 if len(pats) > 1 or _match.patkind(pats[0]):
515 if len(pats) > 1 or _match.patkind(pats[0]):
516 raise util.Abort(_('with multiple sources, destination must be an '
516 raise util.Abort(_('with multiple sources, destination must be an '
517 'existing directory'))
517 'existing directory'))
518 if util.endswithsep(dest):
518 if util.endswithsep(dest):
519 raise util.Abort(_('destination %s is not a directory') % dest)
519 raise util.Abort(_('destination %s is not a directory') % dest)
520
520
521 tfn = targetpathfn
521 tfn = targetpathfn
522 if after:
522 if after:
523 tfn = targetpathafterfn
523 tfn = targetpathafterfn
524 copylist = []
524 copylist = []
525 for pat in pats:
525 for pat in pats:
526 srcs = walkpat(pat)
526 srcs = walkpat(pat)
527 if not srcs:
527 if not srcs:
528 continue
528 continue
529 copylist.append((tfn(pat, dest, srcs), srcs))
529 copylist.append((tfn(pat, dest, srcs), srcs))
530 if not copylist:
530 if not copylist:
531 raise util.Abort(_('no files to copy'))
531 raise util.Abort(_('no files to copy'))
532
532
533 errors = 0
533 errors = 0
534 for targetpath, srcs in copylist:
534 for targetpath, srcs in copylist:
535 for abssrc, relsrc, exact in srcs:
535 for abssrc, relsrc, exact in srcs:
536 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
536 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
537 errors += 1
537 errors += 1
538
538
539 if errors:
539 if errors:
540 ui.warn(_('(consider using --after)\n'))
540 ui.warn(_('(consider using --after)\n'))
541
541
542 return errors != 0
542 return errors != 0
543
543
544 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
544 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
545 runargs=None, appendpid=False):
545 runargs=None, appendpid=False):
546 '''Run a command as a service.'''
546 '''Run a command as a service.'''
547
547
548 if opts['daemon'] and not opts['daemon_pipefds']:
548 if opts['daemon'] and not opts['daemon_pipefds']:
549 # Signal child process startup with file removal
549 # Signal child process startup with file removal
550 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
550 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
551 os.close(lockfd)
551 os.close(lockfd)
552 try:
552 try:
553 if not runargs:
553 if not runargs:
554 runargs = util.hgcmd() + sys.argv[1:]
554 runargs = util.hgcmd() + sys.argv[1:]
555 runargs.append('--daemon-pipefds=%s' % lockpath)
555 runargs.append('--daemon-pipefds=%s' % lockpath)
556 # Don't pass --cwd to the child process, because we've already
556 # Don't pass --cwd to the child process, because we've already
557 # changed directory.
557 # changed directory.
558 for i in xrange(1, len(runargs)):
558 for i in xrange(1, len(runargs)):
559 if runargs[i].startswith('--cwd='):
559 if runargs[i].startswith('--cwd='):
560 del runargs[i]
560 del runargs[i]
561 break
561 break
562 elif runargs[i].startswith('--cwd'):
562 elif runargs[i].startswith('--cwd'):
563 del runargs[i:i + 2]
563 del runargs[i:i + 2]
564 break
564 break
565 def condfn():
565 def condfn():
566 return not os.path.exists(lockpath)
566 return not os.path.exists(lockpath)
567 pid = util.rundetached(runargs, condfn)
567 pid = util.rundetached(runargs, condfn)
568 if pid < 0:
568 if pid < 0:
569 raise util.Abort(_('child process failed to start'))
569 raise util.Abort(_('child process failed to start'))
570 finally:
570 finally:
571 try:
571 try:
572 os.unlink(lockpath)
572 os.unlink(lockpath)
573 except OSError, e:
573 except OSError, e:
574 if e.errno != errno.ENOENT:
574 if e.errno != errno.ENOENT:
575 raise
575 raise
576 if parentfn:
576 if parentfn:
577 return parentfn(pid)
577 return parentfn(pid)
578 else:
578 else:
579 return
579 return
580
580
581 if initfn:
581 if initfn:
582 initfn()
582 initfn()
583
583
584 if opts['pid_file']:
584 if opts['pid_file']:
585 mode = appendpid and 'a' or 'w'
585 mode = appendpid and 'a' or 'w'
586 fp = open(opts['pid_file'], mode)
586 fp = open(opts['pid_file'], mode)
587 fp.write(str(os.getpid()) + '\n')
587 fp.write(str(os.getpid()) + '\n')
588 fp.close()
588 fp.close()
589
589
590 if opts['daemon_pipefds']:
590 if opts['daemon_pipefds']:
591 lockpath = opts['daemon_pipefds']
591 lockpath = opts['daemon_pipefds']
592 try:
592 try:
593 os.setsid()
593 os.setsid()
594 except AttributeError:
594 except AttributeError:
595 pass
595 pass
596 os.unlink(lockpath)
596 os.unlink(lockpath)
597 util.hidewindow()
597 util.hidewindow()
598 sys.stdout.flush()
598 sys.stdout.flush()
599 sys.stderr.flush()
599 sys.stderr.flush()
600
600
601 nullfd = os.open(util.nulldev, os.O_RDWR)
601 nullfd = os.open(util.nulldev, os.O_RDWR)
602 logfilefd = nullfd
602 logfilefd = nullfd
603 if logfile:
603 if logfile:
604 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
604 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
605 os.dup2(nullfd, 0)
605 os.dup2(nullfd, 0)
606 os.dup2(logfilefd, 1)
606 os.dup2(logfilefd, 1)
607 os.dup2(logfilefd, 2)
607 os.dup2(logfilefd, 2)
608 if nullfd not in (0, 1, 2):
608 if nullfd not in (0, 1, 2):
609 os.close(nullfd)
609 os.close(nullfd)
610 if logfile and logfilefd not in (0, 1, 2):
610 if logfile and logfilefd not in (0, 1, 2):
611 os.close(logfilefd)
611 os.close(logfilefd)
612
612
613 if runfn:
613 if runfn:
614 return runfn()
614 return runfn()
615
615
616 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
616 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
617 opts=None):
617 opts=None):
618 '''export changesets as hg patches.'''
618 '''export changesets as hg patches.'''
619
619
620 total = len(revs)
620 total = len(revs)
621 revwidth = max([len(str(rev)) for rev in revs])
621 revwidth = max([len(str(rev)) for rev in revs])
622
622
623 def single(rev, seqno, fp):
623 def single(rev, seqno, fp):
624 ctx = repo[rev]
624 ctx = repo[rev]
625 node = ctx.node()
625 node = ctx.node()
626 parents = [p.node() for p in ctx.parents() if p]
626 parents = [p.node() for p in ctx.parents() if p]
627 branch = ctx.branch()
627 branch = ctx.branch()
628 if switch_parent:
628 if switch_parent:
629 parents.reverse()
629 parents.reverse()
630 prev = (parents and parents[0]) or nullid
630 prev = (parents and parents[0]) or nullid
631
631
632 if not fp:
632 if not fp:
633 fp = make_file(repo, template, node, total=total, seqno=seqno,
633 fp = make_file(repo, template, node, total=total, seqno=seqno,
634 revwidth=revwidth, mode='ab')
634 revwidth=revwidth, mode='ab')
635 if fp != sys.stdout and hasattr(fp, 'name'):
635 if fp != sys.stdout and hasattr(fp, 'name'):
636 repo.ui.note("%s\n" % fp.name)
636 repo.ui.note("%s\n" % fp.name)
637
637
638 fp.write("# HG changeset patch\n")
638 fp.write("# HG changeset patch\n")
639 fp.write("# User %s\n" % ctx.user())
639 fp.write("# User %s\n" % ctx.user())
640 fp.write("# Date %d %d\n" % ctx.date())
640 fp.write("# Date %d %d\n" % ctx.date())
641 if branch and (branch != 'default'):
641 if branch and (branch != 'default'):
642 fp.write("# Branch %s\n" % branch)
642 fp.write("# Branch %s\n" % branch)
643 fp.write("# Node ID %s\n" % hex(node))
643 fp.write("# Node ID %s\n" % hex(node))
644 fp.write("# Parent %s\n" % hex(prev))
644 fp.write("# Parent %s\n" % hex(prev))
645 if len(parents) > 1:
645 if len(parents) > 1:
646 fp.write("# Parent %s\n" % hex(parents[1]))
646 fp.write("# Parent %s\n" % hex(parents[1]))
647 fp.write(ctx.description().rstrip())
647 fp.write(ctx.description().rstrip())
648 fp.write("\n\n")
648 fp.write("\n\n")
649
649
650 for chunk in patch.diff(repo, prev, node, opts=opts):
650 for chunk in patch.diff(repo, prev, node, opts=opts):
651 fp.write(chunk)
651 fp.write(chunk)
652
652
653 for seqno, rev in enumerate(revs):
653 for seqno, rev in enumerate(revs):
654 single(rev, seqno + 1, fp)
654 single(rev, seqno + 1, fp)
655
655
656 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
656 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
657 changes=None, stat=False, fp=None):
657 changes=None, stat=False, fp=None):
658 '''show diff or diffstat.'''
658 '''show diff or diffstat.'''
659 if fp is None:
659 if fp is None:
660 write = ui.write
660 write = ui.write
661 else:
661 else:
662 def write(s, **kw):
662 def write(s, **kw):
663 fp.write(s)
663 fp.write(s)
664
664
665 if stat:
665 if stat:
666 diffopts.context = 0
666 diffopts.context = 0
667 width = 80
667 width = 80
668 if not ui.plain():
668 if not ui.plain():
669 width = util.termwidth()
669 width = util.termwidth()
670 chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
670 chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
671 for chunk, label in patch.diffstatui(util.iterlines(chunks),
671 for chunk, label in patch.diffstatui(util.iterlines(chunks),
672 width=width,
672 width=width,
673 git=diffopts.git):
673 git=diffopts.git):
674 write(chunk, label=label)
674 write(chunk, label=label)
675 else:
675 else:
676 for chunk, label in patch.diffui(repo, node1, node2, match,
676 for chunk, label in patch.diffui(repo, node1, node2, match,
677 changes, diffopts):
677 changes, diffopts):
678 write(chunk, label=label)
678 write(chunk, label=label)
679
679
680 class changeset_printer(object):
680 class changeset_printer(object):
681 '''show changeset information when templating not requested.'''
681 '''show changeset information when templating not requested.'''
682
682
683 def __init__(self, ui, repo, patch, diffopts, buffered):
683 def __init__(self, ui, repo, patch, diffopts, buffered):
684 self.ui = ui
684 self.ui = ui
685 self.repo = repo
685 self.repo = repo
686 self.buffered = buffered
686 self.buffered = buffered
687 self.patch = patch
687 self.patch = patch
688 self.diffopts = diffopts
688 self.diffopts = diffopts
689 self.header = {}
689 self.header = {}
690 self.hunk = {}
690 self.hunk = {}
691 self.lastheader = None
691 self.lastheader = None
692 self.footer = None
692 self.footer = None
693
693
694 def flush(self, rev):
694 def flush(self, rev):
695 if rev in self.header:
695 if rev in self.header:
696 h = self.header[rev]
696 h = self.header[rev]
697 if h != self.lastheader:
697 if h != self.lastheader:
698 self.lastheader = h
698 self.lastheader = h
699 self.ui.write(h)
699 self.ui.write(h)
700 del self.header[rev]
700 del self.header[rev]
701 if rev in self.hunk:
701 if rev in self.hunk:
702 self.ui.write(self.hunk[rev])
702 self.ui.write(self.hunk[rev])
703 del self.hunk[rev]
703 del self.hunk[rev]
704 return 1
704 return 1
705 return 0
705 return 0
706
706
707 def close(self):
707 def close(self):
708 if self.footer:
708 if self.footer:
709 self.ui.write(self.footer)
709 self.ui.write(self.footer)
710
710
711 def show(self, ctx, copies=None, **props):
711 def show(self, ctx, copies=None, matchfn=None, **props):
712 if self.buffered:
712 if self.buffered:
713 self.ui.pushbuffer()
713 self.ui.pushbuffer()
714 self._show(ctx, copies, props)
714 self._show(ctx, copies, matchfn, props)
715 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
715 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
716 else:
716 else:
717 self._show(ctx, copies, props)
717 self._show(ctx, copies, matchfn, props)
718
718
719 def _show(self, ctx, copies, props):
719 def _show(self, ctx, copies, matchfn, props):
720 '''show a single changeset or file revision'''
720 '''show a single changeset or file revision'''
721 changenode = ctx.node()
721 changenode = ctx.node()
722 rev = ctx.rev()
722 rev = ctx.rev()
723
723
724 if self.ui.quiet:
724 if self.ui.quiet:
725 self.ui.write("%d:%s\n" % (rev, short(changenode)),
725 self.ui.write("%d:%s\n" % (rev, short(changenode)),
726 label='log.node')
726 label='log.node')
727 return
727 return
728
728
729 log = self.repo.changelog
729 log = self.repo.changelog
730 date = util.datestr(ctx.date())
730 date = util.datestr(ctx.date())
731
731
732 hexfunc = self.ui.debugflag and hex or short
732 hexfunc = self.ui.debugflag and hex or short
733
733
734 parents = [(p, hexfunc(log.node(p)))
734 parents = [(p, hexfunc(log.node(p)))
735 for p in self._meaningful_parentrevs(log, rev)]
735 for p in self._meaningful_parentrevs(log, rev)]
736
736
737 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
737 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
738 label='log.changeset')
738 label='log.changeset')
739
739
740 branch = ctx.branch()
740 branch = ctx.branch()
741 # don't show the default branch name
741 # don't show the default branch name
742 if branch != 'default':
742 if branch != 'default':
743 branch = encoding.tolocal(branch)
743 branch = encoding.tolocal(branch)
744 self.ui.write(_("branch: %s\n") % branch,
744 self.ui.write(_("branch: %s\n") % branch,
745 label='log.branch')
745 label='log.branch')
746 for tag in self.repo.nodetags(changenode):
746 for tag in self.repo.nodetags(changenode):
747 self.ui.write(_("tag: %s\n") % tag,
747 self.ui.write(_("tag: %s\n") % tag,
748 label='log.tag')
748 label='log.tag')
749 for parent in parents:
749 for parent in parents:
750 self.ui.write(_("parent: %d:%s\n") % parent,
750 self.ui.write(_("parent: %d:%s\n") % parent,
751 label='log.parent')
751 label='log.parent')
752
752
753 if self.ui.debugflag:
753 if self.ui.debugflag:
754 mnode = ctx.manifestnode()
754 mnode = ctx.manifestnode()
755 self.ui.write(_("manifest: %d:%s\n") %
755 self.ui.write(_("manifest: %d:%s\n") %
756 (self.repo.manifest.rev(mnode), hex(mnode)),
756 (self.repo.manifest.rev(mnode), hex(mnode)),
757 label='ui.debug log.manifest')
757 label='ui.debug log.manifest')
758 self.ui.write(_("user: %s\n") % ctx.user(),
758 self.ui.write(_("user: %s\n") % ctx.user(),
759 label='log.user')
759 label='log.user')
760 self.ui.write(_("date: %s\n") % date,
760 self.ui.write(_("date: %s\n") % date,
761 label='log.date')
761 label='log.date')
762
762
763 if self.ui.debugflag:
763 if self.ui.debugflag:
764 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
764 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
765 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
765 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
766 files):
766 files):
767 if value:
767 if value:
768 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
768 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
769 label='ui.debug log.files')
769 label='ui.debug log.files')
770 elif ctx.files() and self.ui.verbose:
770 elif ctx.files() and self.ui.verbose:
771 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
771 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
772 label='ui.note log.files')
772 label='ui.note log.files')
773 if copies and self.ui.verbose:
773 if copies and self.ui.verbose:
774 copies = ['%s (%s)' % c for c in copies]
774 copies = ['%s (%s)' % c for c in copies]
775 self.ui.write(_("copies: %s\n") % ' '.join(copies),
775 self.ui.write(_("copies: %s\n") % ' '.join(copies),
776 label='ui.note log.copies')
776 label='ui.note log.copies')
777
777
778 extra = ctx.extra()
778 extra = ctx.extra()
779 if extra and self.ui.debugflag:
779 if extra and self.ui.debugflag:
780 for key, value in sorted(extra.items()):
780 for key, value in sorted(extra.items()):
781 self.ui.write(_("extra: %s=%s\n")
781 self.ui.write(_("extra: %s=%s\n")
782 % (key, value.encode('string_escape')),
782 % (key, value.encode('string_escape')),
783 label='ui.debug log.extra')
783 label='ui.debug log.extra')
784
784
785 description = ctx.description().strip()
785 description = ctx.description().strip()
786 if description:
786 if description:
787 if self.ui.verbose:
787 if self.ui.verbose:
788 self.ui.write(_("description:\n"),
788 self.ui.write(_("description:\n"),
789 label='ui.note log.description')
789 label='ui.note log.description')
790 self.ui.write(description,
790 self.ui.write(description,
791 label='ui.note log.description')
791 label='ui.note log.description')
792 self.ui.write("\n\n")
792 self.ui.write("\n\n")
793 else:
793 else:
794 self.ui.write(_("summary: %s\n") %
794 self.ui.write(_("summary: %s\n") %
795 description.splitlines()[0],
795 description.splitlines()[0],
796 label='log.summary')
796 label='log.summary')
797 self.ui.write("\n")
797 self.ui.write("\n")
798
798
799 self.showpatch(changenode)
799 self.showpatch(changenode, matchfn)
800
800
801 def showpatch(self, node):
801 def showpatch(self, node, matchfn):
802 if self.patch:
802 if not matchfn:
803 matchfn = self.patch
804 if matchfn:
803 stat = self.diffopts.get('stat')
805 stat = self.diffopts.get('stat')
804 diffopts = patch.diffopts(self.ui, self.diffopts)
806 diffopts = patch.diffopts(self.ui, self.diffopts)
805 prev = self.repo.changelog.parents(node)[0]
807 prev = self.repo.changelog.parents(node)[0]
806 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
808 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
807 match=self.patch, stat=stat)
809 match=matchfn, stat=stat)
808 self.ui.write("\n")
810 self.ui.write("\n")
809
811
810 def _meaningful_parentrevs(self, log, rev):
812 def _meaningful_parentrevs(self, log, rev):
811 """Return list of meaningful (or all if debug) parentrevs for rev.
813 """Return list of meaningful (or all if debug) parentrevs for rev.
812
814
813 For merges (two non-nullrev revisions) both parents are meaningful.
815 For merges (two non-nullrev revisions) both parents are meaningful.
814 Otherwise the first parent revision is considered meaningful if it
816 Otherwise the first parent revision is considered meaningful if it
815 is not the preceding revision.
817 is not the preceding revision.
816 """
818 """
817 parents = log.parentrevs(rev)
819 parents = log.parentrevs(rev)
818 if not self.ui.debugflag and parents[1] == nullrev:
820 if not self.ui.debugflag and parents[1] == nullrev:
819 if parents[0] >= rev - 1:
821 if parents[0] >= rev - 1:
820 parents = []
822 parents = []
821 else:
823 else:
822 parents = [parents[0]]
824 parents = [parents[0]]
823 return parents
825 return parents
824
826
825
827
826 class changeset_templater(changeset_printer):
828 class changeset_templater(changeset_printer):
827 '''format changeset information.'''
829 '''format changeset information.'''
828
830
829 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
831 def __init__(self, ui, repo, patch, diffopts, mapfile, buffered):
830 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
832 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
831 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
833 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
832 defaulttempl = {
834 defaulttempl = {
833 'parent': '{rev}:{node|formatnode} ',
835 'parent': '{rev}:{node|formatnode} ',
834 'manifest': '{rev}:{node|formatnode}',
836 'manifest': '{rev}:{node|formatnode}',
835 'file_copy': '{name} ({source})',
837 'file_copy': '{name} ({source})',
836 'extra': '{key}={value|stringescape}'
838 'extra': '{key}={value|stringescape}'
837 }
839 }
838 # filecopy is preserved for compatibility reasons
840 # filecopy is preserved for compatibility reasons
839 defaulttempl['filecopy'] = defaulttempl['file_copy']
841 defaulttempl['filecopy'] = defaulttempl['file_copy']
840 self.t = templater.templater(mapfile, {'formatnode': formatnode},
842 self.t = templater.templater(mapfile, {'formatnode': formatnode},
841 cache=defaulttempl)
843 cache=defaulttempl)
842 self.cache = {}
844 self.cache = {}
843
845
844 def use_template(self, t):
846 def use_template(self, t):
845 '''set template string to use'''
847 '''set template string to use'''
846 self.t.cache['changeset'] = t
848 self.t.cache['changeset'] = t
847
849
848 def _meaningful_parentrevs(self, ctx):
850 def _meaningful_parentrevs(self, ctx):
849 """Return list of meaningful (or all if debug) parentrevs for rev.
851 """Return list of meaningful (or all if debug) parentrevs for rev.
850 """
852 """
851 parents = ctx.parents()
853 parents = ctx.parents()
852 if len(parents) > 1:
854 if len(parents) > 1:
853 return parents
855 return parents
854 if self.ui.debugflag:
856 if self.ui.debugflag:
855 return [parents[0], self.repo['null']]
857 return [parents[0], self.repo['null']]
856 if parents[0].rev() >= ctx.rev() - 1:
858 if parents[0].rev() >= ctx.rev() - 1:
857 return []
859 return []
858 return parents
860 return parents
859
861
860 def _show(self, ctx, copies, props):
862 def _show(self, ctx, copies, matchfn, props):
861 '''show a single changeset or file revision'''
863 '''show a single changeset or file revision'''
862
864
863 showlist = templatekw.showlist
865 showlist = templatekw.showlist
864
866
865 # showparents() behaviour depends on ui trace level which
867 # showparents() behaviour depends on ui trace level which
866 # causes unexpected behaviours at templating level and makes
868 # causes unexpected behaviours at templating level and makes
867 # it harder to extract it in a standalone function. Its
869 # it harder to extract it in a standalone function. Its
868 # behaviour cannot be changed so leave it here for now.
870 # behaviour cannot be changed so leave it here for now.
869 def showparents(**args):
871 def showparents(**args):
870 ctx = args['ctx']
872 ctx = args['ctx']
871 parents = [[('rev', p.rev()), ('node', p.hex())]
873 parents = [[('rev', p.rev()), ('node', p.hex())]
872 for p in self._meaningful_parentrevs(ctx)]
874 for p in self._meaningful_parentrevs(ctx)]
873 return showlist('parent', parents, **args)
875 return showlist('parent', parents, **args)
874
876
875 props = props.copy()
877 props = props.copy()
876 props.update(templatekw.keywords)
878 props.update(templatekw.keywords)
877 props['parents'] = showparents
879 props['parents'] = showparents
878 props['templ'] = self.t
880 props['templ'] = self.t
879 props['ctx'] = ctx
881 props['ctx'] = ctx
880 props['repo'] = self.repo
882 props['repo'] = self.repo
881 props['revcache'] = {'copies': copies}
883 props['revcache'] = {'copies': copies}
882 props['cache'] = self.cache
884 props['cache'] = self.cache
883
885
884 # find correct templates for current mode
886 # find correct templates for current mode
885
887
886 tmplmodes = [
888 tmplmodes = [
887 (True, None),
889 (True, None),
888 (self.ui.verbose, 'verbose'),
890 (self.ui.verbose, 'verbose'),
889 (self.ui.quiet, 'quiet'),
891 (self.ui.quiet, 'quiet'),
890 (self.ui.debugflag, 'debug'),
892 (self.ui.debugflag, 'debug'),
891 ]
893 ]
892
894
893 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
895 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
894 for mode, postfix in tmplmodes:
896 for mode, postfix in tmplmodes:
895 for type in types:
897 for type in types:
896 cur = postfix and ('%s_%s' % (type, postfix)) or type
898 cur = postfix and ('%s_%s' % (type, postfix)) or type
897 if mode and cur in self.t:
899 if mode and cur in self.t:
898 types[type] = cur
900 types[type] = cur
899
901
900 try:
902 try:
901
903
902 # write header
904 # write header
903 if types['header']:
905 if types['header']:
904 h = templater.stringify(self.t(types['header'], **props))
906 h = templater.stringify(self.t(types['header'], **props))
905 if self.buffered:
907 if self.buffered:
906 self.header[ctx.rev()] = h
908 self.header[ctx.rev()] = h
907 else:
909 else:
908 if self.lastheader != h:
910 if self.lastheader != h:
909 self.lastheader = h
911 self.lastheader = h
910 self.ui.write(h)
912 self.ui.write(h)
911
913
912 # write changeset metadata, then patch if requested
914 # write changeset metadata, then patch if requested
913 key = types['changeset']
915 key = types['changeset']
914 self.ui.write(templater.stringify(self.t(key, **props)))
916 self.ui.write(templater.stringify(self.t(key, **props)))
915 self.showpatch(ctx.node())
917 self.showpatch(ctx.node(), matchfn)
916
918
917 if types['footer']:
919 if types['footer']:
918 if not self.footer:
920 if not self.footer:
919 self.footer = templater.stringify(self.t(types['footer'],
921 self.footer = templater.stringify(self.t(types['footer'],
920 **props))
922 **props))
921
923
922 except KeyError, inst:
924 except KeyError, inst:
923 msg = _("%s: no key named '%s'")
925 msg = _("%s: no key named '%s'")
924 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
926 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
925 except SyntaxError, inst:
927 except SyntaxError, inst:
926 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
928 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
927
929
928 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
930 def show_changeset(ui, repo, opts, buffered=False):
929 """show one changeset using template or regular display.
931 """show one changeset using template or regular display.
930
932
931 Display format will be the first non-empty hit of:
933 Display format will be the first non-empty hit of:
932 1. option 'template'
934 1. option 'template'
933 2. option 'style'
935 2. option 'style'
934 3. [ui] setting 'logtemplate'
936 3. [ui] setting 'logtemplate'
935 4. [ui] setting 'style'
937 4. [ui] setting 'style'
936 If all of these values are either the unset or the empty string,
938 If all of these values are either the unset or the empty string,
937 regular display via changeset_printer() is done.
939 regular display via changeset_printer() is done.
938 """
940 """
939 # options
941 # options
940 patch = False
942 patch = False
941 if opts.get('patch') or opts.get('stat'):
943 if opts.get('patch') or opts.get('stat'):
942 patch = matchfn or matchall(repo)
944 patch = matchall(repo)
943
945
944 tmpl = opts.get('template')
946 tmpl = opts.get('template')
945 style = None
947 style = None
946 if tmpl:
948 if tmpl:
947 tmpl = templater.parsestring(tmpl, quoted=False)
949 tmpl = templater.parsestring(tmpl, quoted=False)
948 else:
950 else:
949 style = opts.get('style')
951 style = opts.get('style')
950
952
951 # ui settings
953 # ui settings
952 if not (tmpl or style):
954 if not (tmpl or style):
953 tmpl = ui.config('ui', 'logtemplate')
955 tmpl = ui.config('ui', 'logtemplate')
954 if tmpl:
956 if tmpl:
955 tmpl = templater.parsestring(tmpl)
957 tmpl = templater.parsestring(tmpl)
956 else:
958 else:
957 style = util.expandpath(ui.config('ui', 'style', ''))
959 style = util.expandpath(ui.config('ui', 'style', ''))
958
960
959 if not (tmpl or style):
961 if not (tmpl or style):
960 return changeset_printer(ui, repo, patch, opts, buffered)
962 return changeset_printer(ui, repo, patch, opts, buffered)
961
963
962 mapfile = None
964 mapfile = None
963 if style and not tmpl:
965 if style and not tmpl:
964 mapfile = style
966 mapfile = style
965 if not os.path.split(mapfile)[0]:
967 if not os.path.split(mapfile)[0]:
966 mapname = (templater.templatepath('map-cmdline.' + mapfile)
968 mapname = (templater.templatepath('map-cmdline.' + mapfile)
967 or templater.templatepath(mapfile))
969 or templater.templatepath(mapfile))
968 if mapname:
970 if mapname:
969 mapfile = mapname
971 mapfile = mapname
970
972
971 try:
973 try:
972 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
974 t = changeset_templater(ui, repo, patch, opts, mapfile, buffered)
973 except SyntaxError, inst:
975 except SyntaxError, inst:
974 raise util.Abort(inst.args[0])
976 raise util.Abort(inst.args[0])
975 if tmpl:
977 if tmpl:
976 t.use_template(tmpl)
978 t.use_template(tmpl)
977 return t
979 return t
978
980
979 def finddate(ui, repo, date):
981 def finddate(ui, repo, date):
980 """Find the tipmost changeset that matches the given date spec"""
982 """Find the tipmost changeset that matches the given date spec"""
981
983
982 df = util.matchdate(date)
984 df = util.matchdate(date)
983 m = matchall(repo)
985 m = matchall(repo)
984 results = {}
986 results = {}
985
987
986 def prep(ctx, fns):
988 def prep(ctx, fns):
987 d = ctx.date()
989 d = ctx.date()
988 if df(d[0]):
990 if df(d[0]):
989 results[ctx.rev()] = d
991 results[ctx.rev()] = d
990
992
991 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
993 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
992 rev = ctx.rev()
994 rev = ctx.rev()
993 if rev in results:
995 if rev in results:
994 ui.status(_("Found revision %s from %s\n") %
996 ui.status(_("Found revision %s from %s\n") %
995 (rev, util.datestr(results[rev])))
997 (rev, util.datestr(results[rev])))
996 return str(rev)
998 return str(rev)
997
999
998 raise util.Abort(_("revision matching date not found"))
1000 raise util.Abort(_("revision matching date not found"))
999
1001
1000 def walkchangerevs(repo, match, opts, prepare):
1002 def walkchangerevs(repo, match, opts, prepare):
1001 '''Iterate over files and the revs in which they changed.
1003 '''Iterate over files and the revs in which they changed.
1002
1004
1003 Callers most commonly need to iterate backwards over the history
1005 Callers most commonly need to iterate backwards over the history
1004 in which they are interested. Doing so has awful (quadratic-looking)
1006 in which they are interested. Doing so has awful (quadratic-looking)
1005 performance, so we use iterators in a "windowed" way.
1007 performance, so we use iterators in a "windowed" way.
1006
1008
1007 We walk a window of revisions in the desired order. Within the
1009 We walk a window of revisions in the desired order. Within the
1008 window, we first walk forwards to gather data, then in the desired
1010 window, we first walk forwards to gather data, then in the desired
1009 order (usually backwards) to display it.
1011 order (usually backwards) to display it.
1010
1012
1011 This function returns an iterator yielding contexts. Before
1013 This function returns an iterator yielding contexts. Before
1012 yielding each context, the iterator will first call the prepare
1014 yielding each context, the iterator will first call the prepare
1013 function on each context in the window in forward order.'''
1015 function on each context in the window in forward order.'''
1014
1016
1015 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1017 def increasing_windows(start, end, windowsize=8, sizelimit=512):
1016 if start < end:
1018 if start < end:
1017 while start < end:
1019 while start < end:
1018 yield start, min(windowsize, end - start)
1020 yield start, min(windowsize, end - start)
1019 start += windowsize
1021 start += windowsize
1020 if windowsize < sizelimit:
1022 if windowsize < sizelimit:
1021 windowsize *= 2
1023 windowsize *= 2
1022 else:
1024 else:
1023 while start > end:
1025 while start > end:
1024 yield start, min(windowsize, start - end - 1)
1026 yield start, min(windowsize, start - end - 1)
1025 start -= windowsize
1027 start -= windowsize
1026 if windowsize < sizelimit:
1028 if windowsize < sizelimit:
1027 windowsize *= 2
1029 windowsize *= 2
1028
1030
1029 follow = opts.get('follow') or opts.get('follow_first')
1031 follow = opts.get('follow') or opts.get('follow_first')
1030
1032
1031 if not len(repo):
1033 if not len(repo):
1032 return []
1034 return []
1033
1035
1034 if follow:
1036 if follow:
1035 defrange = '%s:0' % repo['.'].rev()
1037 defrange = '%s:0' % repo['.'].rev()
1036 else:
1038 else:
1037 defrange = '-1:0'
1039 defrange = '-1:0'
1038 revs = revrange(repo, opts['rev'] or [defrange])
1040 revs = revrange(repo, opts['rev'] or [defrange])
1039 if not revs:
1041 if not revs:
1040 return []
1042 return []
1041 wanted = set()
1043 wanted = set()
1042 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1044 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1043 fncache = {}
1045 fncache = {}
1044 change = util.cachefunc(repo.changectx)
1046 change = util.cachefunc(repo.changectx)
1045
1047
1046 if not slowpath and not match.files():
1048 if not slowpath and not match.files():
1047 # No files, no patterns. Display all revs.
1049 # No files, no patterns. Display all revs.
1048 wanted = set(revs)
1050 wanted = set(revs)
1049 copies = []
1051 copies = []
1050
1052
1051 if not slowpath:
1053 if not slowpath:
1052 # Only files, no patterns. Check the history of each file.
1054 # Only files, no patterns. Check the history of each file.
1053 def filerevgen(filelog, node):
1055 def filerevgen(filelog, node):
1054 cl_count = len(repo)
1056 cl_count = len(repo)
1055 if node is None:
1057 if node is None:
1056 last = len(filelog) - 1
1058 last = len(filelog) - 1
1057 else:
1059 else:
1058 last = filelog.rev(node)
1060 last = filelog.rev(node)
1059 for i, window in increasing_windows(last, nullrev):
1061 for i, window in increasing_windows(last, nullrev):
1060 revs = []
1062 revs = []
1061 for j in xrange(i - window, i + 1):
1063 for j in xrange(i - window, i + 1):
1062 n = filelog.node(j)
1064 n = filelog.node(j)
1063 revs.append((filelog.linkrev(j),
1065 revs.append((filelog.linkrev(j),
1064 follow and filelog.renamed(n)))
1066 follow and filelog.renamed(n)))
1065 for rev in reversed(revs):
1067 for rev in reversed(revs):
1066 # only yield rev for which we have the changelog, it can
1068 # only yield rev for which we have the changelog, it can
1067 # happen while doing "hg log" during a pull or commit
1069 # happen while doing "hg log" during a pull or commit
1068 if rev[0] < cl_count:
1070 if rev[0] < cl_count:
1069 yield rev
1071 yield rev
1070 def iterfiles():
1072 def iterfiles():
1071 for filename in match.files():
1073 for filename in match.files():
1072 yield filename, None
1074 yield filename, None
1073 for filename_node in copies:
1075 for filename_node in copies:
1074 yield filename_node
1076 yield filename_node
1075 minrev, maxrev = min(revs), max(revs)
1077 minrev, maxrev = min(revs), max(revs)
1076 for file_, node in iterfiles():
1078 for file_, node in iterfiles():
1077 filelog = repo.file(file_)
1079 filelog = repo.file(file_)
1078 if not len(filelog):
1080 if not len(filelog):
1079 if node is None:
1081 if node is None:
1080 # A zero count may be a directory or deleted file, so
1082 # A zero count may be a directory or deleted file, so
1081 # try to find matching entries on the slow path.
1083 # try to find matching entries on the slow path.
1082 if follow:
1084 if follow:
1083 raise util.Abort(
1085 raise util.Abort(
1084 _('cannot follow nonexistent file: "%s"') % file_)
1086 _('cannot follow nonexistent file: "%s"') % file_)
1085 slowpath = True
1087 slowpath = True
1086 break
1088 break
1087 else:
1089 else:
1088 continue
1090 continue
1089 for rev, copied in filerevgen(filelog, node):
1091 for rev, copied in filerevgen(filelog, node):
1090 if rev <= maxrev:
1092 if rev <= maxrev:
1091 if rev < minrev:
1093 if rev < minrev:
1092 break
1094 break
1093 fncache.setdefault(rev, [])
1095 fncache.setdefault(rev, [])
1094 fncache[rev].append(file_)
1096 fncache[rev].append(file_)
1095 wanted.add(rev)
1097 wanted.add(rev)
1096 if copied:
1098 if copied:
1097 copies.append(copied)
1099 copies.append(copied)
1098 if slowpath:
1100 if slowpath:
1099 if follow:
1101 if follow:
1100 raise util.Abort(_('can only follow copies/renames for explicit '
1102 raise util.Abort(_('can only follow copies/renames for explicit '
1101 'filenames'))
1103 'filenames'))
1102
1104
1103 # The slow path checks files modified in every changeset.
1105 # The slow path checks files modified in every changeset.
1104 def changerevgen():
1106 def changerevgen():
1105 for i, window in increasing_windows(len(repo) - 1, nullrev):
1107 for i, window in increasing_windows(len(repo) - 1, nullrev):
1106 for j in xrange(i - window, i + 1):
1108 for j in xrange(i - window, i + 1):
1107 yield change(j)
1109 yield change(j)
1108
1110
1109 for ctx in changerevgen():
1111 for ctx in changerevgen():
1110 matches = filter(match, ctx.files())
1112 matches = filter(match, ctx.files())
1111 if matches:
1113 if matches:
1112 fncache[ctx.rev()] = matches
1114 fncache[ctx.rev()] = matches
1113 wanted.add(ctx.rev())
1115 wanted.add(ctx.rev())
1114
1116
1115 class followfilter(object):
1117 class followfilter(object):
1116 def __init__(self, onlyfirst=False):
1118 def __init__(self, onlyfirst=False):
1117 self.startrev = nullrev
1119 self.startrev = nullrev
1118 self.roots = set()
1120 self.roots = set()
1119 self.onlyfirst = onlyfirst
1121 self.onlyfirst = onlyfirst
1120
1122
1121 def match(self, rev):
1123 def match(self, rev):
1122 def realparents(rev):
1124 def realparents(rev):
1123 if self.onlyfirst:
1125 if self.onlyfirst:
1124 return repo.changelog.parentrevs(rev)[0:1]
1126 return repo.changelog.parentrevs(rev)[0:1]
1125 else:
1127 else:
1126 return filter(lambda x: x != nullrev,
1128 return filter(lambda x: x != nullrev,
1127 repo.changelog.parentrevs(rev))
1129 repo.changelog.parentrevs(rev))
1128
1130
1129 if self.startrev == nullrev:
1131 if self.startrev == nullrev:
1130 self.startrev = rev
1132 self.startrev = rev
1131 return True
1133 return True
1132
1134
1133 if rev > self.startrev:
1135 if rev > self.startrev:
1134 # forward: all descendants
1136 # forward: all descendants
1135 if not self.roots:
1137 if not self.roots:
1136 self.roots.add(self.startrev)
1138 self.roots.add(self.startrev)
1137 for parent in realparents(rev):
1139 for parent in realparents(rev):
1138 if parent in self.roots:
1140 if parent in self.roots:
1139 self.roots.add(rev)
1141 self.roots.add(rev)
1140 return True
1142 return True
1141 else:
1143 else:
1142 # backwards: all parents
1144 # backwards: all parents
1143 if not self.roots:
1145 if not self.roots:
1144 self.roots.update(realparents(self.startrev))
1146 self.roots.update(realparents(self.startrev))
1145 if rev in self.roots:
1147 if rev in self.roots:
1146 self.roots.remove(rev)
1148 self.roots.remove(rev)
1147 self.roots.update(realparents(rev))
1149 self.roots.update(realparents(rev))
1148 return True
1150 return True
1149
1151
1150 return False
1152 return False
1151
1153
1152 # it might be worthwhile to do this in the iterator if the rev range
1154 # it might be worthwhile to do this in the iterator if the rev range
1153 # is descending and the prune args are all within that range
1155 # is descending and the prune args are all within that range
1154 for rev in opts.get('prune', ()):
1156 for rev in opts.get('prune', ()):
1155 rev = repo.changelog.rev(repo.lookup(rev))
1157 rev = repo.changelog.rev(repo.lookup(rev))
1156 ff = followfilter()
1158 ff = followfilter()
1157 stop = min(revs[0], revs[-1])
1159 stop = min(revs[0], revs[-1])
1158 for x in xrange(rev, stop - 1, -1):
1160 for x in xrange(rev, stop - 1, -1):
1159 if ff.match(x):
1161 if ff.match(x):
1160 wanted.discard(x)
1162 wanted.discard(x)
1161
1163
1162 def iterate():
1164 def iterate():
1163 if follow and not match.files():
1165 if follow and not match.files():
1164 ff = followfilter(onlyfirst=opts.get('follow_first'))
1166 ff = followfilter(onlyfirst=opts.get('follow_first'))
1165 def want(rev):
1167 def want(rev):
1166 return ff.match(rev) and rev in wanted
1168 return ff.match(rev) and rev in wanted
1167 else:
1169 else:
1168 def want(rev):
1170 def want(rev):
1169 return rev in wanted
1171 return rev in wanted
1170
1172
1171 for i, window in increasing_windows(0, len(revs)):
1173 for i, window in increasing_windows(0, len(revs)):
1172 change = util.cachefunc(repo.changectx)
1174 change = util.cachefunc(repo.changectx)
1173 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1175 nrevs = [rev for rev in revs[i:i + window] if want(rev)]
1174 for rev in sorted(nrevs):
1176 for rev in sorted(nrevs):
1175 fns = fncache.get(rev)
1177 fns = fncache.get(rev)
1176 ctx = change(rev)
1178 ctx = change(rev)
1177 if not fns:
1179 if not fns:
1178 def fns_generator():
1180 def fns_generator():
1179 for f in ctx.files():
1181 for f in ctx.files():
1180 if match(f):
1182 if match(f):
1181 yield f
1183 yield f
1182 fns = fns_generator()
1184 fns = fns_generator()
1183 prepare(ctx, fns)
1185 prepare(ctx, fns)
1184 for rev in nrevs:
1186 for rev in nrevs:
1185 yield change(rev)
1187 yield change(rev)
1186 return iterate()
1188 return iterate()
1187
1189
1188 def commit(ui, repo, commitfunc, pats, opts):
1190 def commit(ui, repo, commitfunc, pats, opts):
1189 '''commit the specified files or all outstanding changes'''
1191 '''commit the specified files or all outstanding changes'''
1190 date = opts.get('date')
1192 date = opts.get('date')
1191 if date:
1193 if date:
1192 opts['date'] = util.parsedate(date)
1194 opts['date'] = util.parsedate(date)
1193 message = logmessage(opts)
1195 message = logmessage(opts)
1194
1196
1195 # extract addremove carefully -- this function can be called from a command
1197 # extract addremove carefully -- this function can be called from a command
1196 # that doesn't support addremove
1198 # that doesn't support addremove
1197 if opts.get('addremove'):
1199 if opts.get('addremove'):
1198 addremove(repo, pats, opts)
1200 addremove(repo, pats, opts)
1199
1201
1200 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1202 return commitfunc(ui, repo, message, match(repo, pats, opts), opts)
1201
1203
1202 def commiteditor(repo, ctx, subs):
1204 def commiteditor(repo, ctx, subs):
1203 if ctx.description():
1205 if ctx.description():
1204 return ctx.description()
1206 return ctx.description()
1205 return commitforceeditor(repo, ctx, subs)
1207 return commitforceeditor(repo, ctx, subs)
1206
1208
1207 def commitforceeditor(repo, ctx, subs):
1209 def commitforceeditor(repo, ctx, subs):
1208 edittext = []
1210 edittext = []
1209 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1211 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
1210 if ctx.description():
1212 if ctx.description():
1211 edittext.append(ctx.description())
1213 edittext.append(ctx.description())
1212 edittext.append("")
1214 edittext.append("")
1213 edittext.append("") # Empty line between message and comments.
1215 edittext.append("") # Empty line between message and comments.
1214 edittext.append(_("HG: Enter commit message."
1216 edittext.append(_("HG: Enter commit message."
1215 " Lines beginning with 'HG:' are removed."))
1217 " Lines beginning with 'HG:' are removed."))
1216 edittext.append(_("HG: Leave message empty to abort commit."))
1218 edittext.append(_("HG: Leave message empty to abort commit."))
1217 edittext.append("HG: --")
1219 edittext.append("HG: --")
1218 edittext.append(_("HG: user: %s") % ctx.user())
1220 edittext.append(_("HG: user: %s") % ctx.user())
1219 if ctx.p2():
1221 if ctx.p2():
1220 edittext.append(_("HG: branch merge"))
1222 edittext.append(_("HG: branch merge"))
1221 if ctx.branch():
1223 if ctx.branch():
1222 edittext.append(_("HG: branch '%s'")
1224 edittext.append(_("HG: branch '%s'")
1223 % encoding.tolocal(ctx.branch()))
1225 % encoding.tolocal(ctx.branch()))
1224 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1226 edittext.extend([_("HG: subrepo %s") % s for s in subs])
1225 edittext.extend([_("HG: added %s") % f for f in added])
1227 edittext.extend([_("HG: added %s") % f for f in added])
1226 edittext.extend([_("HG: changed %s") % f for f in modified])
1228 edittext.extend([_("HG: changed %s") % f for f in modified])
1227 edittext.extend([_("HG: removed %s") % f for f in removed])
1229 edittext.extend([_("HG: removed %s") % f for f in removed])
1228 if not added and not modified and not removed:
1230 if not added and not modified and not removed:
1229 edittext.append(_("HG: no files changed"))
1231 edittext.append(_("HG: no files changed"))
1230 edittext.append("")
1232 edittext.append("")
1231 # run editor in the repository root
1233 # run editor in the repository root
1232 olddir = os.getcwd()
1234 olddir = os.getcwd()
1233 os.chdir(repo.root)
1235 os.chdir(repo.root)
1234 text = repo.ui.edit("\n".join(edittext), ctx.user())
1236 text = repo.ui.edit("\n".join(edittext), ctx.user())
1235 text = re.sub("(?m)^HG:.*\n", "", text)
1237 text = re.sub("(?m)^HG:.*\n", "", text)
1236 os.chdir(olddir)
1238 os.chdir(olddir)
1237
1239
1238 if not text.strip():
1240 if not text.strip():
1239 raise util.Abort(_("empty commit message"))
1241 raise util.Abort(_("empty commit message"))
1240
1242
1241 return text
1243 return text
@@ -1,4455 +1,4459
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, bundlerepo, extensions, copies, error
12 import hg, util, revlog, bundlerepo, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45 """
45 """
46
46
47 bad = []
47 bad = []
48 names = []
48 names = []
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 oldbad = m.bad
50 oldbad = m.bad
51 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
51 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
52
52
53 for f in repo.walk(m):
53 for f in repo.walk(m):
54 exact = m.exact(f)
54 exact = m.exact(f)
55 if exact or f not in repo.dirstate:
55 if exact or f not in repo.dirstate:
56 names.append(f)
56 names.append(f)
57 if ui.verbose or not exact:
57 if ui.verbose or not exact:
58 ui.status(_('adding %s\n') % m.rel(f))
58 ui.status(_('adding %s\n') % m.rel(f))
59 if not opts.get('dry_run'):
59 if not opts.get('dry_run'):
60 bad += [f for f in repo[None].add(names) if f in m.files()]
60 bad += [f for f in repo[None].add(names) if f in m.files()]
61 return bad and 1 or 0
61 return bad and 1 or 0
62
62
63 def addremove(ui, repo, *pats, **opts):
63 def addremove(ui, repo, *pats, **opts):
64 """add all new files, delete all missing files
64 """add all new files, delete all missing files
65
65
66 Add all new files and remove all missing files from the
66 Add all new files and remove all missing files from the
67 repository.
67 repository.
68
68
69 New files are ignored if they match any of the patterns in
69 New files are ignored if they match any of the patterns in
70 .hgignore. As with add, these changes take effect at the next
70 .hgignore. As with add, these changes take effect at the next
71 commit.
71 commit.
72
72
73 Use the -s/--similarity option to detect renamed files. With a
73 Use the -s/--similarity option to detect renamed files. With a
74 parameter greater than 0, this compares every removed file with
74 parameter greater than 0, this compares every removed file with
75 every added file and records those similar enough as renames. This
75 every added file and records those similar enough as renames. This
76 option takes a percentage between 0 (disabled) and 100 (files must
76 option takes a percentage between 0 (disabled) and 100 (files must
77 be identical) as its parameter. Detecting renamed files this way
77 be identical) as its parameter. Detecting renamed files this way
78 can be expensive.
78 can be expensive.
79
79
80 Returns 0 if all files are successfully added.
80 Returns 0 if all files are successfully added.
81 """
81 """
82 try:
82 try:
83 sim = float(opts.get('similarity') or 0)
83 sim = float(opts.get('similarity') or 0)
84 except ValueError:
84 except ValueError:
85 raise util.Abort(_('similarity must be a number'))
85 raise util.Abort(_('similarity must be a number'))
86 if sim < 0 or sim > 100:
86 if sim < 0 or sim > 100:
87 raise util.Abort(_('similarity must be between 0 and 100'))
87 raise util.Abort(_('similarity must be between 0 and 100'))
88 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
88 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
89
89
90 def annotate(ui, repo, *pats, **opts):
90 def annotate(ui, repo, *pats, **opts):
91 """show changeset information by line for each file
91 """show changeset information by line for each file
92
92
93 List changes in files, showing the revision id responsible for
93 List changes in files, showing the revision id responsible for
94 each line
94 each line
95
95
96 This command is useful for discovering when a change was made and
96 This command is useful for discovering when a change was made and
97 by whom.
97 by whom.
98
98
99 Without the -a/--text option, annotate will avoid processing files
99 Without the -a/--text option, annotate will avoid processing files
100 it detects as binary. With -a, annotate will annotate the file
100 it detects as binary. With -a, annotate will annotate the file
101 anyway, although the results will probably be neither useful
101 anyway, although the results will probably be neither useful
102 nor desirable.
102 nor desirable.
103
103
104 Returns 0 on success.
104 Returns 0 on success.
105 """
105 """
106 if opts.get('follow'):
106 if opts.get('follow'):
107 # --follow is deprecated and now just an alias for -f/--file
107 # --follow is deprecated and now just an alias for -f/--file
108 # to mimic the behavior of Mercurial before version 1.5
108 # to mimic the behavior of Mercurial before version 1.5
109 opts['file'] = 1
109 opts['file'] = 1
110
110
111 datefunc = ui.quiet and util.shortdate or util.datestr
111 datefunc = ui.quiet and util.shortdate or util.datestr
112 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
112 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
113
113
114 if not pats:
114 if not pats:
115 raise util.Abort(_('at least one filename or pattern is required'))
115 raise util.Abort(_('at least one filename or pattern is required'))
116
116
117 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
117 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
118 ('number', lambda x: str(x[0].rev())),
118 ('number', lambda x: str(x[0].rev())),
119 ('changeset', lambda x: short(x[0].node())),
119 ('changeset', lambda x: short(x[0].node())),
120 ('date', getdate),
120 ('date', getdate),
121 ('file', lambda x: x[0].path()),
121 ('file', lambda x: x[0].path()),
122 ]
122 ]
123
123
124 if (not opts.get('user') and not opts.get('changeset')
124 if (not opts.get('user') and not opts.get('changeset')
125 and not opts.get('date') and not opts.get('file')):
125 and not opts.get('date') and not opts.get('file')):
126 opts['number'] = 1
126 opts['number'] = 1
127
127
128 linenumber = opts.get('line_number') is not None
128 linenumber = opts.get('line_number') is not None
129 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
129 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
130 raise util.Abort(_('at least one of -n/-c is required for -l'))
130 raise util.Abort(_('at least one of -n/-c is required for -l'))
131
131
132 funcmap = [func for op, func in opmap if opts.get(op)]
132 funcmap = [func for op, func in opmap if opts.get(op)]
133 if linenumber:
133 if linenumber:
134 lastfunc = funcmap[-1]
134 lastfunc = funcmap[-1]
135 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
135 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
136
136
137 ctx = repo[opts.get('rev')]
137 ctx = repo[opts.get('rev')]
138 m = cmdutil.match(repo, pats, opts)
138 m = cmdutil.match(repo, pats, opts)
139 follow = not opts.get('no_follow')
139 follow = not opts.get('no_follow')
140 for abs in ctx.walk(m):
140 for abs in ctx.walk(m):
141 fctx = ctx[abs]
141 fctx = ctx[abs]
142 if not opts.get('text') and util.binary(fctx.data()):
142 if not opts.get('text') and util.binary(fctx.data()):
143 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
143 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
144 continue
144 continue
145
145
146 lines = fctx.annotate(follow=follow, linenumber=linenumber)
146 lines = fctx.annotate(follow=follow, linenumber=linenumber)
147 pieces = []
147 pieces = []
148
148
149 for f in funcmap:
149 for f in funcmap:
150 l = [f(n) for n, dummy in lines]
150 l = [f(n) for n, dummy in lines]
151 if l:
151 if l:
152 ml = max(map(len, l))
152 ml = max(map(len, l))
153 pieces.append(["%*s" % (ml, x) for x in l])
153 pieces.append(["%*s" % (ml, x) for x in l])
154
154
155 if pieces:
155 if pieces:
156 for p, l in zip(zip(*pieces), lines):
156 for p, l in zip(zip(*pieces), lines):
157 ui.write("%s: %s" % (" ".join(p), l[1]))
157 ui.write("%s: %s" % (" ".join(p), l[1]))
158
158
159 def archive(ui, repo, dest, **opts):
159 def archive(ui, repo, dest, **opts):
160 '''create an unversioned archive of a repository revision
160 '''create an unversioned archive of a repository revision
161
161
162 By default, the revision used is the parent of the working
162 By default, the revision used is the parent of the working
163 directory; use -r/--rev to specify a different revision.
163 directory; use -r/--rev to specify a different revision.
164
164
165 The archive type is automatically detected based on file
165 The archive type is automatically detected based on file
166 extension (or override using -t/--type).
166 extension (or override using -t/--type).
167
167
168 Valid types are:
168 Valid types are:
169
169
170 :``files``: a directory full of files (default)
170 :``files``: a directory full of files (default)
171 :``tar``: tar archive, uncompressed
171 :``tar``: tar archive, uncompressed
172 :``tbz2``: tar archive, compressed using bzip2
172 :``tbz2``: tar archive, compressed using bzip2
173 :``tgz``: tar archive, compressed using gzip
173 :``tgz``: tar archive, compressed using gzip
174 :``uzip``: zip archive, uncompressed
174 :``uzip``: zip archive, uncompressed
175 :``zip``: zip archive, compressed using deflate
175 :``zip``: zip archive, compressed using deflate
176
176
177 The exact name of the destination archive or directory is given
177 The exact name of the destination archive or directory is given
178 using a format string; see :hg:`help export` for details.
178 using a format string; see :hg:`help export` for details.
179
179
180 Each member added to an archive file has a directory prefix
180 Each member added to an archive file has a directory prefix
181 prepended. Use -p/--prefix to specify a format string for the
181 prepended. Use -p/--prefix to specify a format string for the
182 prefix. The default is the basename of the archive, with suffixes
182 prefix. The default is the basename of the archive, with suffixes
183 removed.
183 removed.
184
184
185 Returns 0 on success.
185 Returns 0 on success.
186 '''
186 '''
187
187
188 ctx = repo[opts.get('rev')]
188 ctx = repo[opts.get('rev')]
189 if not ctx:
189 if not ctx:
190 raise util.Abort(_('no working directory: please specify a revision'))
190 raise util.Abort(_('no working directory: please specify a revision'))
191 node = ctx.node()
191 node = ctx.node()
192 dest = cmdutil.make_filename(repo, dest, node)
192 dest = cmdutil.make_filename(repo, dest, node)
193 if os.path.realpath(dest) == repo.root:
193 if os.path.realpath(dest) == repo.root:
194 raise util.Abort(_('repository root cannot be destination'))
194 raise util.Abort(_('repository root cannot be destination'))
195
195
196 def guess_type():
196 def guess_type():
197 exttypes = {
197 exttypes = {
198 'tar': ['.tar'],
198 'tar': ['.tar'],
199 'tbz2': ['.tbz2', '.tar.bz2'],
199 'tbz2': ['.tbz2', '.tar.bz2'],
200 'tgz': ['.tgz', '.tar.gz'],
200 'tgz': ['.tgz', '.tar.gz'],
201 'zip': ['.zip'],
201 'zip': ['.zip'],
202 }
202 }
203
203
204 for type, extensions in exttypes.items():
204 for type, extensions in exttypes.items():
205 if util.any(dest.endswith(ext) for ext in extensions):
205 if util.any(dest.endswith(ext) for ext in extensions):
206 return type
206 return type
207 return None
207 return None
208
208
209 kind = opts.get('type') or guess_type() or 'files'
209 kind = opts.get('type') or guess_type() or 'files'
210 prefix = opts.get('prefix')
210 prefix = opts.get('prefix')
211
211
212 if dest == '-':
212 if dest == '-':
213 if kind == 'files':
213 if kind == 'files':
214 raise util.Abort(_('cannot archive plain files to stdout'))
214 raise util.Abort(_('cannot archive plain files to stdout'))
215 dest = sys.stdout
215 dest = sys.stdout
216 if not prefix:
216 if not prefix:
217 prefix = os.path.basename(repo.root) + '-%h'
217 prefix = os.path.basename(repo.root) + '-%h'
218
218
219 prefix = cmdutil.make_filename(repo, prefix, node)
219 prefix = cmdutil.make_filename(repo, prefix, node)
220 matchfn = cmdutil.match(repo, [], opts)
220 matchfn = cmdutil.match(repo, [], opts)
221 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
221 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
222 matchfn, prefix)
222 matchfn, prefix)
223
223
224 def backout(ui, repo, node=None, rev=None, **opts):
224 def backout(ui, repo, node=None, rev=None, **opts):
225 '''reverse effect of earlier changeset
225 '''reverse effect of earlier changeset
226
226
227 Commit the backed out changes as a new changeset. The new
227 Commit the backed out changes as a new changeset. The new
228 changeset is a child of the backed out changeset.
228 changeset is a child of the backed out changeset.
229
229
230 If you backout a changeset other than the tip, a new head is
230 If you backout a changeset other than the tip, a new head is
231 created. This head will be the new tip and you should merge this
231 created. This head will be the new tip and you should merge this
232 backout changeset with another head.
232 backout changeset with another head.
233
233
234 The --merge option remembers the parent of the working directory
234 The --merge option remembers the parent of the working directory
235 before starting the backout, then merges the new head with that
235 before starting the backout, then merges the new head with that
236 changeset afterwards. This saves you from doing the merge by hand.
236 changeset afterwards. This saves you from doing the merge by hand.
237 The result of this merge is not committed, as with a normal merge.
237 The result of this merge is not committed, as with a normal merge.
238
238
239 See :hg:`help dates` for a list of formats valid for -d/--date.
239 See :hg:`help dates` for a list of formats valid for -d/--date.
240
240
241 Returns 0 on success.
241 Returns 0 on success.
242 '''
242 '''
243 if rev and node:
243 if rev and node:
244 raise util.Abort(_("please specify just one revision"))
244 raise util.Abort(_("please specify just one revision"))
245
245
246 if not rev:
246 if not rev:
247 rev = node
247 rev = node
248
248
249 if not rev:
249 if not rev:
250 raise util.Abort(_("please specify a revision to backout"))
250 raise util.Abort(_("please specify a revision to backout"))
251
251
252 date = opts.get('date')
252 date = opts.get('date')
253 if date:
253 if date:
254 opts['date'] = util.parsedate(date)
254 opts['date'] = util.parsedate(date)
255
255
256 cmdutil.bail_if_changed(repo)
256 cmdutil.bail_if_changed(repo)
257 node = repo.lookup(rev)
257 node = repo.lookup(rev)
258
258
259 op1, op2 = repo.dirstate.parents()
259 op1, op2 = repo.dirstate.parents()
260 a = repo.changelog.ancestor(op1, node)
260 a = repo.changelog.ancestor(op1, node)
261 if a != node:
261 if a != node:
262 raise util.Abort(_('cannot backout change on a different branch'))
262 raise util.Abort(_('cannot backout change on a different branch'))
263
263
264 p1, p2 = repo.changelog.parents(node)
264 p1, p2 = repo.changelog.parents(node)
265 if p1 == nullid:
265 if p1 == nullid:
266 raise util.Abort(_('cannot backout a change with no parents'))
266 raise util.Abort(_('cannot backout a change with no parents'))
267 if p2 != nullid:
267 if p2 != nullid:
268 if not opts.get('parent'):
268 if not opts.get('parent'):
269 raise util.Abort(_('cannot backout a merge changeset without '
269 raise util.Abort(_('cannot backout a merge changeset without '
270 '--parent'))
270 '--parent'))
271 p = repo.lookup(opts['parent'])
271 p = repo.lookup(opts['parent'])
272 if p not in (p1, p2):
272 if p not in (p1, p2):
273 raise util.Abort(_('%s is not a parent of %s') %
273 raise util.Abort(_('%s is not a parent of %s') %
274 (short(p), short(node)))
274 (short(p), short(node)))
275 parent = p
275 parent = p
276 else:
276 else:
277 if opts.get('parent'):
277 if opts.get('parent'):
278 raise util.Abort(_('cannot use --parent on non-merge changeset'))
278 raise util.Abort(_('cannot use --parent on non-merge changeset'))
279 parent = p1
279 parent = p1
280
280
281 # the backout should appear on the same branch
281 # the backout should appear on the same branch
282 branch = repo.dirstate.branch()
282 branch = repo.dirstate.branch()
283 hg.clean(repo, node, show_stats=False)
283 hg.clean(repo, node, show_stats=False)
284 repo.dirstate.setbranch(branch)
284 repo.dirstate.setbranch(branch)
285 revert_opts = opts.copy()
285 revert_opts = opts.copy()
286 revert_opts['date'] = None
286 revert_opts['date'] = None
287 revert_opts['all'] = True
287 revert_opts['all'] = True
288 revert_opts['rev'] = hex(parent)
288 revert_opts['rev'] = hex(parent)
289 revert_opts['no_backup'] = None
289 revert_opts['no_backup'] = None
290 revert(ui, repo, **revert_opts)
290 revert(ui, repo, **revert_opts)
291 commit_opts = opts.copy()
291 commit_opts = opts.copy()
292 commit_opts['addremove'] = False
292 commit_opts['addremove'] = False
293 if not commit_opts['message'] and not commit_opts['logfile']:
293 if not commit_opts['message'] and not commit_opts['logfile']:
294 # we don't translate commit messages
294 # we don't translate commit messages
295 commit_opts['message'] = "Backed out changeset %s" % short(node)
295 commit_opts['message'] = "Backed out changeset %s" % short(node)
296 commit_opts['force_editor'] = True
296 commit_opts['force_editor'] = True
297 commit(ui, repo, **commit_opts)
297 commit(ui, repo, **commit_opts)
298 def nice(node):
298 def nice(node):
299 return '%d:%s' % (repo.changelog.rev(node), short(node))
299 return '%d:%s' % (repo.changelog.rev(node), short(node))
300 ui.status(_('changeset %s backs out changeset %s\n') %
300 ui.status(_('changeset %s backs out changeset %s\n') %
301 (nice(repo.changelog.tip()), nice(node)))
301 (nice(repo.changelog.tip()), nice(node)))
302 if op1 != node:
302 if op1 != node:
303 hg.clean(repo, op1, show_stats=False)
303 hg.clean(repo, op1, show_stats=False)
304 if opts.get('merge'):
304 if opts.get('merge'):
305 ui.status(_('merging with changeset %s\n')
305 ui.status(_('merging with changeset %s\n')
306 % nice(repo.changelog.tip()))
306 % nice(repo.changelog.tip()))
307 hg.merge(repo, hex(repo.changelog.tip()))
307 hg.merge(repo, hex(repo.changelog.tip()))
308 else:
308 else:
309 ui.status(_('the backout changeset is a new head - '
309 ui.status(_('the backout changeset is a new head - '
310 'do not forget to merge\n'))
310 'do not forget to merge\n'))
311 ui.status(_('(use "backout --merge" '
311 ui.status(_('(use "backout --merge" '
312 'if you want to auto-merge)\n'))
312 'if you want to auto-merge)\n'))
313
313
314 def bisect(ui, repo, rev=None, extra=None, command=None,
314 def bisect(ui, repo, rev=None, extra=None, command=None,
315 reset=None, good=None, bad=None, skip=None, noupdate=None):
315 reset=None, good=None, bad=None, skip=None, noupdate=None):
316 """subdivision search of changesets
316 """subdivision search of changesets
317
317
318 This command helps to find changesets which introduce problems. To
318 This command helps to find changesets which introduce problems. To
319 use, mark the earliest changeset you know exhibits the problem as
319 use, mark the earliest changeset you know exhibits the problem as
320 bad, then mark the latest changeset which is free from the problem
320 bad, then mark the latest changeset which is free from the problem
321 as good. Bisect will update your working directory to a revision
321 as good. Bisect will update your working directory to a revision
322 for testing (unless the -U/--noupdate option is specified). Once
322 for testing (unless the -U/--noupdate option is specified). Once
323 you have performed tests, mark the working directory as good or
323 you have performed tests, mark the working directory as good or
324 bad, and bisect will either update to another candidate changeset
324 bad, and bisect will either update to another candidate changeset
325 or announce that it has found the bad revision.
325 or announce that it has found the bad revision.
326
326
327 As a shortcut, you can also use the revision argument to mark a
327 As a shortcut, you can also use the revision argument to mark a
328 revision as good or bad without checking it out first.
328 revision as good or bad without checking it out first.
329
329
330 If you supply a command, it will be used for automatic bisection.
330 If you supply a command, it will be used for automatic bisection.
331 Its exit status will be used to mark revisions as good or bad:
331 Its exit status will be used to mark revisions as good or bad:
332 status 0 means good, 125 means to skip the revision, 127
332 status 0 means good, 125 means to skip the revision, 127
333 (command not found) will abort the bisection, and any other
333 (command not found) will abort the bisection, and any other
334 non-zero exit status means the revision is bad.
334 non-zero exit status means the revision is bad.
335
335
336 Returns 0 on success.
336 Returns 0 on success.
337 """
337 """
338 def print_result(nodes, good):
338 def print_result(nodes, good):
339 displayer = cmdutil.show_changeset(ui, repo, {})
339 displayer = cmdutil.show_changeset(ui, repo, {})
340 if len(nodes) == 1:
340 if len(nodes) == 1:
341 # narrowed it down to a single revision
341 # narrowed it down to a single revision
342 if good:
342 if good:
343 ui.write(_("The first good revision is:\n"))
343 ui.write(_("The first good revision is:\n"))
344 else:
344 else:
345 ui.write(_("The first bad revision is:\n"))
345 ui.write(_("The first bad revision is:\n"))
346 displayer.show(repo[nodes[0]])
346 displayer.show(repo[nodes[0]])
347 else:
347 else:
348 # multiple possible revisions
348 # multiple possible revisions
349 if good:
349 if good:
350 ui.write(_("Due to skipped revisions, the first "
350 ui.write(_("Due to skipped revisions, the first "
351 "good revision could be any of:\n"))
351 "good revision could be any of:\n"))
352 else:
352 else:
353 ui.write(_("Due to skipped revisions, the first "
353 ui.write(_("Due to skipped revisions, the first "
354 "bad revision could be any of:\n"))
354 "bad revision could be any of:\n"))
355 for n in nodes:
355 for n in nodes:
356 displayer.show(repo[n])
356 displayer.show(repo[n])
357 displayer.close()
357 displayer.close()
358
358
359 def check_state(state, interactive=True):
359 def check_state(state, interactive=True):
360 if not state['good'] or not state['bad']:
360 if not state['good'] or not state['bad']:
361 if (good or bad or skip or reset) and interactive:
361 if (good or bad or skip or reset) and interactive:
362 return
362 return
363 if not state['good']:
363 if not state['good']:
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
365 else:
365 else:
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
367 return True
367 return True
368
368
369 # backward compatibility
369 # backward compatibility
370 if rev in "good bad reset init".split():
370 if rev in "good bad reset init".split():
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
372 cmd, rev, extra = rev, extra, None
372 cmd, rev, extra = rev, extra, None
373 if cmd == "good":
373 if cmd == "good":
374 good = True
374 good = True
375 elif cmd == "bad":
375 elif cmd == "bad":
376 bad = True
376 bad = True
377 else:
377 else:
378 reset = True
378 reset = True
379 elif extra or good + bad + skip + reset + bool(command) > 1:
379 elif extra or good + bad + skip + reset + bool(command) > 1:
380 raise util.Abort(_('incompatible arguments'))
380 raise util.Abort(_('incompatible arguments'))
381
381
382 if reset:
382 if reset:
383 p = repo.join("bisect.state")
383 p = repo.join("bisect.state")
384 if os.path.exists(p):
384 if os.path.exists(p):
385 os.unlink(p)
385 os.unlink(p)
386 return
386 return
387
387
388 state = hbisect.load_state(repo)
388 state = hbisect.load_state(repo)
389
389
390 if command:
390 if command:
391 changesets = 1
391 changesets = 1
392 try:
392 try:
393 while changesets:
393 while changesets:
394 # update state
394 # update state
395 status = util.system(command)
395 status = util.system(command)
396 if status == 125:
396 if status == 125:
397 transition = "skip"
397 transition = "skip"
398 elif status == 0:
398 elif status == 0:
399 transition = "good"
399 transition = "good"
400 # status < 0 means process was killed
400 # status < 0 means process was killed
401 elif status == 127:
401 elif status == 127:
402 raise util.Abort(_("failed to execute %s") % command)
402 raise util.Abort(_("failed to execute %s") % command)
403 elif status < 0:
403 elif status < 0:
404 raise util.Abort(_("%s killed") % command)
404 raise util.Abort(_("%s killed") % command)
405 else:
405 else:
406 transition = "bad"
406 transition = "bad"
407 ctx = repo[rev or '.']
407 ctx = repo[rev or '.']
408 state[transition].append(ctx.node())
408 state[transition].append(ctx.node())
409 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
409 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
410 check_state(state, interactive=False)
410 check_state(state, interactive=False)
411 # bisect
411 # bisect
412 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
412 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
413 # update to next check
413 # update to next check
414 cmdutil.bail_if_changed(repo)
414 cmdutil.bail_if_changed(repo)
415 hg.clean(repo, nodes[0], show_stats=False)
415 hg.clean(repo, nodes[0], show_stats=False)
416 finally:
416 finally:
417 hbisect.save_state(repo, state)
417 hbisect.save_state(repo, state)
418 print_result(nodes, good)
418 print_result(nodes, good)
419 return
419 return
420
420
421 # update state
421 # update state
422 node = repo.lookup(rev or '.')
422 node = repo.lookup(rev or '.')
423 if good or bad or skip:
423 if good or bad or skip:
424 if good:
424 if good:
425 state['good'].append(node)
425 state['good'].append(node)
426 elif bad:
426 elif bad:
427 state['bad'].append(node)
427 state['bad'].append(node)
428 elif skip:
428 elif skip:
429 state['skip'].append(node)
429 state['skip'].append(node)
430 hbisect.save_state(repo, state)
430 hbisect.save_state(repo, state)
431
431
432 if not check_state(state):
432 if not check_state(state):
433 return
433 return
434
434
435 # actually bisect
435 # actually bisect
436 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
436 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
437 if changesets == 0:
437 if changesets == 0:
438 print_result(nodes, good)
438 print_result(nodes, good)
439 else:
439 else:
440 assert len(nodes) == 1 # only a single node can be tested next
440 assert len(nodes) == 1 # only a single node can be tested next
441 node = nodes[0]
441 node = nodes[0]
442 # compute the approximate number of remaining tests
442 # compute the approximate number of remaining tests
443 tests, size = 0, 2
443 tests, size = 0, 2
444 while size <= changesets:
444 while size <= changesets:
445 tests, size = tests + 1, size * 2
445 tests, size = tests + 1, size * 2
446 rev = repo.changelog.rev(node)
446 rev = repo.changelog.rev(node)
447 ui.write(_("Testing changeset %d:%s "
447 ui.write(_("Testing changeset %d:%s "
448 "(%d changesets remaining, ~%d tests)\n")
448 "(%d changesets remaining, ~%d tests)\n")
449 % (rev, short(node), changesets, tests))
449 % (rev, short(node), changesets, tests))
450 if not noupdate:
450 if not noupdate:
451 cmdutil.bail_if_changed(repo)
451 cmdutil.bail_if_changed(repo)
452 return hg.clean(repo, node)
452 return hg.clean(repo, node)
453
453
454 def branch(ui, repo, label=None, **opts):
454 def branch(ui, repo, label=None, **opts):
455 """set or show the current branch name
455 """set or show the current branch name
456
456
457 With no argument, show the current branch name. With one argument,
457 With no argument, show the current branch name. With one argument,
458 set the working directory branch name (the branch will not exist
458 set the working directory branch name (the branch will not exist
459 in the repository until the next commit). Standard practice
459 in the repository until the next commit). Standard practice
460 recommends that primary development take place on the 'default'
460 recommends that primary development take place on the 'default'
461 branch.
461 branch.
462
462
463 Unless -f/--force is specified, branch will not let you set a
463 Unless -f/--force is specified, branch will not let you set a
464 branch name that already exists, even if it's inactive.
464 branch name that already exists, even if it's inactive.
465
465
466 Use -C/--clean to reset the working directory branch to that of
466 Use -C/--clean to reset the working directory branch to that of
467 the parent of the working directory, negating a previous branch
467 the parent of the working directory, negating a previous branch
468 change.
468 change.
469
469
470 Use the command :hg:`update` to switch to an existing branch. Use
470 Use the command :hg:`update` to switch to an existing branch. Use
471 :hg:`commit --close-branch` to mark this branch as closed.
471 :hg:`commit --close-branch` to mark this branch as closed.
472
472
473 Returns 0 on success.
473 Returns 0 on success.
474 """
474 """
475
475
476 if opts.get('clean'):
476 if opts.get('clean'):
477 label = repo[None].parents()[0].branch()
477 label = repo[None].parents()[0].branch()
478 repo.dirstate.setbranch(label)
478 repo.dirstate.setbranch(label)
479 ui.status(_('reset working directory to branch %s\n') % label)
479 ui.status(_('reset working directory to branch %s\n') % label)
480 elif label:
480 elif label:
481 utflabel = encoding.fromlocal(label)
481 utflabel = encoding.fromlocal(label)
482 if not opts.get('force') and utflabel in repo.branchtags():
482 if not opts.get('force') and utflabel in repo.branchtags():
483 if label not in [p.branch() for p in repo.parents()]:
483 if label not in [p.branch() for p in repo.parents()]:
484 raise util.Abort(_('a branch of the same name already exists'
484 raise util.Abort(_('a branch of the same name already exists'
485 " (use 'hg update' to switch to it)"))
485 " (use 'hg update' to switch to it)"))
486 repo.dirstate.setbranch(utflabel)
486 repo.dirstate.setbranch(utflabel)
487 ui.status(_('marked working directory as branch %s\n') % label)
487 ui.status(_('marked working directory as branch %s\n') % label)
488 else:
488 else:
489 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
489 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
490
490
491 def branches(ui, repo, active=False, closed=False):
491 def branches(ui, repo, active=False, closed=False):
492 """list repository named branches
492 """list repository named branches
493
493
494 List the repository's named branches, indicating which ones are
494 List the repository's named branches, indicating which ones are
495 inactive. If -c/--closed is specified, also list branches which have
495 inactive. If -c/--closed is specified, also list branches which have
496 been marked closed (see :hg:`commit --close-branch`).
496 been marked closed (see :hg:`commit --close-branch`).
497
497
498 If -a/--active is specified, only show active branches. A branch
498 If -a/--active is specified, only show active branches. A branch
499 is considered active if it contains repository heads.
499 is considered active if it contains repository heads.
500
500
501 Use the command :hg:`update` to switch to an existing branch.
501 Use the command :hg:`update` to switch to an existing branch.
502
502
503 Returns 0.
503 Returns 0.
504 """
504 """
505
505
506 hexfunc = ui.debugflag and hex or short
506 hexfunc = ui.debugflag and hex or short
507 activebranches = [repo[n].branch() for n in repo.heads()]
507 activebranches = [repo[n].branch() for n in repo.heads()]
508 def testactive(tag, node):
508 def testactive(tag, node):
509 realhead = tag in activebranches
509 realhead = tag in activebranches
510 open = node in repo.branchheads(tag, closed=False)
510 open = node in repo.branchheads(tag, closed=False)
511 return realhead and open
511 return realhead and open
512 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
512 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
513 for tag, node in repo.branchtags().items()],
513 for tag, node in repo.branchtags().items()],
514 reverse=True)
514 reverse=True)
515
515
516 for isactive, node, tag in branches:
516 for isactive, node, tag in branches:
517 if (not active) or isactive:
517 if (not active) or isactive:
518 encodedtag = encoding.tolocal(tag)
518 encodedtag = encoding.tolocal(tag)
519 if ui.quiet:
519 if ui.quiet:
520 ui.write("%s\n" % encodedtag)
520 ui.write("%s\n" % encodedtag)
521 else:
521 else:
522 hn = repo.lookup(node)
522 hn = repo.lookup(node)
523 if isactive:
523 if isactive:
524 notice = ''
524 notice = ''
525 elif hn not in repo.branchheads(tag, closed=False):
525 elif hn not in repo.branchheads(tag, closed=False):
526 if not closed:
526 if not closed:
527 continue
527 continue
528 notice = _(' (closed)')
528 notice = _(' (closed)')
529 else:
529 else:
530 notice = _(' (inactive)')
530 notice = _(' (inactive)')
531 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
531 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
532 data = encodedtag, rev, hexfunc(hn), notice
532 data = encodedtag, rev, hexfunc(hn), notice
533 ui.write("%s %s:%s%s\n" % data)
533 ui.write("%s %s:%s%s\n" % data)
534
534
535 def bundle(ui, repo, fname, dest=None, **opts):
535 def bundle(ui, repo, fname, dest=None, **opts):
536 """create a changegroup file
536 """create a changegroup file
537
537
538 Generate a compressed changegroup file collecting changesets not
538 Generate a compressed changegroup file collecting changesets not
539 known to be in another repository.
539 known to be in another repository.
540
540
541 If you omit the destination repository, then hg assumes the
541 If you omit the destination repository, then hg assumes the
542 destination will have all the nodes you specify with --base
542 destination will have all the nodes you specify with --base
543 parameters. To create a bundle containing all changesets, use
543 parameters. To create a bundle containing all changesets, use
544 -a/--all (or --base null).
544 -a/--all (or --base null).
545
545
546 You can change compression method with the -t/--type option.
546 You can change compression method with the -t/--type option.
547 The available compression methods are: none, bzip2, and
547 The available compression methods are: none, bzip2, and
548 gzip (by default, bundles are compressed using bzip2).
548 gzip (by default, bundles are compressed using bzip2).
549
549
550 The bundle file can then be transferred using conventional means
550 The bundle file can then be transferred using conventional means
551 and applied to another repository with the unbundle or pull
551 and applied to another repository with the unbundle or pull
552 command. This is useful when direct push and pull are not
552 command. This is useful when direct push and pull are not
553 available or when exporting an entire repository is undesirable.
553 available or when exporting an entire repository is undesirable.
554
554
555 Applying bundles preserves all changeset contents including
555 Applying bundles preserves all changeset contents including
556 permissions, copy/rename information, and revision history.
556 permissions, copy/rename information, and revision history.
557
557
558 Returns 0 on success, 1 if no changes found.
558 Returns 0 on success, 1 if no changes found.
559 """
559 """
560 revs = opts.get('rev') or None
560 revs = opts.get('rev') or None
561 if revs:
561 if revs:
562 revs = [repo.lookup(rev) for rev in revs]
562 revs = [repo.lookup(rev) for rev in revs]
563 if opts.get('all'):
563 if opts.get('all'):
564 base = ['null']
564 base = ['null']
565 else:
565 else:
566 base = opts.get('base')
566 base = opts.get('base')
567 if base:
567 if base:
568 if dest:
568 if dest:
569 raise util.Abort(_("--base is incompatible with specifying "
569 raise util.Abort(_("--base is incompatible with specifying "
570 "a destination"))
570 "a destination"))
571 base = [repo.lookup(rev) for rev in base]
571 base = [repo.lookup(rev) for rev in base]
572 # create the right base
572 # create the right base
573 # XXX: nodesbetween / changegroup* should be "fixed" instead
573 # XXX: nodesbetween / changegroup* should be "fixed" instead
574 o = []
574 o = []
575 has = set((nullid,))
575 has = set((nullid,))
576 for n in base:
576 for n in base:
577 has.update(repo.changelog.reachable(n))
577 has.update(repo.changelog.reachable(n))
578 if revs:
578 if revs:
579 visit = list(revs)
579 visit = list(revs)
580 has.difference_update(revs)
580 has.difference_update(revs)
581 else:
581 else:
582 visit = repo.changelog.heads()
582 visit = repo.changelog.heads()
583 seen = {}
583 seen = {}
584 while visit:
584 while visit:
585 n = visit.pop(0)
585 n = visit.pop(0)
586 parents = [p for p in repo.changelog.parents(n) if p not in has]
586 parents = [p for p in repo.changelog.parents(n) if p not in has]
587 if len(parents) == 0:
587 if len(parents) == 0:
588 if n not in has:
588 if n not in has:
589 o.append(n)
589 o.append(n)
590 else:
590 else:
591 for p in parents:
591 for p in parents:
592 if p not in seen:
592 if p not in seen:
593 seen[p] = 1
593 seen[p] = 1
594 visit.append(p)
594 visit.append(p)
595 else:
595 else:
596 dest = ui.expandpath(dest or 'default-push', dest or 'default')
596 dest = ui.expandpath(dest or 'default-push', dest or 'default')
597 dest, branches = hg.parseurl(dest, opts.get('branch'))
597 dest, branches = hg.parseurl(dest, opts.get('branch'))
598 other = hg.repository(hg.remoteui(repo, opts), dest)
598 other = hg.repository(hg.remoteui(repo, opts), dest)
599 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
599 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
600 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
600 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
601
601
602 if not o:
602 if not o:
603 ui.status(_("no changes found\n"))
603 ui.status(_("no changes found\n"))
604 return 1
604 return 1
605
605
606 if revs:
606 if revs:
607 cg = repo.changegroupsubset(o, revs, 'bundle')
607 cg = repo.changegroupsubset(o, revs, 'bundle')
608 else:
608 else:
609 cg = repo.changegroup(o, 'bundle')
609 cg = repo.changegroup(o, 'bundle')
610
610
611 bundletype = opts.get('type', 'bzip2').lower()
611 bundletype = opts.get('type', 'bzip2').lower()
612 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
612 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
613 bundletype = btypes.get(bundletype)
613 bundletype = btypes.get(bundletype)
614 if bundletype not in changegroup.bundletypes:
614 if bundletype not in changegroup.bundletypes:
615 raise util.Abort(_('unknown bundle type specified with --type'))
615 raise util.Abort(_('unknown bundle type specified with --type'))
616
616
617 changegroup.writebundle(cg, fname, bundletype)
617 changegroup.writebundle(cg, fname, bundletype)
618
618
619 def cat(ui, repo, file1, *pats, **opts):
619 def cat(ui, repo, file1, *pats, **opts):
620 """output the current or given revision of files
620 """output the current or given revision of files
621
621
622 Print the specified files as they were at the given revision. If
622 Print the specified files as they were at the given revision. If
623 no revision is given, the parent of the working directory is used,
623 no revision is given, the parent of the working directory is used,
624 or tip if no revision is checked out.
624 or tip if no revision is checked out.
625
625
626 Output may be to a file, in which case the name of the file is
626 Output may be to a file, in which case the name of the file is
627 given using a format string. The formatting rules are the same as
627 given using a format string. The formatting rules are the same as
628 for the export command, with the following additions:
628 for the export command, with the following additions:
629
629
630 :``%s``: basename of file being printed
630 :``%s``: basename of file being printed
631 :``%d``: dirname of file being printed, or '.' if in repository root
631 :``%d``: dirname of file being printed, or '.' if in repository root
632 :``%p``: root-relative path name of file being printed
632 :``%p``: root-relative path name of file being printed
633
633
634 Returns 0 on success.
634 Returns 0 on success.
635 """
635 """
636 ctx = repo[opts.get('rev')]
636 ctx = repo[opts.get('rev')]
637 err = 1
637 err = 1
638 m = cmdutil.match(repo, (file1,) + pats, opts)
638 m = cmdutil.match(repo, (file1,) + pats, opts)
639 for abs in ctx.walk(m):
639 for abs in ctx.walk(m):
640 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
640 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
641 data = ctx[abs].data()
641 data = ctx[abs].data()
642 if opts.get('decode'):
642 if opts.get('decode'):
643 data = repo.wwritedata(abs, data)
643 data = repo.wwritedata(abs, data)
644 fp.write(data)
644 fp.write(data)
645 err = 0
645 err = 0
646 return err
646 return err
647
647
648 def clone(ui, source, dest=None, **opts):
648 def clone(ui, source, dest=None, **opts):
649 """make a copy of an existing repository
649 """make a copy of an existing repository
650
650
651 Create a copy of an existing repository in a new directory.
651 Create a copy of an existing repository in a new directory.
652
652
653 If no destination directory name is specified, it defaults to the
653 If no destination directory name is specified, it defaults to the
654 basename of the source.
654 basename of the source.
655
655
656 The location of the source is added to the new repository's
656 The location of the source is added to the new repository's
657 .hg/hgrc file, as the default to be used for future pulls.
657 .hg/hgrc file, as the default to be used for future pulls.
658
658
659 See :hg:`help urls` for valid source format details.
659 See :hg:`help urls` for valid source format details.
660
660
661 It is possible to specify an ``ssh://`` URL as the destination, but no
661 It is possible to specify an ``ssh://`` URL as the destination, but no
662 .hg/hgrc and working directory will be created on the remote side.
662 .hg/hgrc and working directory will be created on the remote side.
663 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
663 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
664
664
665 A set of changesets (tags, or branch names) to pull may be specified
665 A set of changesets (tags, or branch names) to pull may be specified
666 by listing each changeset (tag, or branch name) with -r/--rev.
666 by listing each changeset (tag, or branch name) with -r/--rev.
667 If -r/--rev is used, the cloned repository will contain only a subset
667 If -r/--rev is used, the cloned repository will contain only a subset
668 of the changesets of the source repository. Only the set of changesets
668 of the changesets of the source repository. Only the set of changesets
669 defined by all -r/--rev options (including all their ancestors)
669 defined by all -r/--rev options (including all their ancestors)
670 will be pulled into the destination repository.
670 will be pulled into the destination repository.
671 No subsequent changesets (including subsequent tags) will be present
671 No subsequent changesets (including subsequent tags) will be present
672 in the destination.
672 in the destination.
673
673
674 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
674 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
675 local source repositories.
675 local source repositories.
676
676
677 For efficiency, hardlinks are used for cloning whenever the source
677 For efficiency, hardlinks are used for cloning whenever the source
678 and destination are on the same filesystem (note this applies only
678 and destination are on the same filesystem (note this applies only
679 to the repository data, not to the working directory). Some
679 to the repository data, not to the working directory). Some
680 filesystems, such as AFS, implement hardlinking incorrectly, but
680 filesystems, such as AFS, implement hardlinking incorrectly, but
681 do not report errors. In these cases, use the --pull option to
681 do not report errors. In these cases, use the --pull option to
682 avoid hardlinking.
682 avoid hardlinking.
683
683
684 In some cases, you can clone repositories and the working directory
684 In some cases, you can clone repositories and the working directory
685 using full hardlinks with ::
685 using full hardlinks with ::
686
686
687 $ cp -al REPO REPOCLONE
687 $ cp -al REPO REPOCLONE
688
688
689 This is the fastest way to clone, but it is not always safe. The
689 This is the fastest way to clone, but it is not always safe. The
690 operation is not atomic (making sure REPO is not modified during
690 operation is not atomic (making sure REPO is not modified during
691 the operation is up to you) and you have to make sure your editor
691 the operation is up to you) and you have to make sure your editor
692 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
692 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
693 this is not compatible with certain extensions that place their
693 this is not compatible with certain extensions that place their
694 metadata under the .hg directory, such as mq.
694 metadata under the .hg directory, such as mq.
695
695
696 Mercurial will update the working directory to the first applicable
696 Mercurial will update the working directory to the first applicable
697 revision from this list:
697 revision from this list:
698
698
699 a) null if -U or the source repository has no changesets
699 a) null if -U or the source repository has no changesets
700 b) if -u . and the source repository is local, the first parent of
700 b) if -u . and the source repository is local, the first parent of
701 the source repository's working directory
701 the source repository's working directory
702 c) the changeset specified with -u (if a branch name, this means the
702 c) the changeset specified with -u (if a branch name, this means the
703 latest head of that branch)
703 latest head of that branch)
704 d) the changeset specified with -r
704 d) the changeset specified with -r
705 e) the tipmost head specified with -b
705 e) the tipmost head specified with -b
706 f) the tipmost head specified with the url#branch source syntax
706 f) the tipmost head specified with the url#branch source syntax
707 g) the tipmost head of the default branch
707 g) the tipmost head of the default branch
708 h) tip
708 h) tip
709
709
710 Returns 0 on success.
710 Returns 0 on success.
711 """
711 """
712 if opts.get('noupdate') and opts.get('updaterev'):
712 if opts.get('noupdate') and opts.get('updaterev'):
713 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
713 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
714
714
715 r = hg.clone(hg.remoteui(ui, opts), source, dest,
715 r = hg.clone(hg.remoteui(ui, opts), source, dest,
716 pull=opts.get('pull'),
716 pull=opts.get('pull'),
717 stream=opts.get('uncompressed'),
717 stream=opts.get('uncompressed'),
718 rev=opts.get('rev'),
718 rev=opts.get('rev'),
719 update=opts.get('updaterev') or not opts.get('noupdate'),
719 update=opts.get('updaterev') or not opts.get('noupdate'),
720 branch=opts.get('branch'))
720 branch=opts.get('branch'))
721
721
722 return r is None
722 return r is None
723
723
724 def commit(ui, repo, *pats, **opts):
724 def commit(ui, repo, *pats, **opts):
725 """commit the specified files or all outstanding changes
725 """commit the specified files or all outstanding changes
726
726
727 Commit changes to the given files into the repository. Unlike a
727 Commit changes to the given files into the repository. Unlike a
728 centralized RCS, this operation is a local operation. See
728 centralized RCS, this operation is a local operation. See
729 :hg:`push` for a way to actively distribute your changes.
729 :hg:`push` for a way to actively distribute your changes.
730
730
731 If a list of files is omitted, all changes reported by :hg:`status`
731 If a list of files is omitted, all changes reported by :hg:`status`
732 will be committed.
732 will be committed.
733
733
734 If you are committing the result of a merge, do not provide any
734 If you are committing the result of a merge, do not provide any
735 filenames or -I/-X filters.
735 filenames or -I/-X filters.
736
736
737 If no commit message is specified, the configured editor is
737 If no commit message is specified, the configured editor is
738 started to prompt you for a message.
738 started to prompt you for a message.
739
739
740 See :hg:`help dates` for a list of formats valid for -d/--date.
740 See :hg:`help dates` for a list of formats valid for -d/--date.
741
741
742 Returns 0 on success, 1 if nothing changed.
742 Returns 0 on success, 1 if nothing changed.
743 """
743 """
744 extra = {}
744 extra = {}
745 if opts.get('close_branch'):
745 if opts.get('close_branch'):
746 if repo['.'].node() not in repo.branchheads():
746 if repo['.'].node() not in repo.branchheads():
747 # The topo heads set is included in the branch heads set of the
747 # The topo heads set is included in the branch heads set of the
748 # current branch, so it's sufficient to test branchheads
748 # current branch, so it's sufficient to test branchheads
749 raise util.Abort(_('can only close branch heads'))
749 raise util.Abort(_('can only close branch heads'))
750 extra['close'] = 1
750 extra['close'] = 1
751 e = cmdutil.commiteditor
751 e = cmdutil.commiteditor
752 if opts.get('force_editor'):
752 if opts.get('force_editor'):
753 e = cmdutil.commitforceeditor
753 e = cmdutil.commitforceeditor
754
754
755 def commitfunc(ui, repo, message, match, opts):
755 def commitfunc(ui, repo, message, match, opts):
756 return repo.commit(message, opts.get('user'), opts.get('date'), match,
756 return repo.commit(message, opts.get('user'), opts.get('date'), match,
757 editor=e, extra=extra)
757 editor=e, extra=extra)
758
758
759 branch = repo[None].branch()
759 branch = repo[None].branch()
760 bheads = repo.branchheads(branch)
760 bheads = repo.branchheads(branch)
761
761
762 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
762 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
763 if not node:
763 if not node:
764 ui.status(_("nothing changed\n"))
764 ui.status(_("nothing changed\n"))
765 return 1
765 return 1
766
766
767 ctx = repo[node]
767 ctx = repo[node]
768 parents = ctx.parents()
768 parents = ctx.parents()
769
769
770 if bheads and not [x for x in parents
770 if bheads and not [x for x in parents
771 if x.node() in bheads and x.branch() == branch]:
771 if x.node() in bheads and x.branch() == branch]:
772 ui.status(_('created new head\n'))
772 ui.status(_('created new head\n'))
773 # The message is not printed for initial roots. For the other
773 # The message is not printed for initial roots. For the other
774 # changesets, it is printed in the following situations:
774 # changesets, it is printed in the following situations:
775 #
775 #
776 # Par column: for the 2 parents with ...
776 # Par column: for the 2 parents with ...
777 # N: null or no parent
777 # N: null or no parent
778 # B: parent is on another named branch
778 # B: parent is on another named branch
779 # C: parent is a regular non head changeset
779 # C: parent is a regular non head changeset
780 # H: parent was a branch head of the current branch
780 # H: parent was a branch head of the current branch
781 # Msg column: whether we print "created new head" message
781 # Msg column: whether we print "created new head" message
782 # In the following, it is assumed that there already exists some
782 # In the following, it is assumed that there already exists some
783 # initial branch heads of the current branch, otherwise nothing is
783 # initial branch heads of the current branch, otherwise nothing is
784 # printed anyway.
784 # printed anyway.
785 #
785 #
786 # Par Msg Comment
786 # Par Msg Comment
787 # NN y additional topo root
787 # NN y additional topo root
788 #
788 #
789 # BN y additional branch root
789 # BN y additional branch root
790 # CN y additional topo head
790 # CN y additional topo head
791 # HN n usual case
791 # HN n usual case
792 #
792 #
793 # BB y weird additional branch root
793 # BB y weird additional branch root
794 # CB y branch merge
794 # CB y branch merge
795 # HB n merge with named branch
795 # HB n merge with named branch
796 #
796 #
797 # CC y additional head from merge
797 # CC y additional head from merge
798 # CH n merge with a head
798 # CH n merge with a head
799 #
799 #
800 # HH n head merge: head count decreases
800 # HH n head merge: head count decreases
801
801
802 if not opts.get('close_branch'):
802 if not opts.get('close_branch'):
803 for r in parents:
803 for r in parents:
804 if r.extra().get('close'):
804 if r.extra().get('close'):
805 ui.status(_('reopening closed branch head %d\n') % r)
805 ui.status(_('reopening closed branch head %d\n') % r)
806
806
807 if ui.debugflag:
807 if ui.debugflag:
808 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
808 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
809 elif ui.verbose:
809 elif ui.verbose:
810 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
810 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
811
811
812 def copy(ui, repo, *pats, **opts):
812 def copy(ui, repo, *pats, **opts):
813 """mark files as copied for the next commit
813 """mark files as copied for the next commit
814
814
815 Mark dest as having copies of source files. If dest is a
815 Mark dest as having copies of source files. If dest is a
816 directory, copies are put in that directory. If dest is a file,
816 directory, copies are put in that directory. If dest is a file,
817 the source must be a single file.
817 the source must be a single file.
818
818
819 By default, this command copies the contents of files as they
819 By default, this command copies the contents of files as they
820 exist in the working directory. If invoked with -A/--after, the
820 exist in the working directory. If invoked with -A/--after, the
821 operation is recorded, but no copying is performed.
821 operation is recorded, but no copying is performed.
822
822
823 This command takes effect with the next commit. To undo a copy
823 This command takes effect with the next commit. To undo a copy
824 before that, see :hg:`revert`.
824 before that, see :hg:`revert`.
825
825
826 Returns 0 on success, 1 if errors are encountered.
826 Returns 0 on success, 1 if errors are encountered.
827 """
827 """
828 wlock = repo.wlock(False)
828 wlock = repo.wlock(False)
829 try:
829 try:
830 return cmdutil.copy(ui, repo, pats, opts)
830 return cmdutil.copy(ui, repo, pats, opts)
831 finally:
831 finally:
832 wlock.release()
832 wlock.release()
833
833
834 def debugancestor(ui, repo, *args):
834 def debugancestor(ui, repo, *args):
835 """find the ancestor revision of two revisions in a given index"""
835 """find the ancestor revision of two revisions in a given index"""
836 if len(args) == 3:
836 if len(args) == 3:
837 index, rev1, rev2 = args
837 index, rev1, rev2 = args
838 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
838 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
839 lookup = r.lookup
839 lookup = r.lookup
840 elif len(args) == 2:
840 elif len(args) == 2:
841 if not repo:
841 if not repo:
842 raise util.Abort(_("There is no Mercurial repository here "
842 raise util.Abort(_("There is no Mercurial repository here "
843 "(.hg not found)"))
843 "(.hg not found)"))
844 rev1, rev2 = args
844 rev1, rev2 = args
845 r = repo.changelog
845 r = repo.changelog
846 lookup = repo.lookup
846 lookup = repo.lookup
847 else:
847 else:
848 raise util.Abort(_('either two or three arguments required'))
848 raise util.Abort(_('either two or three arguments required'))
849 a = r.ancestor(lookup(rev1), lookup(rev2))
849 a = r.ancestor(lookup(rev1), lookup(rev2))
850 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
850 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
851
851
852 def debugbuilddag(ui, repo, text,
852 def debugbuilddag(ui, repo, text,
853 mergeable_file=False,
853 mergeable_file=False,
854 appended_file=False,
854 appended_file=False,
855 overwritten_file=False,
855 overwritten_file=False,
856 new_file=False):
856 new_file=False):
857 """builds a repo with a given dag from scratch in the current empty repo
857 """builds a repo with a given dag from scratch in the current empty repo
858
858
859 Elements:
859 Elements:
860
860
861 - "+n" is a linear run of n nodes based on the current default parent
861 - "+n" is a linear run of n nodes based on the current default parent
862 - "." is a single node based on the current default parent
862 - "." is a single node based on the current default parent
863 - "$" resets the default parent to null (implied at the start);
863 - "$" resets the default parent to null (implied at the start);
864 otherwise the default parent is always the last node created
864 otherwise the default parent is always the last node created
865 - "<p" sets the default parent to the backref p
865 - "<p" sets the default parent to the backref p
866 - "*p" is a fork at parent p, which is a backref
866 - "*p" is a fork at parent p, which is a backref
867 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
867 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
868 - "/p2" is a merge of the preceding node and p2
868 - "/p2" is a merge of the preceding node and p2
869 - ":tag" defines a local tag for the preceding node
869 - ":tag" defines a local tag for the preceding node
870 - "@branch" sets the named branch for subsequent nodes
870 - "@branch" sets the named branch for subsequent nodes
871 - "!command" runs the command using your shell
871 - "!command" runs the command using your shell
872 - "!!my command\\n" is like "!", but to the end of the line
872 - "!!my command\\n" is like "!", but to the end of the line
873 - "#...\\n" is a comment up to the end of the line
873 - "#...\\n" is a comment up to the end of the line
874
874
875 Whitespace between the above elements is ignored.
875 Whitespace between the above elements is ignored.
876
876
877 A backref is either
877 A backref is either
878
878
879 - a number n, which references the node curr-n, where curr is the current
879 - a number n, which references the node curr-n, where curr is the current
880 node, or
880 node, or
881 - the name of a local tag you placed earlier using ":tag", or
881 - the name of a local tag you placed earlier using ":tag", or
882 - empty to denote the default parent.
882 - empty to denote the default parent.
883
883
884 All string valued-elements are either strictly alphanumeric, or must
884 All string valued-elements are either strictly alphanumeric, or must
885 be enclosed in double quotes ("..."), with "\" as escape character.
885 be enclosed in double quotes ("..."), with "\" as escape character.
886
886
887 Note that the --overwritten-file and --appended-file options imply the
887 Note that the --overwritten-file and --appended-file options imply the
888 use of "HGMERGE=internal:local" during DAG buildup.
888 use of "HGMERGE=internal:local" during DAG buildup.
889 """
889 """
890
890
891 if not (mergeable_file or appended_file or overwritten_file or new_file):
891 if not (mergeable_file or appended_file or overwritten_file or new_file):
892 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
892 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
893
893
894 if len(repo.changelog) > 0:
894 if len(repo.changelog) > 0:
895 raise util.Abort(_('repository is not empty'))
895 raise util.Abort(_('repository is not empty'))
896
896
897 if overwritten_file or appended_file:
897 if overwritten_file or appended_file:
898 # we don't want to fail in merges during buildup
898 # we don't want to fail in merges during buildup
899 os.environ['HGMERGE'] = 'internal:local'
899 os.environ['HGMERGE'] = 'internal:local'
900
900
901 def writefile(fname, text, fmode="w"):
901 def writefile(fname, text, fmode="w"):
902 f = open(fname, fmode)
902 f = open(fname, fmode)
903 try:
903 try:
904 f.write(text)
904 f.write(text)
905 finally:
905 finally:
906 f.close()
906 f.close()
907
907
908 if mergeable_file:
908 if mergeable_file:
909 linesperrev = 2
909 linesperrev = 2
910 # determine number of revs in DAG
910 # determine number of revs in DAG
911 n = 0
911 n = 0
912 for type, data in dagparser.parsedag(text):
912 for type, data in dagparser.parsedag(text):
913 if type == 'n':
913 if type == 'n':
914 n += 1
914 n += 1
915 # make a file with k lines per rev
915 # make a file with k lines per rev
916 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
916 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
917 + "\n")
917 + "\n")
918
918
919 at = -1
919 at = -1
920 atbranch = 'default'
920 atbranch = 'default'
921 for type, data in dagparser.parsedag(text):
921 for type, data in dagparser.parsedag(text):
922 if type == 'n':
922 if type == 'n':
923 ui.status('node %s\n' % str(data))
923 ui.status('node %s\n' % str(data))
924 id, ps = data
924 id, ps = data
925 p1 = ps[0]
925 p1 = ps[0]
926 if p1 != at:
926 if p1 != at:
927 update(ui, repo, node=p1, clean=True)
927 update(ui, repo, node=p1, clean=True)
928 at = p1
928 at = p1
929 if repo.dirstate.branch() != atbranch:
929 if repo.dirstate.branch() != atbranch:
930 branch(ui, repo, atbranch, force=True)
930 branch(ui, repo, atbranch, force=True)
931 if len(ps) > 1:
931 if len(ps) > 1:
932 p2 = ps[1]
932 p2 = ps[1]
933 merge(ui, repo, node=p2)
933 merge(ui, repo, node=p2)
934
934
935 if mergeable_file:
935 if mergeable_file:
936 f = open("mf", "r+")
936 f = open("mf", "r+")
937 try:
937 try:
938 lines = f.read().split("\n")
938 lines = f.read().split("\n")
939 lines[id * linesperrev] += " r%i" % id
939 lines[id * linesperrev] += " r%i" % id
940 f.seek(0)
940 f.seek(0)
941 f.write("\n".join(lines))
941 f.write("\n".join(lines))
942 finally:
942 finally:
943 f.close()
943 f.close()
944
944
945 if appended_file:
945 if appended_file:
946 writefile("af", "r%i\n" % id, "a")
946 writefile("af", "r%i\n" % id, "a")
947
947
948 if overwritten_file:
948 if overwritten_file:
949 writefile("of", "r%i\n" % id)
949 writefile("of", "r%i\n" % id)
950
950
951 if new_file:
951 if new_file:
952 writefile("nf%i" % id, "r%i\n" % id)
952 writefile("nf%i" % id, "r%i\n" % id)
953
953
954 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
954 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
955 at = id
955 at = id
956 elif type == 'l':
956 elif type == 'l':
957 id, name = data
957 id, name = data
958 ui.status('tag %s\n' % name)
958 ui.status('tag %s\n' % name)
959 tag(ui, repo, name, local=True)
959 tag(ui, repo, name, local=True)
960 elif type == 'a':
960 elif type == 'a':
961 ui.status('branch %s\n' % data)
961 ui.status('branch %s\n' % data)
962 atbranch = data
962 atbranch = data
963 elif type in 'cC':
963 elif type in 'cC':
964 r = util.system(data, cwd=repo.root)
964 r = util.system(data, cwd=repo.root)
965 if r:
965 if r:
966 desc, r = util.explain_exit(r)
966 desc, r = util.explain_exit(r)
967 raise util.Abort(_('%s command %s') % (data, desc))
967 raise util.Abort(_('%s command %s') % (data, desc))
968
968
969 def debugcommands(ui, cmd='', *args):
969 def debugcommands(ui, cmd='', *args):
970 """list all available commands and options"""
970 """list all available commands and options"""
971 for cmd, vals in sorted(table.iteritems()):
971 for cmd, vals in sorted(table.iteritems()):
972 cmd = cmd.split('|')[0].strip('^')
972 cmd = cmd.split('|')[0].strip('^')
973 opts = ', '.join([i[1] for i in vals[1]])
973 opts = ', '.join([i[1] for i in vals[1]])
974 ui.write('%s: %s\n' % (cmd, opts))
974 ui.write('%s: %s\n' % (cmd, opts))
975
975
976 def debugcomplete(ui, cmd='', **opts):
976 def debugcomplete(ui, cmd='', **opts):
977 """returns the completion list associated with the given command"""
977 """returns the completion list associated with the given command"""
978
978
979 if opts.get('options'):
979 if opts.get('options'):
980 options = []
980 options = []
981 otables = [globalopts]
981 otables = [globalopts]
982 if cmd:
982 if cmd:
983 aliases, entry = cmdutil.findcmd(cmd, table, False)
983 aliases, entry = cmdutil.findcmd(cmd, table, False)
984 otables.append(entry[1])
984 otables.append(entry[1])
985 for t in otables:
985 for t in otables:
986 for o in t:
986 for o in t:
987 if "(DEPRECATED)" in o[3]:
987 if "(DEPRECATED)" in o[3]:
988 continue
988 continue
989 if o[0]:
989 if o[0]:
990 options.append('-%s' % o[0])
990 options.append('-%s' % o[0])
991 options.append('--%s' % o[1])
991 options.append('--%s' % o[1])
992 ui.write("%s\n" % "\n".join(options))
992 ui.write("%s\n" % "\n".join(options))
993 return
993 return
994
994
995 cmdlist = cmdutil.findpossible(cmd, table)
995 cmdlist = cmdutil.findpossible(cmd, table)
996 if ui.verbose:
996 if ui.verbose:
997 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
997 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
998 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
998 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
999
999
1000 def debugfsinfo(ui, path = "."):
1000 def debugfsinfo(ui, path = "."):
1001 """show information detected about current filesystem"""
1001 """show information detected about current filesystem"""
1002 open('.debugfsinfo', 'w').write('')
1002 open('.debugfsinfo', 'w').write('')
1003 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1003 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1004 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1004 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1005 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1005 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1006 and 'yes' or 'no'))
1006 and 'yes' or 'no'))
1007 os.unlink('.debugfsinfo')
1007 os.unlink('.debugfsinfo')
1008
1008
1009 def debugrebuildstate(ui, repo, rev="tip"):
1009 def debugrebuildstate(ui, repo, rev="tip"):
1010 """rebuild the dirstate as it would look like for the given revision"""
1010 """rebuild the dirstate as it would look like for the given revision"""
1011 ctx = repo[rev]
1011 ctx = repo[rev]
1012 wlock = repo.wlock()
1012 wlock = repo.wlock()
1013 try:
1013 try:
1014 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1014 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1015 finally:
1015 finally:
1016 wlock.release()
1016 wlock.release()
1017
1017
1018 def debugcheckstate(ui, repo):
1018 def debugcheckstate(ui, repo):
1019 """validate the correctness of the current dirstate"""
1019 """validate the correctness of the current dirstate"""
1020 parent1, parent2 = repo.dirstate.parents()
1020 parent1, parent2 = repo.dirstate.parents()
1021 m1 = repo[parent1].manifest()
1021 m1 = repo[parent1].manifest()
1022 m2 = repo[parent2].manifest()
1022 m2 = repo[parent2].manifest()
1023 errors = 0
1023 errors = 0
1024 for f in repo.dirstate:
1024 for f in repo.dirstate:
1025 state = repo.dirstate[f]
1025 state = repo.dirstate[f]
1026 if state in "nr" and f not in m1:
1026 if state in "nr" and f not in m1:
1027 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1027 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1028 errors += 1
1028 errors += 1
1029 if state in "a" and f in m1:
1029 if state in "a" and f in m1:
1030 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1030 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1031 errors += 1
1031 errors += 1
1032 if state in "m" and f not in m1 and f not in m2:
1032 if state in "m" and f not in m1 and f not in m2:
1033 ui.warn(_("%s in state %s, but not in either manifest\n") %
1033 ui.warn(_("%s in state %s, but not in either manifest\n") %
1034 (f, state))
1034 (f, state))
1035 errors += 1
1035 errors += 1
1036 for f in m1:
1036 for f in m1:
1037 state = repo.dirstate[f]
1037 state = repo.dirstate[f]
1038 if state not in "nrm":
1038 if state not in "nrm":
1039 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1039 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1040 errors += 1
1040 errors += 1
1041 if errors:
1041 if errors:
1042 error = _(".hg/dirstate inconsistent with current parent's manifest")
1042 error = _(".hg/dirstate inconsistent with current parent's manifest")
1043 raise util.Abort(error)
1043 raise util.Abort(error)
1044
1044
1045 def showconfig(ui, repo, *values, **opts):
1045 def showconfig(ui, repo, *values, **opts):
1046 """show combined config settings from all hgrc files
1046 """show combined config settings from all hgrc files
1047
1047
1048 With no arguments, print names and values of all config items.
1048 With no arguments, print names and values of all config items.
1049
1049
1050 With one argument of the form section.name, print just the value
1050 With one argument of the form section.name, print just the value
1051 of that config item.
1051 of that config item.
1052
1052
1053 With multiple arguments, print names and values of all config
1053 With multiple arguments, print names and values of all config
1054 items with matching section names.
1054 items with matching section names.
1055
1055
1056 With --debug, the source (filename and line number) is printed
1056 With --debug, the source (filename and line number) is printed
1057 for each config item.
1057 for each config item.
1058
1058
1059 Returns 0 on success.
1059 Returns 0 on success.
1060 """
1060 """
1061
1061
1062 for f in util.rcpath():
1062 for f in util.rcpath():
1063 ui.debug(_('read config from: %s\n') % f)
1063 ui.debug(_('read config from: %s\n') % f)
1064 untrusted = bool(opts.get('untrusted'))
1064 untrusted = bool(opts.get('untrusted'))
1065 if values:
1065 if values:
1066 if len([v for v in values if '.' in v]) > 1:
1066 if len([v for v in values if '.' in v]) > 1:
1067 raise util.Abort(_('only one config item permitted'))
1067 raise util.Abort(_('only one config item permitted'))
1068 for section, name, value in ui.walkconfig(untrusted=untrusted):
1068 for section, name, value in ui.walkconfig(untrusted=untrusted):
1069 sectname = section + '.' + name
1069 sectname = section + '.' + name
1070 if values:
1070 if values:
1071 for v in values:
1071 for v in values:
1072 if v == section:
1072 if v == section:
1073 ui.debug('%s: ' %
1073 ui.debug('%s: ' %
1074 ui.configsource(section, name, untrusted))
1074 ui.configsource(section, name, untrusted))
1075 ui.write('%s=%s\n' % (sectname, value))
1075 ui.write('%s=%s\n' % (sectname, value))
1076 elif v == sectname:
1076 elif v == sectname:
1077 ui.debug('%s: ' %
1077 ui.debug('%s: ' %
1078 ui.configsource(section, name, untrusted))
1078 ui.configsource(section, name, untrusted))
1079 ui.write(value, '\n')
1079 ui.write(value, '\n')
1080 else:
1080 else:
1081 ui.debug('%s: ' %
1081 ui.debug('%s: ' %
1082 ui.configsource(section, name, untrusted))
1082 ui.configsource(section, name, untrusted))
1083 ui.write('%s=%s\n' % (sectname, value))
1083 ui.write('%s=%s\n' % (sectname, value))
1084
1084
1085 def debugpushkey(ui, repopath, namespace, *keyinfo):
1085 def debugpushkey(ui, repopath, namespace, *keyinfo):
1086 '''access the pushkey key/value protocol
1086 '''access the pushkey key/value protocol
1087
1087
1088 With two args, list the keys in the given namespace.
1088 With two args, list the keys in the given namespace.
1089
1089
1090 With five args, set a key to new if it currently is set to old.
1090 With five args, set a key to new if it currently is set to old.
1091 Reports success or failure.
1091 Reports success or failure.
1092 '''
1092 '''
1093
1093
1094 target = hg.repository(ui, repopath)
1094 target = hg.repository(ui, repopath)
1095 if keyinfo:
1095 if keyinfo:
1096 key, old, new = keyinfo
1096 key, old, new = keyinfo
1097 r = target.pushkey(namespace, key, old, new)
1097 r = target.pushkey(namespace, key, old, new)
1098 ui.status(str(r) + '\n')
1098 ui.status(str(r) + '\n')
1099 return not(r)
1099 return not(r)
1100 else:
1100 else:
1101 for k, v in target.listkeys(namespace).iteritems():
1101 for k, v in target.listkeys(namespace).iteritems():
1102 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1102 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1103 v.encode('string-escape')))
1103 v.encode('string-escape')))
1104
1104
1105 def debugrevspec(ui, repo, expr):
1105 def debugrevspec(ui, repo, expr):
1106 '''parse and apply a revision specification'''
1106 '''parse and apply a revision specification'''
1107 if ui.verbose:
1107 if ui.verbose:
1108 tree = revset.parse(expr)
1108 tree = revset.parse(expr)
1109 ui.note(tree, "\n")
1109 ui.note(tree, "\n")
1110 func = revset.match(expr)
1110 func = revset.match(expr)
1111 for c in func(repo, range(len(repo))):
1111 for c in func(repo, range(len(repo))):
1112 ui.write("%s\n" % c)
1112 ui.write("%s\n" % c)
1113
1113
1114 def debugsetparents(ui, repo, rev1, rev2=None):
1114 def debugsetparents(ui, repo, rev1, rev2=None):
1115 """manually set the parents of the current working directory
1115 """manually set the parents of the current working directory
1116
1116
1117 This is useful for writing repository conversion tools, but should
1117 This is useful for writing repository conversion tools, but should
1118 be used with care.
1118 be used with care.
1119
1119
1120 Returns 0 on success.
1120 Returns 0 on success.
1121 """
1121 """
1122
1122
1123 if not rev2:
1123 if not rev2:
1124 rev2 = hex(nullid)
1124 rev2 = hex(nullid)
1125
1125
1126 wlock = repo.wlock()
1126 wlock = repo.wlock()
1127 try:
1127 try:
1128 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1128 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1129 finally:
1129 finally:
1130 wlock.release()
1130 wlock.release()
1131
1131
1132 def debugstate(ui, repo, nodates=None):
1132 def debugstate(ui, repo, nodates=None):
1133 """show the contents of the current dirstate"""
1133 """show the contents of the current dirstate"""
1134 timestr = ""
1134 timestr = ""
1135 showdate = not nodates
1135 showdate = not nodates
1136 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1136 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1137 if showdate:
1137 if showdate:
1138 if ent[3] == -1:
1138 if ent[3] == -1:
1139 # Pad or slice to locale representation
1139 # Pad or slice to locale representation
1140 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1140 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1141 time.localtime(0)))
1141 time.localtime(0)))
1142 timestr = 'unset'
1142 timestr = 'unset'
1143 timestr = (timestr[:locale_len] +
1143 timestr = (timestr[:locale_len] +
1144 ' ' * (locale_len - len(timestr)))
1144 ' ' * (locale_len - len(timestr)))
1145 else:
1145 else:
1146 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1146 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1147 time.localtime(ent[3]))
1147 time.localtime(ent[3]))
1148 if ent[1] & 020000:
1148 if ent[1] & 020000:
1149 mode = 'lnk'
1149 mode = 'lnk'
1150 else:
1150 else:
1151 mode = '%3o' % (ent[1] & 0777)
1151 mode = '%3o' % (ent[1] & 0777)
1152 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1152 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1153 for f in repo.dirstate.copies():
1153 for f in repo.dirstate.copies():
1154 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1154 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1155
1155
1156 def debugsub(ui, repo, rev=None):
1156 def debugsub(ui, repo, rev=None):
1157 if rev == '':
1157 if rev == '':
1158 rev = None
1158 rev = None
1159 for k, v in sorted(repo[rev].substate.items()):
1159 for k, v in sorted(repo[rev].substate.items()):
1160 ui.write('path %s\n' % k)
1160 ui.write('path %s\n' % k)
1161 ui.write(' source %s\n' % v[0])
1161 ui.write(' source %s\n' % v[0])
1162 ui.write(' revision %s\n' % v[1])
1162 ui.write(' revision %s\n' % v[1])
1163
1163
1164 def debugdag(ui, repo, file_=None, *revs, **opts):
1164 def debugdag(ui, repo, file_=None, *revs, **opts):
1165 """format the changelog or an index DAG as a concise textual description
1165 """format the changelog or an index DAG as a concise textual description
1166
1166
1167 If you pass a revlog index, the revlog's DAG is emitted. If you list
1167 If you pass a revlog index, the revlog's DAG is emitted. If you list
1168 revision numbers, they get labelled in the output as rN.
1168 revision numbers, they get labelled in the output as rN.
1169
1169
1170 Otherwise, the changelog DAG of the current repo is emitted.
1170 Otherwise, the changelog DAG of the current repo is emitted.
1171 """
1171 """
1172 spaces = opts.get('spaces')
1172 spaces = opts.get('spaces')
1173 dots = opts.get('dots')
1173 dots = opts.get('dots')
1174 if file_:
1174 if file_:
1175 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1175 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1176 revs = set((int(r) for r in revs))
1176 revs = set((int(r) for r in revs))
1177 def events():
1177 def events():
1178 for r in rlog:
1178 for r in rlog:
1179 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1179 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1180 if r in revs:
1180 if r in revs:
1181 yield 'l', (r, "r%i" % r)
1181 yield 'l', (r, "r%i" % r)
1182 elif repo:
1182 elif repo:
1183 cl = repo.changelog
1183 cl = repo.changelog
1184 tags = opts.get('tags')
1184 tags = opts.get('tags')
1185 branches = opts.get('branches')
1185 branches = opts.get('branches')
1186 if tags:
1186 if tags:
1187 labels = {}
1187 labels = {}
1188 for l, n in repo.tags().items():
1188 for l, n in repo.tags().items():
1189 labels.setdefault(cl.rev(n), []).append(l)
1189 labels.setdefault(cl.rev(n), []).append(l)
1190 def events():
1190 def events():
1191 b = "default"
1191 b = "default"
1192 for r in cl:
1192 for r in cl:
1193 if branches:
1193 if branches:
1194 newb = cl.read(cl.node(r))[5]['branch']
1194 newb = cl.read(cl.node(r))[5]['branch']
1195 if newb != b:
1195 if newb != b:
1196 yield 'a', newb
1196 yield 'a', newb
1197 b = newb
1197 b = newb
1198 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1198 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1199 if tags:
1199 if tags:
1200 ls = labels.get(r)
1200 ls = labels.get(r)
1201 if ls:
1201 if ls:
1202 for l in ls:
1202 for l in ls:
1203 yield 'l', (r, l)
1203 yield 'l', (r, l)
1204 else:
1204 else:
1205 raise util.Abort(_('need repo for changelog dag'))
1205 raise util.Abort(_('need repo for changelog dag'))
1206
1206
1207 for line in dagparser.dagtextlines(events(),
1207 for line in dagparser.dagtextlines(events(),
1208 addspaces=spaces,
1208 addspaces=spaces,
1209 wraplabels=True,
1209 wraplabels=True,
1210 wrapannotations=True,
1210 wrapannotations=True,
1211 wrapnonlinear=dots,
1211 wrapnonlinear=dots,
1212 usedots=dots,
1212 usedots=dots,
1213 maxlinewidth=70):
1213 maxlinewidth=70):
1214 ui.write(line)
1214 ui.write(line)
1215 ui.write("\n")
1215 ui.write("\n")
1216
1216
1217 def debugdata(ui, file_, rev):
1217 def debugdata(ui, file_, rev):
1218 """dump the contents of a data file revision"""
1218 """dump the contents of a data file revision"""
1219 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1219 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1220 try:
1220 try:
1221 ui.write(r.revision(r.lookup(rev)))
1221 ui.write(r.revision(r.lookup(rev)))
1222 except KeyError:
1222 except KeyError:
1223 raise util.Abort(_('invalid revision identifier %s') % rev)
1223 raise util.Abort(_('invalid revision identifier %s') % rev)
1224
1224
1225 def debugdate(ui, date, range=None, **opts):
1225 def debugdate(ui, date, range=None, **opts):
1226 """parse and display a date"""
1226 """parse and display a date"""
1227 if opts["extended"]:
1227 if opts["extended"]:
1228 d = util.parsedate(date, util.extendeddateformats)
1228 d = util.parsedate(date, util.extendeddateformats)
1229 else:
1229 else:
1230 d = util.parsedate(date)
1230 d = util.parsedate(date)
1231 ui.write("internal: %s %s\n" % d)
1231 ui.write("internal: %s %s\n" % d)
1232 ui.write("standard: %s\n" % util.datestr(d))
1232 ui.write("standard: %s\n" % util.datestr(d))
1233 if range:
1233 if range:
1234 m = util.matchdate(range)
1234 m = util.matchdate(range)
1235 ui.write("match: %s\n" % m(d[0]))
1235 ui.write("match: %s\n" % m(d[0]))
1236
1236
1237 def debugindex(ui, file_):
1237 def debugindex(ui, file_):
1238 """dump the contents of an index file"""
1238 """dump the contents of an index file"""
1239 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1239 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1240 ui.write(" rev offset length base linkrev"
1240 ui.write(" rev offset length base linkrev"
1241 " nodeid p1 p2\n")
1241 " nodeid p1 p2\n")
1242 for i in r:
1242 for i in r:
1243 node = r.node(i)
1243 node = r.node(i)
1244 try:
1244 try:
1245 pp = r.parents(node)
1245 pp = r.parents(node)
1246 except:
1246 except:
1247 pp = [nullid, nullid]
1247 pp = [nullid, nullid]
1248 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1248 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1249 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1249 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1250 short(node), short(pp[0]), short(pp[1])))
1250 short(node), short(pp[0]), short(pp[1])))
1251
1251
1252 def debugindexdot(ui, file_):
1252 def debugindexdot(ui, file_):
1253 """dump an index DAG as a graphviz dot file"""
1253 """dump an index DAG as a graphviz dot file"""
1254 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1254 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1255 ui.write("digraph G {\n")
1255 ui.write("digraph G {\n")
1256 for i in r:
1256 for i in r:
1257 node = r.node(i)
1257 node = r.node(i)
1258 pp = r.parents(node)
1258 pp = r.parents(node)
1259 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1259 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1260 if pp[1] != nullid:
1260 if pp[1] != nullid:
1261 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1261 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1262 ui.write("}\n")
1262 ui.write("}\n")
1263
1263
1264 def debuginstall(ui):
1264 def debuginstall(ui):
1265 '''test Mercurial installation
1265 '''test Mercurial installation
1266
1266
1267 Returns 0 on success.
1267 Returns 0 on success.
1268 '''
1268 '''
1269
1269
1270 def writetemp(contents):
1270 def writetemp(contents):
1271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1272 f = os.fdopen(fd, "wb")
1272 f = os.fdopen(fd, "wb")
1273 f.write(contents)
1273 f.write(contents)
1274 f.close()
1274 f.close()
1275 return name
1275 return name
1276
1276
1277 problems = 0
1277 problems = 0
1278
1278
1279 # encoding
1279 # encoding
1280 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1280 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1281 try:
1281 try:
1282 encoding.fromlocal("test")
1282 encoding.fromlocal("test")
1283 except util.Abort, inst:
1283 except util.Abort, inst:
1284 ui.write(" %s\n" % inst)
1284 ui.write(" %s\n" % inst)
1285 ui.write(_(" (check that your locale is properly set)\n"))
1285 ui.write(_(" (check that your locale is properly set)\n"))
1286 problems += 1
1286 problems += 1
1287
1287
1288 # compiled modules
1288 # compiled modules
1289 ui.status(_("Checking extensions...\n"))
1289 ui.status(_("Checking extensions...\n"))
1290 try:
1290 try:
1291 import bdiff, mpatch, base85
1291 import bdiff, mpatch, base85
1292 except Exception, inst:
1292 except Exception, inst:
1293 ui.write(" %s\n" % inst)
1293 ui.write(" %s\n" % inst)
1294 ui.write(_(" One or more extensions could not be found"))
1294 ui.write(_(" One or more extensions could not be found"))
1295 ui.write(_(" (check that you compiled the extensions)\n"))
1295 ui.write(_(" (check that you compiled the extensions)\n"))
1296 problems += 1
1296 problems += 1
1297
1297
1298 # templates
1298 # templates
1299 ui.status(_("Checking templates...\n"))
1299 ui.status(_("Checking templates...\n"))
1300 try:
1300 try:
1301 import templater
1301 import templater
1302 templater.templater(templater.templatepath("map-cmdline.default"))
1302 templater.templater(templater.templatepath("map-cmdline.default"))
1303 except Exception, inst:
1303 except Exception, inst:
1304 ui.write(" %s\n" % inst)
1304 ui.write(" %s\n" % inst)
1305 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1305 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1306 problems += 1
1306 problems += 1
1307
1307
1308 # patch
1308 # patch
1309 ui.status(_("Checking patch...\n"))
1309 ui.status(_("Checking patch...\n"))
1310 patchproblems = 0
1310 patchproblems = 0
1311 a = "1\n2\n3\n4\n"
1311 a = "1\n2\n3\n4\n"
1312 b = "1\n2\n3\ninsert\n4\n"
1312 b = "1\n2\n3\ninsert\n4\n"
1313 fa = writetemp(a)
1313 fa = writetemp(a)
1314 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1314 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1315 os.path.basename(fa))
1315 os.path.basename(fa))
1316 fd = writetemp(d)
1316 fd = writetemp(d)
1317
1317
1318 files = {}
1318 files = {}
1319 try:
1319 try:
1320 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1320 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1321 except util.Abort, e:
1321 except util.Abort, e:
1322 ui.write(_(" patch call failed:\n"))
1322 ui.write(_(" patch call failed:\n"))
1323 ui.write(" " + str(e) + "\n")
1323 ui.write(" " + str(e) + "\n")
1324 patchproblems += 1
1324 patchproblems += 1
1325 else:
1325 else:
1326 if list(files) != [os.path.basename(fa)]:
1326 if list(files) != [os.path.basename(fa)]:
1327 ui.write(_(" unexpected patch output!\n"))
1327 ui.write(_(" unexpected patch output!\n"))
1328 patchproblems += 1
1328 patchproblems += 1
1329 a = open(fa).read()
1329 a = open(fa).read()
1330 if a != b:
1330 if a != b:
1331 ui.write(_(" patch test failed!\n"))
1331 ui.write(_(" patch test failed!\n"))
1332 patchproblems += 1
1332 patchproblems += 1
1333
1333
1334 if patchproblems:
1334 if patchproblems:
1335 if ui.config('ui', 'patch'):
1335 if ui.config('ui', 'patch'):
1336 ui.write(_(" (Current patch tool may be incompatible with patch,"
1336 ui.write(_(" (Current patch tool may be incompatible with patch,"
1337 " or misconfigured. Please check your .hgrc file)\n"))
1337 " or misconfigured. Please check your .hgrc file)\n"))
1338 else:
1338 else:
1339 ui.write(_(" Internal patcher failure, please report this error"
1339 ui.write(_(" Internal patcher failure, please report this error"
1340 " to http://mercurial.selenic.com/bts/\n"))
1340 " to http://mercurial.selenic.com/bts/\n"))
1341 problems += patchproblems
1341 problems += patchproblems
1342
1342
1343 os.unlink(fa)
1343 os.unlink(fa)
1344 os.unlink(fd)
1344 os.unlink(fd)
1345
1345
1346 # editor
1346 # editor
1347 ui.status(_("Checking commit editor...\n"))
1347 ui.status(_("Checking commit editor...\n"))
1348 editor = ui.geteditor()
1348 editor = ui.geteditor()
1349 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1349 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1350 if not cmdpath:
1350 if not cmdpath:
1351 if editor == 'vi':
1351 if editor == 'vi':
1352 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1352 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1353 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1353 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1354 else:
1354 else:
1355 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1355 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1356 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1356 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1357 problems += 1
1357 problems += 1
1358
1358
1359 # check username
1359 # check username
1360 ui.status(_("Checking username...\n"))
1360 ui.status(_("Checking username...\n"))
1361 try:
1361 try:
1362 user = ui.username()
1362 user = ui.username()
1363 except util.Abort, e:
1363 except util.Abort, e:
1364 ui.write(" %s\n" % e)
1364 ui.write(" %s\n" % e)
1365 ui.write(_(" (specify a username in your .hgrc file)\n"))
1365 ui.write(_(" (specify a username in your .hgrc file)\n"))
1366 problems += 1
1366 problems += 1
1367
1367
1368 if not problems:
1368 if not problems:
1369 ui.status(_("No problems detected\n"))
1369 ui.status(_("No problems detected\n"))
1370 else:
1370 else:
1371 ui.write(_("%s problems detected,"
1371 ui.write(_("%s problems detected,"
1372 " please check your install!\n") % problems)
1372 " please check your install!\n") % problems)
1373
1373
1374 return problems
1374 return problems
1375
1375
1376 def debugrename(ui, repo, file1, *pats, **opts):
1376 def debugrename(ui, repo, file1, *pats, **opts):
1377 """dump rename information"""
1377 """dump rename information"""
1378
1378
1379 ctx = repo[opts.get('rev')]
1379 ctx = repo[opts.get('rev')]
1380 m = cmdutil.match(repo, (file1,) + pats, opts)
1380 m = cmdutil.match(repo, (file1,) + pats, opts)
1381 for abs in ctx.walk(m):
1381 for abs in ctx.walk(m):
1382 fctx = ctx[abs]
1382 fctx = ctx[abs]
1383 o = fctx.filelog().renamed(fctx.filenode())
1383 o = fctx.filelog().renamed(fctx.filenode())
1384 rel = m.rel(abs)
1384 rel = m.rel(abs)
1385 if o:
1385 if o:
1386 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1386 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1387 else:
1387 else:
1388 ui.write(_("%s not renamed\n") % rel)
1388 ui.write(_("%s not renamed\n") % rel)
1389
1389
1390 def debugwalk(ui, repo, *pats, **opts):
1390 def debugwalk(ui, repo, *pats, **opts):
1391 """show how files match on given patterns"""
1391 """show how files match on given patterns"""
1392 m = cmdutil.match(repo, pats, opts)
1392 m = cmdutil.match(repo, pats, opts)
1393 items = list(repo.walk(m))
1393 items = list(repo.walk(m))
1394 if not items:
1394 if not items:
1395 return
1395 return
1396 fmt = 'f %%-%ds %%-%ds %%s' % (
1396 fmt = 'f %%-%ds %%-%ds %%s' % (
1397 max([len(abs) for abs in items]),
1397 max([len(abs) for abs in items]),
1398 max([len(m.rel(abs)) for abs in items]))
1398 max([len(m.rel(abs)) for abs in items]))
1399 for abs in items:
1399 for abs in items:
1400 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1400 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1401 ui.write("%s\n" % line.rstrip())
1401 ui.write("%s\n" % line.rstrip())
1402
1402
1403 def diff(ui, repo, *pats, **opts):
1403 def diff(ui, repo, *pats, **opts):
1404 """diff repository (or selected files)
1404 """diff repository (or selected files)
1405
1405
1406 Show differences between revisions for the specified files.
1406 Show differences between revisions for the specified files.
1407
1407
1408 Differences between files are shown using the unified diff format.
1408 Differences between files are shown using the unified diff format.
1409
1409
1410 NOTE: diff may generate unexpected results for merges, as it will
1410 NOTE: diff may generate unexpected results for merges, as it will
1411 default to comparing against the working directory's first parent
1411 default to comparing against the working directory's first parent
1412 changeset if no revisions are specified.
1412 changeset if no revisions are specified.
1413
1413
1414 When two revision arguments are given, then changes are shown
1414 When two revision arguments are given, then changes are shown
1415 between those revisions. If only one revision is specified then
1415 between those revisions. If only one revision is specified then
1416 that revision is compared to the working directory, and, when no
1416 that revision is compared to the working directory, and, when no
1417 revisions are specified, the working directory files are compared
1417 revisions are specified, the working directory files are compared
1418 to its parent.
1418 to its parent.
1419
1419
1420 Alternatively you can specify -c/--change with a revision to see
1420 Alternatively you can specify -c/--change with a revision to see
1421 the changes in that changeset relative to its first parent.
1421 the changes in that changeset relative to its first parent.
1422
1422
1423 Without the -a/--text option, diff will avoid generating diffs of
1423 Without the -a/--text option, diff will avoid generating diffs of
1424 files it detects as binary. With -a, diff will generate a diff
1424 files it detects as binary. With -a, diff will generate a diff
1425 anyway, probably with undesirable results.
1425 anyway, probably with undesirable results.
1426
1426
1427 Use the -g/--git option to generate diffs in the git extended diff
1427 Use the -g/--git option to generate diffs in the git extended diff
1428 format. For more information, read :hg:`help diffs`.
1428 format. For more information, read :hg:`help diffs`.
1429
1429
1430 Returns 0 on success.
1430 Returns 0 on success.
1431 """
1431 """
1432
1432
1433 revs = opts.get('rev')
1433 revs = opts.get('rev')
1434 change = opts.get('change')
1434 change = opts.get('change')
1435 stat = opts.get('stat')
1435 stat = opts.get('stat')
1436 reverse = opts.get('reverse')
1436 reverse = opts.get('reverse')
1437
1437
1438 if revs and change:
1438 if revs and change:
1439 msg = _('cannot specify --rev and --change at the same time')
1439 msg = _('cannot specify --rev and --change at the same time')
1440 raise util.Abort(msg)
1440 raise util.Abort(msg)
1441 elif change:
1441 elif change:
1442 node2 = repo.lookup(change)
1442 node2 = repo.lookup(change)
1443 node1 = repo[node2].parents()[0].node()
1443 node1 = repo[node2].parents()[0].node()
1444 else:
1444 else:
1445 node1, node2 = cmdutil.revpair(repo, revs)
1445 node1, node2 = cmdutil.revpair(repo, revs)
1446
1446
1447 if reverse:
1447 if reverse:
1448 node1, node2 = node2, node1
1448 node1, node2 = node2, node1
1449
1449
1450 diffopts = patch.diffopts(ui, opts)
1450 diffopts = patch.diffopts(ui, opts)
1451 m = cmdutil.match(repo, pats, opts)
1451 m = cmdutil.match(repo, pats, opts)
1452 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1452 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1453
1453
1454 def export(ui, repo, *changesets, **opts):
1454 def export(ui, repo, *changesets, **opts):
1455 """dump the header and diffs for one or more changesets
1455 """dump the header and diffs for one or more changesets
1456
1456
1457 Print the changeset header and diffs for one or more revisions.
1457 Print the changeset header and diffs for one or more revisions.
1458
1458
1459 The information shown in the changeset header is: author, date,
1459 The information shown in the changeset header is: author, date,
1460 branch name (if non-default), changeset hash, parent(s) and commit
1460 branch name (if non-default), changeset hash, parent(s) and commit
1461 comment.
1461 comment.
1462
1462
1463 NOTE: export may generate unexpected diff output for merge
1463 NOTE: export may generate unexpected diff output for merge
1464 changesets, as it will compare the merge changeset against its
1464 changesets, as it will compare the merge changeset against its
1465 first parent only.
1465 first parent only.
1466
1466
1467 Output may be to a file, in which case the name of the file is
1467 Output may be to a file, in which case the name of the file is
1468 given using a format string. The formatting rules are as follows:
1468 given using a format string. The formatting rules are as follows:
1469
1469
1470 :``%%``: literal "%" character
1470 :``%%``: literal "%" character
1471 :``%H``: changeset hash (40 bytes of hexadecimal)
1471 :``%H``: changeset hash (40 bytes of hexadecimal)
1472 :``%N``: number of patches being generated
1472 :``%N``: number of patches being generated
1473 :``%R``: changeset revision number
1473 :``%R``: changeset revision number
1474 :``%b``: basename of the exporting repository
1474 :``%b``: basename of the exporting repository
1475 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1475 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1476 :``%n``: zero-padded sequence number, starting at 1
1476 :``%n``: zero-padded sequence number, starting at 1
1477 :``%r``: zero-padded changeset revision number
1477 :``%r``: zero-padded changeset revision number
1478
1478
1479 Without the -a/--text option, export will avoid generating diffs
1479 Without the -a/--text option, export will avoid generating diffs
1480 of files it detects as binary. With -a, export will generate a
1480 of files it detects as binary. With -a, export will generate a
1481 diff anyway, probably with undesirable results.
1481 diff anyway, probably with undesirable results.
1482
1482
1483 Use the -g/--git option to generate diffs in the git extended diff
1483 Use the -g/--git option to generate diffs in the git extended diff
1484 format. See :hg:`help diffs` for more information.
1484 format. See :hg:`help diffs` for more information.
1485
1485
1486 With the --switch-parent option, the diff will be against the
1486 With the --switch-parent option, the diff will be against the
1487 second parent. It can be useful to review a merge.
1487 second parent. It can be useful to review a merge.
1488
1488
1489 Returns 0 on success.
1489 Returns 0 on success.
1490 """
1490 """
1491 changesets += tuple(opts.get('rev', []))
1491 changesets += tuple(opts.get('rev', []))
1492 if not changesets:
1492 if not changesets:
1493 raise util.Abort(_("export requires at least one changeset"))
1493 raise util.Abort(_("export requires at least one changeset"))
1494 revs = cmdutil.revrange(repo, changesets)
1494 revs = cmdutil.revrange(repo, changesets)
1495 if len(revs) > 1:
1495 if len(revs) > 1:
1496 ui.note(_('exporting patches:\n'))
1496 ui.note(_('exporting patches:\n'))
1497 else:
1497 else:
1498 ui.note(_('exporting patch:\n'))
1498 ui.note(_('exporting patch:\n'))
1499 cmdutil.export(repo, revs, template=opts.get('output'),
1499 cmdutil.export(repo, revs, template=opts.get('output'),
1500 switch_parent=opts.get('switch_parent'),
1500 switch_parent=opts.get('switch_parent'),
1501 opts=patch.diffopts(ui, opts))
1501 opts=patch.diffopts(ui, opts))
1502
1502
1503 def forget(ui, repo, *pats, **opts):
1503 def forget(ui, repo, *pats, **opts):
1504 """forget the specified files on the next commit
1504 """forget the specified files on the next commit
1505
1505
1506 Mark the specified files so they will no longer be tracked
1506 Mark the specified files so they will no longer be tracked
1507 after the next commit.
1507 after the next commit.
1508
1508
1509 This only removes files from the current branch, not from the
1509 This only removes files from the current branch, not from the
1510 entire project history, and it does not delete them from the
1510 entire project history, and it does not delete them from the
1511 working directory.
1511 working directory.
1512
1512
1513 To undo a forget before the next commit, see :hg:`add`.
1513 To undo a forget before the next commit, see :hg:`add`.
1514
1514
1515 Returns 0 on success.
1515 Returns 0 on success.
1516 """
1516 """
1517
1517
1518 if not pats:
1518 if not pats:
1519 raise util.Abort(_('no files specified'))
1519 raise util.Abort(_('no files specified'))
1520
1520
1521 m = cmdutil.match(repo, pats, opts)
1521 m = cmdutil.match(repo, pats, opts)
1522 s = repo.status(match=m, clean=True)
1522 s = repo.status(match=m, clean=True)
1523 forget = sorted(s[0] + s[1] + s[3] + s[6])
1523 forget = sorted(s[0] + s[1] + s[3] + s[6])
1524 errs = 0
1524 errs = 0
1525
1525
1526 for f in m.files():
1526 for f in m.files():
1527 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1527 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1528 ui.warn(_('not removing %s: file is already untracked\n')
1528 ui.warn(_('not removing %s: file is already untracked\n')
1529 % m.rel(f))
1529 % m.rel(f))
1530 errs = 1
1530 errs = 1
1531
1531
1532 for f in forget:
1532 for f in forget:
1533 if ui.verbose or not m.exact(f):
1533 if ui.verbose or not m.exact(f):
1534 ui.status(_('removing %s\n') % m.rel(f))
1534 ui.status(_('removing %s\n') % m.rel(f))
1535
1535
1536 repo[None].remove(forget, unlink=False)
1536 repo[None].remove(forget, unlink=False)
1537 return errs
1537 return errs
1538
1538
1539 def grep(ui, repo, pattern, *pats, **opts):
1539 def grep(ui, repo, pattern, *pats, **opts):
1540 """search for a pattern in specified files and revisions
1540 """search for a pattern in specified files and revisions
1541
1541
1542 Search revisions of files for a regular expression.
1542 Search revisions of files for a regular expression.
1543
1543
1544 This command behaves differently than Unix grep. It only accepts
1544 This command behaves differently than Unix grep. It only accepts
1545 Python/Perl regexps. It searches repository history, not the
1545 Python/Perl regexps. It searches repository history, not the
1546 working directory. It always prints the revision number in which a
1546 working directory. It always prints the revision number in which a
1547 match appears.
1547 match appears.
1548
1548
1549 By default, grep only prints output for the first revision of a
1549 By default, grep only prints output for the first revision of a
1550 file in which it finds a match. To get it to print every revision
1550 file in which it finds a match. To get it to print every revision
1551 that contains a change in match status ("-" for a match that
1551 that contains a change in match status ("-" for a match that
1552 becomes a non-match, or "+" for a non-match that becomes a match),
1552 becomes a non-match, or "+" for a non-match that becomes a match),
1553 use the --all flag.
1553 use the --all flag.
1554
1554
1555 Returns 0 if a match is found, 1 otherwise.
1555 Returns 0 if a match is found, 1 otherwise.
1556 """
1556 """
1557 reflags = 0
1557 reflags = 0
1558 if opts.get('ignore_case'):
1558 if opts.get('ignore_case'):
1559 reflags |= re.I
1559 reflags |= re.I
1560 try:
1560 try:
1561 regexp = re.compile(pattern, reflags)
1561 regexp = re.compile(pattern, reflags)
1562 except Exception, inst:
1562 except Exception, inst:
1563 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1563 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1564 return 1
1564 return 1
1565 sep, eol = ':', '\n'
1565 sep, eol = ':', '\n'
1566 if opts.get('print0'):
1566 if opts.get('print0'):
1567 sep = eol = '\0'
1567 sep = eol = '\0'
1568
1568
1569 getfile = util.lrucachefunc(repo.file)
1569 getfile = util.lrucachefunc(repo.file)
1570
1570
1571 def matchlines(body):
1571 def matchlines(body):
1572 begin = 0
1572 begin = 0
1573 linenum = 0
1573 linenum = 0
1574 while True:
1574 while True:
1575 match = regexp.search(body, begin)
1575 match = regexp.search(body, begin)
1576 if not match:
1576 if not match:
1577 break
1577 break
1578 mstart, mend = match.span()
1578 mstart, mend = match.span()
1579 linenum += body.count('\n', begin, mstart) + 1
1579 linenum += body.count('\n', begin, mstart) + 1
1580 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1580 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1581 begin = body.find('\n', mend) + 1 or len(body)
1581 begin = body.find('\n', mend) + 1 or len(body)
1582 lend = begin - 1
1582 lend = begin - 1
1583 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1583 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1584
1584
1585 class linestate(object):
1585 class linestate(object):
1586 def __init__(self, line, linenum, colstart, colend):
1586 def __init__(self, line, linenum, colstart, colend):
1587 self.line = line
1587 self.line = line
1588 self.linenum = linenum
1588 self.linenum = linenum
1589 self.colstart = colstart
1589 self.colstart = colstart
1590 self.colend = colend
1590 self.colend = colend
1591
1591
1592 def __hash__(self):
1592 def __hash__(self):
1593 return hash((self.linenum, self.line))
1593 return hash((self.linenum, self.line))
1594
1594
1595 def __eq__(self, other):
1595 def __eq__(self, other):
1596 return self.line == other.line
1596 return self.line == other.line
1597
1597
1598 matches = {}
1598 matches = {}
1599 copies = {}
1599 copies = {}
1600 def grepbody(fn, rev, body):
1600 def grepbody(fn, rev, body):
1601 matches[rev].setdefault(fn, [])
1601 matches[rev].setdefault(fn, [])
1602 m = matches[rev][fn]
1602 m = matches[rev][fn]
1603 for lnum, cstart, cend, line in matchlines(body):
1603 for lnum, cstart, cend, line in matchlines(body):
1604 s = linestate(line, lnum, cstart, cend)
1604 s = linestate(line, lnum, cstart, cend)
1605 m.append(s)
1605 m.append(s)
1606
1606
1607 def difflinestates(a, b):
1607 def difflinestates(a, b):
1608 sm = difflib.SequenceMatcher(None, a, b)
1608 sm = difflib.SequenceMatcher(None, a, b)
1609 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1609 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1610 if tag == 'insert':
1610 if tag == 'insert':
1611 for i in xrange(blo, bhi):
1611 for i in xrange(blo, bhi):
1612 yield ('+', b[i])
1612 yield ('+', b[i])
1613 elif tag == 'delete':
1613 elif tag == 'delete':
1614 for i in xrange(alo, ahi):
1614 for i in xrange(alo, ahi):
1615 yield ('-', a[i])
1615 yield ('-', a[i])
1616 elif tag == 'replace':
1616 elif tag == 'replace':
1617 for i in xrange(alo, ahi):
1617 for i in xrange(alo, ahi):
1618 yield ('-', a[i])
1618 yield ('-', a[i])
1619 for i in xrange(blo, bhi):
1619 for i in xrange(blo, bhi):
1620 yield ('+', b[i])
1620 yield ('+', b[i])
1621
1621
1622 def display(fn, ctx, pstates, states):
1622 def display(fn, ctx, pstates, states):
1623 rev = ctx.rev()
1623 rev = ctx.rev()
1624 datefunc = ui.quiet and util.shortdate or util.datestr
1624 datefunc = ui.quiet and util.shortdate or util.datestr
1625 found = False
1625 found = False
1626 filerevmatches = {}
1626 filerevmatches = {}
1627 if opts.get('all'):
1627 if opts.get('all'):
1628 iter = difflinestates(pstates, states)
1628 iter = difflinestates(pstates, states)
1629 else:
1629 else:
1630 iter = [('', l) for l in states]
1630 iter = [('', l) for l in states]
1631 for change, l in iter:
1631 for change, l in iter:
1632 cols = [fn, str(rev)]
1632 cols = [fn, str(rev)]
1633 before, match, after = None, None, None
1633 before, match, after = None, None, None
1634 if opts.get('line_number'):
1634 if opts.get('line_number'):
1635 cols.append(str(l.linenum))
1635 cols.append(str(l.linenum))
1636 if opts.get('all'):
1636 if opts.get('all'):
1637 cols.append(change)
1637 cols.append(change)
1638 if opts.get('user'):
1638 if opts.get('user'):
1639 cols.append(ui.shortuser(ctx.user()))
1639 cols.append(ui.shortuser(ctx.user()))
1640 if opts.get('date'):
1640 if opts.get('date'):
1641 cols.append(datefunc(ctx.date()))
1641 cols.append(datefunc(ctx.date()))
1642 if opts.get('files_with_matches'):
1642 if opts.get('files_with_matches'):
1643 c = (fn, rev)
1643 c = (fn, rev)
1644 if c in filerevmatches:
1644 if c in filerevmatches:
1645 continue
1645 continue
1646 filerevmatches[c] = 1
1646 filerevmatches[c] = 1
1647 else:
1647 else:
1648 before = l.line[:l.colstart]
1648 before = l.line[:l.colstart]
1649 match = l.line[l.colstart:l.colend]
1649 match = l.line[l.colstart:l.colend]
1650 after = l.line[l.colend:]
1650 after = l.line[l.colend:]
1651 ui.write(sep.join(cols))
1651 ui.write(sep.join(cols))
1652 if before is not None:
1652 if before is not None:
1653 ui.write(sep + before)
1653 ui.write(sep + before)
1654 ui.write(match, label='grep.match')
1654 ui.write(match, label='grep.match')
1655 ui.write(after)
1655 ui.write(after)
1656 ui.write(eol)
1656 ui.write(eol)
1657 found = True
1657 found = True
1658 return found
1658 return found
1659
1659
1660 skip = {}
1660 skip = {}
1661 revfiles = {}
1661 revfiles = {}
1662 matchfn = cmdutil.match(repo, pats, opts)
1662 matchfn = cmdutil.match(repo, pats, opts)
1663 found = False
1663 found = False
1664 follow = opts.get('follow')
1664 follow = opts.get('follow')
1665
1665
1666 def prep(ctx, fns):
1666 def prep(ctx, fns):
1667 rev = ctx.rev()
1667 rev = ctx.rev()
1668 pctx = ctx.parents()[0]
1668 pctx = ctx.parents()[0]
1669 parent = pctx.rev()
1669 parent = pctx.rev()
1670 matches.setdefault(rev, {})
1670 matches.setdefault(rev, {})
1671 matches.setdefault(parent, {})
1671 matches.setdefault(parent, {})
1672 files = revfiles.setdefault(rev, [])
1672 files = revfiles.setdefault(rev, [])
1673 for fn in fns:
1673 for fn in fns:
1674 flog = getfile(fn)
1674 flog = getfile(fn)
1675 try:
1675 try:
1676 fnode = ctx.filenode(fn)
1676 fnode = ctx.filenode(fn)
1677 except error.LookupError:
1677 except error.LookupError:
1678 continue
1678 continue
1679
1679
1680 copied = flog.renamed(fnode)
1680 copied = flog.renamed(fnode)
1681 copy = follow and copied and copied[0]
1681 copy = follow and copied and copied[0]
1682 if copy:
1682 if copy:
1683 copies.setdefault(rev, {})[fn] = copy
1683 copies.setdefault(rev, {})[fn] = copy
1684 if fn in skip:
1684 if fn in skip:
1685 if copy:
1685 if copy:
1686 skip[copy] = True
1686 skip[copy] = True
1687 continue
1687 continue
1688 files.append(fn)
1688 files.append(fn)
1689
1689
1690 if fn not in matches[rev]:
1690 if fn not in matches[rev]:
1691 grepbody(fn, rev, flog.read(fnode))
1691 grepbody(fn, rev, flog.read(fnode))
1692
1692
1693 pfn = copy or fn
1693 pfn = copy or fn
1694 if pfn not in matches[parent]:
1694 if pfn not in matches[parent]:
1695 try:
1695 try:
1696 fnode = pctx.filenode(pfn)
1696 fnode = pctx.filenode(pfn)
1697 grepbody(pfn, parent, flog.read(fnode))
1697 grepbody(pfn, parent, flog.read(fnode))
1698 except error.LookupError:
1698 except error.LookupError:
1699 pass
1699 pass
1700
1700
1701 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1701 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1702 rev = ctx.rev()
1702 rev = ctx.rev()
1703 parent = ctx.parents()[0].rev()
1703 parent = ctx.parents()[0].rev()
1704 for fn in sorted(revfiles.get(rev, [])):
1704 for fn in sorted(revfiles.get(rev, [])):
1705 states = matches[rev][fn]
1705 states = matches[rev][fn]
1706 copy = copies.get(rev, {}).get(fn)
1706 copy = copies.get(rev, {}).get(fn)
1707 if fn in skip:
1707 if fn in skip:
1708 if copy:
1708 if copy:
1709 skip[copy] = True
1709 skip[copy] = True
1710 continue
1710 continue
1711 pstates = matches.get(parent, {}).get(copy or fn, [])
1711 pstates = matches.get(parent, {}).get(copy or fn, [])
1712 if pstates or states:
1712 if pstates or states:
1713 r = display(fn, ctx, pstates, states)
1713 r = display(fn, ctx, pstates, states)
1714 found = found or r
1714 found = found or r
1715 if r and not opts.get('all'):
1715 if r and not opts.get('all'):
1716 skip[fn] = True
1716 skip[fn] = True
1717 if copy:
1717 if copy:
1718 skip[copy] = True
1718 skip[copy] = True
1719 del matches[rev]
1719 del matches[rev]
1720 del revfiles[rev]
1720 del revfiles[rev]
1721
1721
1722 return not found
1722 return not found
1723
1723
1724 def heads(ui, repo, *branchrevs, **opts):
1724 def heads(ui, repo, *branchrevs, **opts):
1725 """show current repository heads or show branch heads
1725 """show current repository heads or show branch heads
1726
1726
1727 With no arguments, show all repository branch heads.
1727 With no arguments, show all repository branch heads.
1728
1728
1729 Repository "heads" are changesets with no child changesets. They are
1729 Repository "heads" are changesets with no child changesets. They are
1730 where development generally takes place and are the usual targets
1730 where development generally takes place and are the usual targets
1731 for update and merge operations. Branch heads are changesets that have
1731 for update and merge operations. Branch heads are changesets that have
1732 no child changeset on the same branch.
1732 no child changeset on the same branch.
1733
1733
1734 If one or more REVs are given, only branch heads on the branches
1734 If one or more REVs are given, only branch heads on the branches
1735 associated with the specified changesets are shown.
1735 associated with the specified changesets are shown.
1736
1736
1737 If -c/--closed is specified, also show branch heads marked closed
1737 If -c/--closed is specified, also show branch heads marked closed
1738 (see :hg:`commit --close-branch`).
1738 (see :hg:`commit --close-branch`).
1739
1739
1740 If STARTREV is specified, only those heads that are descendants of
1740 If STARTREV is specified, only those heads that are descendants of
1741 STARTREV will be displayed.
1741 STARTREV will be displayed.
1742
1742
1743 If -t/--topo is specified, named branch mechanics will be ignored and only
1743 If -t/--topo is specified, named branch mechanics will be ignored and only
1744 changesets without children will be shown.
1744 changesets without children will be shown.
1745
1745
1746 Returns 0 if matching heads are found, 1 if not.
1746 Returns 0 if matching heads are found, 1 if not.
1747 """
1747 """
1748
1748
1749 if opts.get('rev'):
1749 if opts.get('rev'):
1750 start = repo.lookup(opts['rev'])
1750 start = repo.lookup(opts['rev'])
1751 else:
1751 else:
1752 start = None
1752 start = None
1753
1753
1754 if opts.get('topo'):
1754 if opts.get('topo'):
1755 heads = [repo[h] for h in repo.heads(start)]
1755 heads = [repo[h] for h in repo.heads(start)]
1756 else:
1756 else:
1757 heads = []
1757 heads = []
1758 for b, ls in repo.branchmap().iteritems():
1758 for b, ls in repo.branchmap().iteritems():
1759 if start is None:
1759 if start is None:
1760 heads += [repo[h] for h in ls]
1760 heads += [repo[h] for h in ls]
1761 continue
1761 continue
1762 startrev = repo.changelog.rev(start)
1762 startrev = repo.changelog.rev(start)
1763 descendants = set(repo.changelog.descendants(startrev))
1763 descendants = set(repo.changelog.descendants(startrev))
1764 descendants.add(startrev)
1764 descendants.add(startrev)
1765 rev = repo.changelog.rev
1765 rev = repo.changelog.rev
1766 heads += [repo[h] for h in ls if rev(h) in descendants]
1766 heads += [repo[h] for h in ls if rev(h) in descendants]
1767
1767
1768 if branchrevs:
1768 if branchrevs:
1769 decode, encode = encoding.fromlocal, encoding.tolocal
1769 decode, encode = encoding.fromlocal, encoding.tolocal
1770 branches = set(repo[decode(br)].branch() for br in branchrevs)
1770 branches = set(repo[decode(br)].branch() for br in branchrevs)
1771 heads = [h for h in heads if h.branch() in branches]
1771 heads = [h for h in heads if h.branch() in branches]
1772
1772
1773 if not opts.get('closed'):
1773 if not opts.get('closed'):
1774 heads = [h for h in heads if not h.extra().get('close')]
1774 heads = [h for h in heads if not h.extra().get('close')]
1775
1775
1776 if opts.get('active') and branchrevs:
1776 if opts.get('active') and branchrevs:
1777 dagheads = repo.heads(start)
1777 dagheads = repo.heads(start)
1778 heads = [h for h in heads if h.node() in dagheads]
1778 heads = [h for h in heads if h.node() in dagheads]
1779
1779
1780 if branchrevs:
1780 if branchrevs:
1781 haveheads = set(h.branch() for h in heads)
1781 haveheads = set(h.branch() for h in heads)
1782 if branches - haveheads:
1782 if branches - haveheads:
1783 headless = ', '.join(encode(b) for b in branches - haveheads)
1783 headless = ', '.join(encode(b) for b in branches - haveheads)
1784 msg = _('no open branch heads found on branches %s')
1784 msg = _('no open branch heads found on branches %s')
1785 if opts.get('rev'):
1785 if opts.get('rev'):
1786 msg += _(' (started at %s)' % opts['rev'])
1786 msg += _(' (started at %s)' % opts['rev'])
1787 ui.warn((msg + '\n') % headless)
1787 ui.warn((msg + '\n') % headless)
1788
1788
1789 if not heads:
1789 if not heads:
1790 return 1
1790 return 1
1791
1791
1792 heads = sorted(heads, key=lambda x: -x.rev())
1792 heads = sorted(heads, key=lambda x: -x.rev())
1793 displayer = cmdutil.show_changeset(ui, repo, opts)
1793 displayer = cmdutil.show_changeset(ui, repo, opts)
1794 for ctx in heads:
1794 for ctx in heads:
1795 displayer.show(ctx)
1795 displayer.show(ctx)
1796 displayer.close()
1796 displayer.close()
1797
1797
1798 def help_(ui, name=None, with_version=False, unknowncmd=False):
1798 def help_(ui, name=None, with_version=False, unknowncmd=False):
1799 """show help for a given topic or a help overview
1799 """show help for a given topic or a help overview
1800
1800
1801 With no arguments, print a list of commands with short help messages.
1801 With no arguments, print a list of commands with short help messages.
1802
1802
1803 Given a topic, extension, or command name, print help for that
1803 Given a topic, extension, or command name, print help for that
1804 topic.
1804 topic.
1805
1805
1806 Returns 0 if successful.
1806 Returns 0 if successful.
1807 """
1807 """
1808 option_lists = []
1808 option_lists = []
1809 textwidth = util.termwidth() - 2
1809 textwidth = util.termwidth() - 2
1810
1810
1811 def addglobalopts(aliases):
1811 def addglobalopts(aliases):
1812 if ui.verbose:
1812 if ui.verbose:
1813 option_lists.append((_("global options:"), globalopts))
1813 option_lists.append((_("global options:"), globalopts))
1814 if name == 'shortlist':
1814 if name == 'shortlist':
1815 option_lists.append((_('use "hg help" for the full list '
1815 option_lists.append((_('use "hg help" for the full list '
1816 'of commands'), ()))
1816 'of commands'), ()))
1817 else:
1817 else:
1818 if name == 'shortlist':
1818 if name == 'shortlist':
1819 msg = _('use "hg help" for the full list of commands '
1819 msg = _('use "hg help" for the full list of commands '
1820 'or "hg -v" for details')
1820 'or "hg -v" for details')
1821 elif aliases:
1821 elif aliases:
1822 msg = _('use "hg -v help%s" to show aliases and '
1822 msg = _('use "hg -v help%s" to show aliases and '
1823 'global options') % (name and " " + name or "")
1823 'global options') % (name and " " + name or "")
1824 else:
1824 else:
1825 msg = _('use "hg -v help %s" to show global options') % name
1825 msg = _('use "hg -v help %s" to show global options') % name
1826 option_lists.append((msg, ()))
1826 option_lists.append((msg, ()))
1827
1827
1828 def helpcmd(name):
1828 def helpcmd(name):
1829 if with_version:
1829 if with_version:
1830 version_(ui)
1830 version_(ui)
1831 ui.write('\n')
1831 ui.write('\n')
1832
1832
1833 try:
1833 try:
1834 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1834 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1835 except error.AmbiguousCommand, inst:
1835 except error.AmbiguousCommand, inst:
1836 # py3k fix: except vars can't be used outside the scope of the
1836 # py3k fix: except vars can't be used outside the scope of the
1837 # except block, nor can be used inside a lambda. python issue4617
1837 # except block, nor can be used inside a lambda. python issue4617
1838 prefix = inst.args[0]
1838 prefix = inst.args[0]
1839 select = lambda c: c.lstrip('^').startswith(prefix)
1839 select = lambda c: c.lstrip('^').startswith(prefix)
1840 helplist(_('list of commands:\n\n'), select)
1840 helplist(_('list of commands:\n\n'), select)
1841 return
1841 return
1842
1842
1843 # check if it's an invalid alias and display its error if it is
1843 # check if it's an invalid alias and display its error if it is
1844 if getattr(entry[0], 'badalias', False):
1844 if getattr(entry[0], 'badalias', False):
1845 if not unknowncmd:
1845 if not unknowncmd:
1846 entry[0](ui)
1846 entry[0](ui)
1847 return
1847 return
1848
1848
1849 # synopsis
1849 # synopsis
1850 if len(entry) > 2:
1850 if len(entry) > 2:
1851 if entry[2].startswith('hg'):
1851 if entry[2].startswith('hg'):
1852 ui.write("%s\n" % entry[2])
1852 ui.write("%s\n" % entry[2])
1853 else:
1853 else:
1854 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1854 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1855 else:
1855 else:
1856 ui.write('hg %s\n' % aliases[0])
1856 ui.write('hg %s\n' % aliases[0])
1857
1857
1858 # aliases
1858 # aliases
1859 if not ui.quiet and len(aliases) > 1:
1859 if not ui.quiet and len(aliases) > 1:
1860 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1860 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1861
1861
1862 # description
1862 # description
1863 doc = gettext(entry[0].__doc__)
1863 doc = gettext(entry[0].__doc__)
1864 if not doc:
1864 if not doc:
1865 doc = _("(no help text available)")
1865 doc = _("(no help text available)")
1866 if hasattr(entry[0], 'definition'): # aliased command
1866 if hasattr(entry[0], 'definition'): # aliased command
1867 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1867 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1868 if ui.quiet:
1868 if ui.quiet:
1869 doc = doc.splitlines()[0]
1869 doc = doc.splitlines()[0]
1870 keep = ui.verbose and ['verbose'] or []
1870 keep = ui.verbose and ['verbose'] or []
1871 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1871 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1872 ui.write("\n%s\n" % formatted)
1872 ui.write("\n%s\n" % formatted)
1873 if pruned:
1873 if pruned:
1874 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1874 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1875
1875
1876 if not ui.quiet:
1876 if not ui.quiet:
1877 # options
1877 # options
1878 if entry[1]:
1878 if entry[1]:
1879 option_lists.append((_("options:\n"), entry[1]))
1879 option_lists.append((_("options:\n"), entry[1]))
1880
1880
1881 addglobalopts(False)
1881 addglobalopts(False)
1882
1882
1883 def helplist(header, select=None):
1883 def helplist(header, select=None):
1884 h = {}
1884 h = {}
1885 cmds = {}
1885 cmds = {}
1886 for c, e in table.iteritems():
1886 for c, e in table.iteritems():
1887 f = c.split("|", 1)[0]
1887 f = c.split("|", 1)[0]
1888 if select and not select(f):
1888 if select and not select(f):
1889 continue
1889 continue
1890 if (not select and name != 'shortlist' and
1890 if (not select and name != 'shortlist' and
1891 e[0].__module__ != __name__):
1891 e[0].__module__ != __name__):
1892 continue
1892 continue
1893 if name == "shortlist" and not f.startswith("^"):
1893 if name == "shortlist" and not f.startswith("^"):
1894 continue
1894 continue
1895 f = f.lstrip("^")
1895 f = f.lstrip("^")
1896 if not ui.debugflag and f.startswith("debug"):
1896 if not ui.debugflag and f.startswith("debug"):
1897 continue
1897 continue
1898 doc = e[0].__doc__
1898 doc = e[0].__doc__
1899 if doc and 'DEPRECATED' in doc and not ui.verbose:
1899 if doc and 'DEPRECATED' in doc and not ui.verbose:
1900 continue
1900 continue
1901 doc = gettext(doc)
1901 doc = gettext(doc)
1902 if not doc:
1902 if not doc:
1903 doc = _("(no help text available)")
1903 doc = _("(no help text available)")
1904 h[f] = doc.splitlines()[0].rstrip()
1904 h[f] = doc.splitlines()[0].rstrip()
1905 cmds[f] = c.lstrip("^")
1905 cmds[f] = c.lstrip("^")
1906
1906
1907 if not h:
1907 if not h:
1908 ui.status(_('no commands defined\n'))
1908 ui.status(_('no commands defined\n'))
1909 return
1909 return
1910
1910
1911 ui.status(header)
1911 ui.status(header)
1912 fns = sorted(h)
1912 fns = sorted(h)
1913 m = max(map(len, fns))
1913 m = max(map(len, fns))
1914 for f in fns:
1914 for f in fns:
1915 if ui.verbose:
1915 if ui.verbose:
1916 commands = cmds[f].replace("|",", ")
1916 commands = cmds[f].replace("|",", ")
1917 ui.write(" %s:\n %s\n"%(commands, h[f]))
1917 ui.write(" %s:\n %s\n"%(commands, h[f]))
1918 else:
1918 else:
1919 ui.write('%s\n' % (util.wrap(h[f],
1919 ui.write('%s\n' % (util.wrap(h[f],
1920 initindent=' %-*s ' % (m, f),
1920 initindent=' %-*s ' % (m, f),
1921 hangindent=' ' * (m + 4))))
1921 hangindent=' ' * (m + 4))))
1922
1922
1923 if not ui.quiet:
1923 if not ui.quiet:
1924 addglobalopts(True)
1924 addglobalopts(True)
1925
1925
1926 def helptopic(name):
1926 def helptopic(name):
1927 for names, header, doc in help.helptable:
1927 for names, header, doc in help.helptable:
1928 if name in names:
1928 if name in names:
1929 break
1929 break
1930 else:
1930 else:
1931 raise error.UnknownCommand(name)
1931 raise error.UnknownCommand(name)
1932
1932
1933 # description
1933 # description
1934 if not doc:
1934 if not doc:
1935 doc = _("(no help text available)")
1935 doc = _("(no help text available)")
1936 if hasattr(doc, '__call__'):
1936 if hasattr(doc, '__call__'):
1937 doc = doc()
1937 doc = doc()
1938
1938
1939 ui.write("%s\n\n" % header)
1939 ui.write("%s\n\n" % header)
1940 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1940 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1941
1941
1942 def helpext(name):
1942 def helpext(name):
1943 try:
1943 try:
1944 mod = extensions.find(name)
1944 mod = extensions.find(name)
1945 doc = gettext(mod.__doc__) or _('no help text available')
1945 doc = gettext(mod.__doc__) or _('no help text available')
1946 except KeyError:
1946 except KeyError:
1947 mod = None
1947 mod = None
1948 doc = extensions.disabledext(name)
1948 doc = extensions.disabledext(name)
1949 if not doc:
1949 if not doc:
1950 raise error.UnknownCommand(name)
1950 raise error.UnknownCommand(name)
1951
1951
1952 if '\n' not in doc:
1952 if '\n' not in doc:
1953 head, tail = doc, ""
1953 head, tail = doc, ""
1954 else:
1954 else:
1955 head, tail = doc.split('\n', 1)
1955 head, tail = doc.split('\n', 1)
1956 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1956 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1957 if tail:
1957 if tail:
1958 ui.write(minirst.format(tail, textwidth))
1958 ui.write(minirst.format(tail, textwidth))
1959 ui.status('\n\n')
1959 ui.status('\n\n')
1960
1960
1961 if mod:
1961 if mod:
1962 try:
1962 try:
1963 ct = mod.cmdtable
1963 ct = mod.cmdtable
1964 except AttributeError:
1964 except AttributeError:
1965 ct = {}
1965 ct = {}
1966 modcmds = set([c.split('|', 1)[0] for c in ct])
1966 modcmds = set([c.split('|', 1)[0] for c in ct])
1967 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1967 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1968 else:
1968 else:
1969 ui.write(_('use "hg help extensions" for information on enabling '
1969 ui.write(_('use "hg help extensions" for information on enabling '
1970 'extensions\n'))
1970 'extensions\n'))
1971
1971
1972 def helpextcmd(name):
1972 def helpextcmd(name):
1973 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1973 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1974 doc = gettext(mod.__doc__).splitlines()[0]
1974 doc = gettext(mod.__doc__).splitlines()[0]
1975
1975
1976 msg = help.listexts(_("'%s' is provided by the following "
1976 msg = help.listexts(_("'%s' is provided by the following "
1977 "extension:") % cmd, {ext: doc}, len(ext),
1977 "extension:") % cmd, {ext: doc}, len(ext),
1978 indent=4)
1978 indent=4)
1979 ui.write(minirst.format(msg, textwidth))
1979 ui.write(minirst.format(msg, textwidth))
1980 ui.write('\n\n')
1980 ui.write('\n\n')
1981 ui.write(_('use "hg help extensions" for information on enabling '
1981 ui.write(_('use "hg help extensions" for information on enabling '
1982 'extensions\n'))
1982 'extensions\n'))
1983
1983
1984 if name and name != 'shortlist':
1984 if name and name != 'shortlist':
1985 i = None
1985 i = None
1986 if unknowncmd:
1986 if unknowncmd:
1987 queries = (helpextcmd,)
1987 queries = (helpextcmd,)
1988 else:
1988 else:
1989 queries = (helptopic, helpcmd, helpext, helpextcmd)
1989 queries = (helptopic, helpcmd, helpext, helpextcmd)
1990 for f in queries:
1990 for f in queries:
1991 try:
1991 try:
1992 f(name)
1992 f(name)
1993 i = None
1993 i = None
1994 break
1994 break
1995 except error.UnknownCommand, inst:
1995 except error.UnknownCommand, inst:
1996 i = inst
1996 i = inst
1997 if i:
1997 if i:
1998 raise i
1998 raise i
1999
1999
2000 else:
2000 else:
2001 # program name
2001 # program name
2002 if ui.verbose or with_version:
2002 if ui.verbose or with_version:
2003 version_(ui)
2003 version_(ui)
2004 else:
2004 else:
2005 ui.status(_("Mercurial Distributed SCM\n"))
2005 ui.status(_("Mercurial Distributed SCM\n"))
2006 ui.status('\n')
2006 ui.status('\n')
2007
2007
2008 # list of commands
2008 # list of commands
2009 if name == "shortlist":
2009 if name == "shortlist":
2010 header = _('basic commands:\n\n')
2010 header = _('basic commands:\n\n')
2011 else:
2011 else:
2012 header = _('list of commands:\n\n')
2012 header = _('list of commands:\n\n')
2013
2013
2014 helplist(header)
2014 helplist(header)
2015 if name != 'shortlist':
2015 if name != 'shortlist':
2016 exts, maxlength = extensions.enabled()
2016 exts, maxlength = extensions.enabled()
2017 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2017 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2018 if text:
2018 if text:
2019 ui.write("\n%s\n" % minirst.format(text, textwidth))
2019 ui.write("\n%s\n" % minirst.format(text, textwidth))
2020
2020
2021 # list all option lists
2021 # list all option lists
2022 opt_output = []
2022 opt_output = []
2023 multioccur = False
2023 multioccur = False
2024 for title, options in option_lists:
2024 for title, options in option_lists:
2025 opt_output.append(("\n%s" % title, None))
2025 opt_output.append(("\n%s" % title, None))
2026 for option in options:
2026 for option in options:
2027 if len(option) == 5:
2027 if len(option) == 5:
2028 shortopt, longopt, default, desc, optlabel = option
2028 shortopt, longopt, default, desc, optlabel = option
2029 else:
2029 else:
2030 shortopt, longopt, default, desc = option
2030 shortopt, longopt, default, desc = option
2031 optlabel = _("VALUE") # default label
2031 optlabel = _("VALUE") # default label
2032
2032
2033 if _("DEPRECATED") in desc and not ui.verbose:
2033 if _("DEPRECATED") in desc and not ui.verbose:
2034 continue
2034 continue
2035 if isinstance(default, list):
2035 if isinstance(default, list):
2036 numqualifier = " %s [+]" % optlabel
2036 numqualifier = " %s [+]" % optlabel
2037 multioccur = True
2037 multioccur = True
2038 elif (default is not None) and not isinstance(default, bool):
2038 elif (default is not None) and not isinstance(default, bool):
2039 numqualifier = " %s" % optlabel
2039 numqualifier = " %s" % optlabel
2040 else:
2040 else:
2041 numqualifier = ""
2041 numqualifier = ""
2042 opt_output.append(("%2s%s" %
2042 opt_output.append(("%2s%s" %
2043 (shortopt and "-%s" % shortopt,
2043 (shortopt and "-%s" % shortopt,
2044 longopt and " --%s%s" %
2044 longopt and " --%s%s" %
2045 (longopt, numqualifier)),
2045 (longopt, numqualifier)),
2046 "%s%s" % (desc,
2046 "%s%s" % (desc,
2047 default
2047 default
2048 and _(" (default: %s)") % default
2048 and _(" (default: %s)") % default
2049 or "")))
2049 or "")))
2050 if multioccur:
2050 if multioccur:
2051 msg = _("\n[+] marked option can be specified multiple times")
2051 msg = _("\n[+] marked option can be specified multiple times")
2052 if ui.verbose and name != 'shortlist':
2052 if ui.verbose and name != 'shortlist':
2053 opt_output.append((msg, ()))
2053 opt_output.append((msg, ()))
2054 else:
2054 else:
2055 opt_output.insert(-1, (msg, ()))
2055 opt_output.insert(-1, (msg, ()))
2056
2056
2057 if not name:
2057 if not name:
2058 ui.write(_("\nadditional help topics:\n\n"))
2058 ui.write(_("\nadditional help topics:\n\n"))
2059 topics = []
2059 topics = []
2060 for names, header, doc in help.helptable:
2060 for names, header, doc in help.helptable:
2061 topics.append((sorted(names, key=len, reverse=True)[0], header))
2061 topics.append((sorted(names, key=len, reverse=True)[0], header))
2062 topics_len = max([len(s[0]) for s in topics])
2062 topics_len = max([len(s[0]) for s in topics])
2063 for t, desc in topics:
2063 for t, desc in topics:
2064 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2064 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2065
2065
2066 if opt_output:
2066 if opt_output:
2067 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
2067 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
2068 for first, second in opt_output:
2068 for first, second in opt_output:
2069 if second:
2069 if second:
2070 initindent = ' %-*s ' % (opts_len, first)
2070 initindent = ' %-*s ' % (opts_len, first)
2071 hangindent = ' ' * (opts_len + 3)
2071 hangindent = ' ' * (opts_len + 3)
2072 ui.write('%s\n' % (util.wrap(second,
2072 ui.write('%s\n' % (util.wrap(second,
2073 initindent=initindent,
2073 initindent=initindent,
2074 hangindent=hangindent)))
2074 hangindent=hangindent)))
2075 else:
2075 else:
2076 ui.write("%s\n" % first)
2076 ui.write("%s\n" % first)
2077
2077
2078 def identify(ui, repo, source=None,
2078 def identify(ui, repo, source=None,
2079 rev=None, num=None, id=None, branch=None, tags=None):
2079 rev=None, num=None, id=None, branch=None, tags=None):
2080 """identify the working copy or specified revision
2080 """identify the working copy or specified revision
2081
2081
2082 With no revision, print a summary of the current state of the
2082 With no revision, print a summary of the current state of the
2083 repository.
2083 repository.
2084
2084
2085 Specifying a path to a repository root or Mercurial bundle will
2085 Specifying a path to a repository root or Mercurial bundle will
2086 cause lookup to operate on that repository/bundle.
2086 cause lookup to operate on that repository/bundle.
2087
2087
2088 This summary identifies the repository state using one or two
2088 This summary identifies the repository state using one or two
2089 parent hash identifiers, followed by a "+" if there are
2089 parent hash identifiers, followed by a "+" if there are
2090 uncommitted changes in the working directory, a list of tags for
2090 uncommitted changes in the working directory, a list of tags for
2091 this revision and a branch name for non-default branches.
2091 this revision and a branch name for non-default branches.
2092
2092
2093 Returns 0 if successful.
2093 Returns 0 if successful.
2094 """
2094 """
2095
2095
2096 if not repo and not source:
2096 if not repo and not source:
2097 raise util.Abort(_("There is no Mercurial repository here "
2097 raise util.Abort(_("There is no Mercurial repository here "
2098 "(.hg not found)"))
2098 "(.hg not found)"))
2099
2099
2100 hexfunc = ui.debugflag and hex or short
2100 hexfunc = ui.debugflag and hex or short
2101 default = not (num or id or branch or tags)
2101 default = not (num or id or branch or tags)
2102 output = []
2102 output = []
2103
2103
2104 revs = []
2104 revs = []
2105 if source:
2105 if source:
2106 source, branches = hg.parseurl(ui.expandpath(source))
2106 source, branches = hg.parseurl(ui.expandpath(source))
2107 repo = hg.repository(ui, source)
2107 repo = hg.repository(ui, source)
2108 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2108 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2109
2109
2110 if not repo.local():
2110 if not repo.local():
2111 if not rev and revs:
2111 if not rev and revs:
2112 rev = revs[0]
2112 rev = revs[0]
2113 if not rev:
2113 if not rev:
2114 rev = "tip"
2114 rev = "tip"
2115 if num or branch or tags:
2115 if num or branch or tags:
2116 raise util.Abort(
2116 raise util.Abort(
2117 "can't query remote revision number, branch, or tags")
2117 "can't query remote revision number, branch, or tags")
2118 output = [hexfunc(repo.lookup(rev))]
2118 output = [hexfunc(repo.lookup(rev))]
2119 elif not rev:
2119 elif not rev:
2120 ctx = repo[None]
2120 ctx = repo[None]
2121 parents = ctx.parents()
2121 parents = ctx.parents()
2122 changed = False
2122 changed = False
2123 if default or id or num:
2123 if default or id or num:
2124 changed = util.any(repo.status())
2124 changed = util.any(repo.status())
2125 if default or id:
2125 if default or id:
2126 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2126 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2127 (changed) and "+" or "")]
2127 (changed) and "+" or "")]
2128 if num:
2128 if num:
2129 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2129 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2130 (changed) and "+" or ""))
2130 (changed) and "+" or ""))
2131 else:
2131 else:
2132 ctx = repo[rev]
2132 ctx = repo[rev]
2133 if default or id:
2133 if default or id:
2134 output = [hexfunc(ctx.node())]
2134 output = [hexfunc(ctx.node())]
2135 if num:
2135 if num:
2136 output.append(str(ctx.rev()))
2136 output.append(str(ctx.rev()))
2137
2137
2138 if repo.local() and default and not ui.quiet:
2138 if repo.local() and default and not ui.quiet:
2139 b = encoding.tolocal(ctx.branch())
2139 b = encoding.tolocal(ctx.branch())
2140 if b != 'default':
2140 if b != 'default':
2141 output.append("(%s)" % b)
2141 output.append("(%s)" % b)
2142
2142
2143 # multiple tags for a single parent separated by '/'
2143 # multiple tags for a single parent separated by '/'
2144 t = "/".join(ctx.tags())
2144 t = "/".join(ctx.tags())
2145 if t:
2145 if t:
2146 output.append(t)
2146 output.append(t)
2147
2147
2148 if branch:
2148 if branch:
2149 output.append(encoding.tolocal(ctx.branch()))
2149 output.append(encoding.tolocal(ctx.branch()))
2150
2150
2151 if tags:
2151 if tags:
2152 output.extend(ctx.tags())
2152 output.extend(ctx.tags())
2153
2153
2154 ui.write("%s\n" % ' '.join(output))
2154 ui.write("%s\n" % ' '.join(output))
2155
2155
2156 def import_(ui, repo, patch1, *patches, **opts):
2156 def import_(ui, repo, patch1, *patches, **opts):
2157 """import an ordered set of patches
2157 """import an ordered set of patches
2158
2158
2159 Import a list of patches and commit them individually (unless
2159 Import a list of patches and commit them individually (unless
2160 --no-commit is specified).
2160 --no-commit is specified).
2161
2161
2162 If there are outstanding changes in the working directory, import
2162 If there are outstanding changes in the working directory, import
2163 will abort unless given the -f/--force flag.
2163 will abort unless given the -f/--force flag.
2164
2164
2165 You can import a patch straight from a mail message. Even patches
2165 You can import a patch straight from a mail message. Even patches
2166 as attachments work (to use the body part, it must have type
2166 as attachments work (to use the body part, it must have type
2167 text/plain or text/x-patch). From and Subject headers of email
2167 text/plain or text/x-patch). From and Subject headers of email
2168 message are used as default committer and commit message. All
2168 message are used as default committer and commit message. All
2169 text/plain body parts before first diff are added to commit
2169 text/plain body parts before first diff are added to commit
2170 message.
2170 message.
2171
2171
2172 If the imported patch was generated by :hg:`export`, user and
2172 If the imported patch was generated by :hg:`export`, user and
2173 description from patch override values from message headers and
2173 description from patch override values from message headers and
2174 body. Values given on command line with -m/--message and -u/--user
2174 body. Values given on command line with -m/--message and -u/--user
2175 override these.
2175 override these.
2176
2176
2177 If --exact is specified, import will set the working directory to
2177 If --exact is specified, import will set the working directory to
2178 the parent of each patch before applying it, and will abort if the
2178 the parent of each patch before applying it, and will abort if the
2179 resulting changeset has a different ID than the one recorded in
2179 resulting changeset has a different ID than the one recorded in
2180 the patch. This may happen due to character set problems or other
2180 the patch. This may happen due to character set problems or other
2181 deficiencies in the text patch format.
2181 deficiencies in the text patch format.
2182
2182
2183 With -s/--similarity, hg will attempt to discover renames and
2183 With -s/--similarity, hg will attempt to discover renames and
2184 copies in the patch in the same way as 'addremove'.
2184 copies in the patch in the same way as 'addremove'.
2185
2185
2186 To read a patch from standard input, use "-" as the patch name. If
2186 To read a patch from standard input, use "-" as the patch name. If
2187 a URL is specified, the patch will be downloaded from it.
2187 a URL is specified, the patch will be downloaded from it.
2188 See :hg:`help dates` for a list of formats valid for -d/--date.
2188 See :hg:`help dates` for a list of formats valid for -d/--date.
2189
2189
2190 Returns 0 on success.
2190 Returns 0 on success.
2191 """
2191 """
2192 patches = (patch1,) + patches
2192 patches = (patch1,) + patches
2193
2193
2194 date = opts.get('date')
2194 date = opts.get('date')
2195 if date:
2195 if date:
2196 opts['date'] = util.parsedate(date)
2196 opts['date'] = util.parsedate(date)
2197
2197
2198 try:
2198 try:
2199 sim = float(opts.get('similarity') or 0)
2199 sim = float(opts.get('similarity') or 0)
2200 except ValueError:
2200 except ValueError:
2201 raise util.Abort(_('similarity must be a number'))
2201 raise util.Abort(_('similarity must be a number'))
2202 if sim < 0 or sim > 100:
2202 if sim < 0 or sim > 100:
2203 raise util.Abort(_('similarity must be between 0 and 100'))
2203 raise util.Abort(_('similarity must be between 0 and 100'))
2204
2204
2205 if opts.get('exact') or not opts.get('force'):
2205 if opts.get('exact') or not opts.get('force'):
2206 cmdutil.bail_if_changed(repo)
2206 cmdutil.bail_if_changed(repo)
2207
2207
2208 d = opts["base"]
2208 d = opts["base"]
2209 strip = opts["strip"]
2209 strip = opts["strip"]
2210 wlock = lock = None
2210 wlock = lock = None
2211
2211
2212 def tryone(ui, hunk):
2212 def tryone(ui, hunk):
2213 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2213 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2214 patch.extract(ui, hunk)
2214 patch.extract(ui, hunk)
2215
2215
2216 if not tmpname:
2216 if not tmpname:
2217 return None
2217 return None
2218 commitid = _('to working directory')
2218 commitid = _('to working directory')
2219
2219
2220 try:
2220 try:
2221 cmdline_message = cmdutil.logmessage(opts)
2221 cmdline_message = cmdutil.logmessage(opts)
2222 if cmdline_message:
2222 if cmdline_message:
2223 # pickup the cmdline msg
2223 # pickup the cmdline msg
2224 message = cmdline_message
2224 message = cmdline_message
2225 elif message:
2225 elif message:
2226 # pickup the patch msg
2226 # pickup the patch msg
2227 message = message.strip()
2227 message = message.strip()
2228 else:
2228 else:
2229 # launch the editor
2229 # launch the editor
2230 message = None
2230 message = None
2231 ui.debug('message:\n%s\n' % message)
2231 ui.debug('message:\n%s\n' % message)
2232
2232
2233 wp = repo.parents()
2233 wp = repo.parents()
2234 if opts.get('exact'):
2234 if opts.get('exact'):
2235 if not nodeid or not p1:
2235 if not nodeid or not p1:
2236 raise util.Abort(_('not a Mercurial patch'))
2236 raise util.Abort(_('not a Mercurial patch'))
2237 p1 = repo.lookup(p1)
2237 p1 = repo.lookup(p1)
2238 p2 = repo.lookup(p2 or hex(nullid))
2238 p2 = repo.lookup(p2 or hex(nullid))
2239
2239
2240 if p1 != wp[0].node():
2240 if p1 != wp[0].node():
2241 hg.clean(repo, p1)
2241 hg.clean(repo, p1)
2242 repo.dirstate.setparents(p1, p2)
2242 repo.dirstate.setparents(p1, p2)
2243 elif p2:
2243 elif p2:
2244 try:
2244 try:
2245 p1 = repo.lookup(p1)
2245 p1 = repo.lookup(p1)
2246 p2 = repo.lookup(p2)
2246 p2 = repo.lookup(p2)
2247 if p1 == wp[0].node():
2247 if p1 == wp[0].node():
2248 repo.dirstate.setparents(p1, p2)
2248 repo.dirstate.setparents(p1, p2)
2249 except error.RepoError:
2249 except error.RepoError:
2250 pass
2250 pass
2251 if opts.get('exact') or opts.get('import_branch'):
2251 if opts.get('exact') or opts.get('import_branch'):
2252 repo.dirstate.setbranch(branch or 'default')
2252 repo.dirstate.setbranch(branch or 'default')
2253
2253
2254 files = {}
2254 files = {}
2255 try:
2255 try:
2256 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2256 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2257 files=files, eolmode=None)
2257 files=files, eolmode=None)
2258 finally:
2258 finally:
2259 files = patch.updatedir(ui, repo, files,
2259 files = patch.updatedir(ui, repo, files,
2260 similarity=sim / 100.0)
2260 similarity=sim / 100.0)
2261 if not opts.get('no_commit'):
2261 if not opts.get('no_commit'):
2262 if opts.get('exact'):
2262 if opts.get('exact'):
2263 m = None
2263 m = None
2264 else:
2264 else:
2265 m = cmdutil.matchfiles(repo, files or [])
2265 m = cmdutil.matchfiles(repo, files or [])
2266 n = repo.commit(message, opts.get('user') or user,
2266 n = repo.commit(message, opts.get('user') or user,
2267 opts.get('date') or date, match=m,
2267 opts.get('date') or date, match=m,
2268 editor=cmdutil.commiteditor)
2268 editor=cmdutil.commiteditor)
2269 if opts.get('exact'):
2269 if opts.get('exact'):
2270 if hex(n) != nodeid:
2270 if hex(n) != nodeid:
2271 repo.rollback()
2271 repo.rollback()
2272 raise util.Abort(_('patch is damaged'
2272 raise util.Abort(_('patch is damaged'
2273 ' or loses information'))
2273 ' or loses information'))
2274 # Force a dirstate write so that the next transaction
2274 # Force a dirstate write so that the next transaction
2275 # backups an up-do-date file.
2275 # backups an up-do-date file.
2276 repo.dirstate.write()
2276 repo.dirstate.write()
2277 if n:
2277 if n:
2278 commitid = short(n)
2278 commitid = short(n)
2279
2279
2280 return commitid
2280 return commitid
2281 finally:
2281 finally:
2282 os.unlink(tmpname)
2282 os.unlink(tmpname)
2283
2283
2284 try:
2284 try:
2285 wlock = repo.wlock()
2285 wlock = repo.wlock()
2286 lock = repo.lock()
2286 lock = repo.lock()
2287 lastcommit = None
2287 lastcommit = None
2288 for p in patches:
2288 for p in patches:
2289 pf = os.path.join(d, p)
2289 pf = os.path.join(d, p)
2290
2290
2291 if pf == '-':
2291 if pf == '-':
2292 ui.status(_("applying patch from stdin\n"))
2292 ui.status(_("applying patch from stdin\n"))
2293 pf = sys.stdin
2293 pf = sys.stdin
2294 else:
2294 else:
2295 ui.status(_("applying %s\n") % p)
2295 ui.status(_("applying %s\n") % p)
2296 pf = url.open(ui, pf)
2296 pf = url.open(ui, pf)
2297
2297
2298 haspatch = False
2298 haspatch = False
2299 for hunk in patch.split(pf):
2299 for hunk in patch.split(pf):
2300 commitid = tryone(ui, hunk)
2300 commitid = tryone(ui, hunk)
2301 if commitid:
2301 if commitid:
2302 haspatch = True
2302 haspatch = True
2303 if lastcommit:
2303 if lastcommit:
2304 ui.status(_('applied %s\n') % lastcommit)
2304 ui.status(_('applied %s\n') % lastcommit)
2305 lastcommit = commitid
2305 lastcommit = commitid
2306
2306
2307 if not haspatch:
2307 if not haspatch:
2308 raise util.Abort(_('no diffs found'))
2308 raise util.Abort(_('no diffs found'))
2309
2309
2310 finally:
2310 finally:
2311 release(lock, wlock)
2311 release(lock, wlock)
2312
2312
2313 def incoming(ui, repo, source="default", **opts):
2313 def incoming(ui, repo, source="default", **opts):
2314 """show new changesets found in source
2314 """show new changesets found in source
2315
2315
2316 Show new changesets found in the specified path/URL or the default
2316 Show new changesets found in the specified path/URL or the default
2317 pull location. These are the changesets that would have been pulled
2317 pull location. These are the changesets that would have been pulled
2318 if a pull at the time you issued this command.
2318 if a pull at the time you issued this command.
2319
2319
2320 For remote repository, using --bundle avoids downloading the
2320 For remote repository, using --bundle avoids downloading the
2321 changesets twice if the incoming is followed by a pull.
2321 changesets twice if the incoming is followed by a pull.
2322
2322
2323 See pull for valid source format details.
2323 See pull for valid source format details.
2324
2324
2325 Returns 0 if there are incoming changes, 1 otherwise.
2325 Returns 0 if there are incoming changes, 1 otherwise.
2326 """
2326 """
2327 limit = cmdutil.loglimit(opts)
2327 limit = cmdutil.loglimit(opts)
2328 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2328 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2329 other = hg.repository(hg.remoteui(repo, opts), source)
2329 other = hg.repository(hg.remoteui(repo, opts), source)
2330 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2330 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2331 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2331 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2332 if revs:
2332 if revs:
2333 revs = [other.lookup(rev) for rev in revs]
2333 revs = [other.lookup(rev) for rev in revs]
2334
2334
2335 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2335 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2336 force=opts.get('force'))
2336 force=opts.get('force'))
2337 common, incoming, rheads = tmp
2337 common, incoming, rheads = tmp
2338 if not incoming:
2338 if not incoming:
2339 try:
2339 try:
2340 os.unlink(opts["bundle"])
2340 os.unlink(opts["bundle"])
2341 except:
2341 except:
2342 pass
2342 pass
2343 ui.status(_("no changes found\n"))
2343 ui.status(_("no changes found\n"))
2344 return 1
2344 return 1
2345
2345
2346 cleanup = None
2346 cleanup = None
2347 try:
2347 try:
2348 fname = opts["bundle"]
2348 fname = opts["bundle"]
2349 if fname or not other.local():
2349 if fname or not other.local():
2350 # create a bundle (uncompressed if other repo is not local)
2350 # create a bundle (uncompressed if other repo is not local)
2351
2351
2352 if revs is None and other.capable('changegroupsubset'):
2352 if revs is None and other.capable('changegroupsubset'):
2353 revs = rheads
2353 revs = rheads
2354
2354
2355 if revs is None:
2355 if revs is None:
2356 cg = other.changegroup(incoming, "incoming")
2356 cg = other.changegroup(incoming, "incoming")
2357 else:
2357 else:
2358 cg = other.changegroupsubset(incoming, revs, 'incoming')
2358 cg = other.changegroupsubset(incoming, revs, 'incoming')
2359 bundletype = other.local() and "HG10BZ" or "HG10UN"
2359 bundletype = other.local() and "HG10BZ" or "HG10UN"
2360 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2360 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2361 # keep written bundle?
2361 # keep written bundle?
2362 if opts["bundle"]:
2362 if opts["bundle"]:
2363 cleanup = None
2363 cleanup = None
2364 if not other.local():
2364 if not other.local():
2365 # use the created uncompressed bundlerepo
2365 # use the created uncompressed bundlerepo
2366 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2366 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2367
2367
2368 o = other.changelog.nodesbetween(incoming, revs)[0]
2368 o = other.changelog.nodesbetween(incoming, revs)[0]
2369 if opts.get('newest_first'):
2369 if opts.get('newest_first'):
2370 o.reverse()
2370 o.reverse()
2371 displayer = cmdutil.show_changeset(ui, other, opts)
2371 displayer = cmdutil.show_changeset(ui, other, opts)
2372 count = 0
2372 count = 0
2373 for n in o:
2373 for n in o:
2374 if limit is not None and count >= limit:
2374 if limit is not None and count >= limit:
2375 break
2375 break
2376 parents = [p for p in other.changelog.parents(n) if p != nullid]
2376 parents = [p for p in other.changelog.parents(n) if p != nullid]
2377 if opts.get('no_merges') and len(parents) == 2:
2377 if opts.get('no_merges') and len(parents) == 2:
2378 continue
2378 continue
2379 count += 1
2379 count += 1
2380 displayer.show(other[n])
2380 displayer.show(other[n])
2381 displayer.close()
2381 displayer.close()
2382 finally:
2382 finally:
2383 if hasattr(other, 'close'):
2383 if hasattr(other, 'close'):
2384 other.close()
2384 other.close()
2385 if cleanup:
2385 if cleanup:
2386 os.unlink(cleanup)
2386 os.unlink(cleanup)
2387
2387
2388 def init(ui, dest=".", **opts):
2388 def init(ui, dest=".", **opts):
2389 """create a new repository in the given directory
2389 """create a new repository in the given directory
2390
2390
2391 Initialize a new repository in the given directory. If the given
2391 Initialize a new repository in the given directory. If the given
2392 directory does not exist, it will be created.
2392 directory does not exist, it will be created.
2393
2393
2394 If no directory is given, the current directory is used.
2394 If no directory is given, the current directory is used.
2395
2395
2396 It is possible to specify an ``ssh://`` URL as the destination.
2396 It is possible to specify an ``ssh://`` URL as the destination.
2397 See :hg:`help urls` for more information.
2397 See :hg:`help urls` for more information.
2398
2398
2399 Returns 0 on success.
2399 Returns 0 on success.
2400 """
2400 """
2401 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2401 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2402
2402
2403 def locate(ui, repo, *pats, **opts):
2403 def locate(ui, repo, *pats, **opts):
2404 """locate files matching specific patterns
2404 """locate files matching specific patterns
2405
2405
2406 Print files under Mercurial control in the working directory whose
2406 Print files under Mercurial control in the working directory whose
2407 names match the given patterns.
2407 names match the given patterns.
2408
2408
2409 By default, this command searches all directories in the working
2409 By default, this command searches all directories in the working
2410 directory. To search just the current directory and its
2410 directory. To search just the current directory and its
2411 subdirectories, use "--include .".
2411 subdirectories, use "--include .".
2412
2412
2413 If no patterns are given to match, this command prints the names
2413 If no patterns are given to match, this command prints the names
2414 of all files under Mercurial control in the working directory.
2414 of all files under Mercurial control in the working directory.
2415
2415
2416 If you want to feed the output of this command into the "xargs"
2416 If you want to feed the output of this command into the "xargs"
2417 command, use the -0 option to both this command and "xargs". This
2417 command, use the -0 option to both this command and "xargs". This
2418 will avoid the problem of "xargs" treating single filenames that
2418 will avoid the problem of "xargs" treating single filenames that
2419 contain whitespace as multiple filenames.
2419 contain whitespace as multiple filenames.
2420
2420
2421 Returns 0 if a match is found, 1 otherwise.
2421 Returns 0 if a match is found, 1 otherwise.
2422 """
2422 """
2423 end = opts.get('print0') and '\0' or '\n'
2423 end = opts.get('print0') and '\0' or '\n'
2424 rev = opts.get('rev') or None
2424 rev = opts.get('rev') or None
2425
2425
2426 ret = 1
2426 ret = 1
2427 m = cmdutil.match(repo, pats, opts, default='relglob')
2427 m = cmdutil.match(repo, pats, opts, default='relglob')
2428 m.bad = lambda x, y: False
2428 m.bad = lambda x, y: False
2429 for abs in repo[rev].walk(m):
2429 for abs in repo[rev].walk(m):
2430 if not rev and abs not in repo.dirstate:
2430 if not rev and abs not in repo.dirstate:
2431 continue
2431 continue
2432 if opts.get('fullpath'):
2432 if opts.get('fullpath'):
2433 ui.write(repo.wjoin(abs), end)
2433 ui.write(repo.wjoin(abs), end)
2434 else:
2434 else:
2435 ui.write(((pats and m.rel(abs)) or abs), end)
2435 ui.write(((pats and m.rel(abs)) or abs), end)
2436 ret = 0
2436 ret = 0
2437
2437
2438 return ret
2438 return ret
2439
2439
2440 def log(ui, repo, *pats, **opts):
2440 def log(ui, repo, *pats, **opts):
2441 """show revision history of entire repository or files
2441 """show revision history of entire repository or files
2442
2442
2443 Print the revision history of the specified files or the entire
2443 Print the revision history of the specified files or the entire
2444 project.
2444 project.
2445
2445
2446 File history is shown without following rename or copy history of
2446 File history is shown without following rename or copy history of
2447 files. Use -f/--follow with a filename to follow history across
2447 files. Use -f/--follow with a filename to follow history across
2448 renames and copies. --follow without a filename will only show
2448 renames and copies. --follow without a filename will only show
2449 ancestors or descendants of the starting revision. --follow-first
2449 ancestors or descendants of the starting revision. --follow-first
2450 only follows the first parent of merge revisions.
2450 only follows the first parent of merge revisions.
2451
2451
2452 If no revision range is specified, the default is tip:0 unless
2452 If no revision range is specified, the default is tip:0 unless
2453 --follow is set, in which case the working directory parent is
2453 --follow is set, in which case the working directory parent is
2454 used as the starting revision. You can specify a revision set for
2454 used as the starting revision. You can specify a revision set for
2455 log, see :hg:`help revsets` for more information.
2455 log, see :hg:`help revsets` for more information.
2456
2456
2457 See :hg:`help dates` for a list of formats valid for -d/--date.
2457 See :hg:`help dates` for a list of formats valid for -d/--date.
2458
2458
2459 By default this command prints revision number and changeset id,
2459 By default this command prints revision number and changeset id,
2460 tags, non-trivial parents, user, date and time, and a summary for
2460 tags, non-trivial parents, user, date and time, and a summary for
2461 each commit. When the -v/--verbose switch is used, the list of
2461 each commit. When the -v/--verbose switch is used, the list of
2462 changed files and full commit message are shown.
2462 changed files and full commit message are shown.
2463
2463
2464 NOTE: log -p/--patch may generate unexpected diff output for merge
2464 NOTE: log -p/--patch may generate unexpected diff output for merge
2465 changesets, as it will only compare the merge changeset against
2465 changesets, as it will only compare the merge changeset against
2466 its first parent. Also, only files different from BOTH parents
2466 its first parent. Also, only files different from BOTH parents
2467 will appear in files:.
2467 will appear in files:.
2468
2468
2469 Returns 0 on success.
2469 Returns 0 on success.
2470 """
2470 """
2471
2471
2472 matchfn = cmdutil.match(repo, pats, opts)
2472 matchfn = cmdutil.match(repo, pats, opts)
2473 limit = cmdutil.loglimit(opts)
2473 limit = cmdutil.loglimit(opts)
2474 count = 0
2474 count = 0
2475
2475
2476 endrev = None
2476 endrev = None
2477 if opts.get('copies') and opts.get('rev'):
2477 if opts.get('copies') and opts.get('rev'):
2478 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2478 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2479
2479
2480 df = False
2480 df = False
2481 if opts["date"]:
2481 if opts["date"]:
2482 df = util.matchdate(opts["date"])
2482 df = util.matchdate(opts["date"])
2483
2483
2484 branches = opts.get('branch', []) + opts.get('only_branch', [])
2484 branches = opts.get('branch', []) + opts.get('only_branch', [])
2485 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2485 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2486
2486
2487 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2487 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2488 def prep(ctx, fns):
2488 def prep(ctx, fns):
2489 rev = ctx.rev()
2489 rev = ctx.rev()
2490 parents = [p for p in repo.changelog.parentrevs(rev)
2490 parents = [p for p in repo.changelog.parentrevs(rev)
2491 if p != nullrev]
2491 if p != nullrev]
2492 if opts.get('no_merges') and len(parents) == 2:
2492 if opts.get('no_merges') and len(parents) == 2:
2493 return
2493 return
2494 if opts.get('only_merges') and len(parents) != 2:
2494 if opts.get('only_merges') and len(parents) != 2:
2495 return
2495 return
2496 if opts.get('branch') and ctx.branch() not in opts['branch']:
2496 if opts.get('branch') and ctx.branch() not in opts['branch']:
2497 return
2497 return
2498 if df and not df(ctx.date()[0]):
2498 if df and not df(ctx.date()[0]):
2499 return
2499 return
2500 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2500 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2501 return
2501 return
2502 if opts.get('keyword'):
2502 if opts.get('keyword'):
2503 for k in [kw.lower() for kw in opts['keyword']]:
2503 for k in [kw.lower() for kw in opts['keyword']]:
2504 if (k in ctx.user().lower() or
2504 if (k in ctx.user().lower() or
2505 k in ctx.description().lower() or
2505 k in ctx.description().lower() or
2506 k in " ".join(ctx.files()).lower()):
2506 k in " ".join(ctx.files()).lower()):
2507 break
2507 break
2508 else:
2508 else:
2509 return
2509 return
2510
2510
2511 copies = None
2511 copies = None
2512 if opts.get('copies') and rev:
2512 if opts.get('copies') and rev:
2513 copies = []
2513 copies = []
2514 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2514 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2515 for fn in ctx.files():
2515 for fn in ctx.files():
2516 rename = getrenamed(fn, rev)
2516 rename = getrenamed(fn, rev)
2517 if rename:
2517 if rename:
2518 copies.append((fn, rename[0]))
2518 copies.append((fn, rename[0]))
2519
2519
2520 displayer.show(ctx, copies=copies)
2520 revmatchfn = None
2521 if opts.get('patch') or opts.get('stat'):
2522 revmatchfn = cmdutil.match(repo, fns)
2523
2524 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2521
2525
2522 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2526 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2523 if count == limit:
2527 if count == limit:
2524 break
2528 break
2525 if displayer.flush(ctx.rev()):
2529 if displayer.flush(ctx.rev()):
2526 count += 1
2530 count += 1
2527 displayer.close()
2531 displayer.close()
2528
2532
2529 def manifest(ui, repo, node=None, rev=None):
2533 def manifest(ui, repo, node=None, rev=None):
2530 """output the current or given revision of the project manifest
2534 """output the current or given revision of the project manifest
2531
2535
2532 Print a list of version controlled files for the given revision.
2536 Print a list of version controlled files for the given revision.
2533 If no revision is given, the first parent of the working directory
2537 If no revision is given, the first parent of the working directory
2534 is used, or the null revision if no revision is checked out.
2538 is used, or the null revision if no revision is checked out.
2535
2539
2536 With -v, print file permissions, symlink and executable bits.
2540 With -v, print file permissions, symlink and executable bits.
2537 With --debug, print file revision hashes.
2541 With --debug, print file revision hashes.
2538
2542
2539 Returns 0 on success.
2543 Returns 0 on success.
2540 """
2544 """
2541
2545
2542 if rev and node:
2546 if rev and node:
2543 raise util.Abort(_("please specify just one revision"))
2547 raise util.Abort(_("please specify just one revision"))
2544
2548
2545 if not node:
2549 if not node:
2546 node = rev
2550 node = rev
2547
2551
2548 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2552 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2549 ctx = repo[node]
2553 ctx = repo[node]
2550 for f in ctx:
2554 for f in ctx:
2551 if ui.debugflag:
2555 if ui.debugflag:
2552 ui.write("%40s " % hex(ctx.manifest()[f]))
2556 ui.write("%40s " % hex(ctx.manifest()[f]))
2553 if ui.verbose:
2557 if ui.verbose:
2554 ui.write(decor[ctx.flags(f)])
2558 ui.write(decor[ctx.flags(f)])
2555 ui.write("%s\n" % f)
2559 ui.write("%s\n" % f)
2556
2560
2557 def merge(ui, repo, node=None, **opts):
2561 def merge(ui, repo, node=None, **opts):
2558 """merge working directory with another revision
2562 """merge working directory with another revision
2559
2563
2560 The current working directory is updated with all changes made in
2564 The current working directory is updated with all changes made in
2561 the requested revision since the last common predecessor revision.
2565 the requested revision since the last common predecessor revision.
2562
2566
2563 Files that changed between either parent are marked as changed for
2567 Files that changed between either parent are marked as changed for
2564 the next commit and a commit must be performed before any further
2568 the next commit and a commit must be performed before any further
2565 updates to the repository are allowed. The next commit will have
2569 updates to the repository are allowed. The next commit will have
2566 two parents.
2570 two parents.
2567
2571
2568 If no revision is specified, the working directory's parent is a
2572 If no revision is specified, the working directory's parent is a
2569 head revision, and the current branch contains exactly one other
2573 head revision, and the current branch contains exactly one other
2570 head, the other head is merged with by default. Otherwise, an
2574 head, the other head is merged with by default. Otherwise, an
2571 explicit revision with which to merge with must be provided.
2575 explicit revision with which to merge with must be provided.
2572
2576
2573 To undo an uncommitted merge, use :hg:`update --clean .` which
2577 To undo an uncommitted merge, use :hg:`update --clean .` which
2574 will check out a clean copy of the original merge parent, losing
2578 will check out a clean copy of the original merge parent, losing
2575 all changes.
2579 all changes.
2576
2580
2577 Returns 0 on success, 1 if there are unresolved files.
2581 Returns 0 on success, 1 if there are unresolved files.
2578 """
2582 """
2579
2583
2580 if opts.get('rev') and node:
2584 if opts.get('rev') and node:
2581 raise util.Abort(_("please specify just one revision"))
2585 raise util.Abort(_("please specify just one revision"))
2582 if not node:
2586 if not node:
2583 node = opts.get('rev')
2587 node = opts.get('rev')
2584
2588
2585 if not node:
2589 if not node:
2586 branch = repo.changectx(None).branch()
2590 branch = repo.changectx(None).branch()
2587 bheads = repo.branchheads(branch)
2591 bheads = repo.branchheads(branch)
2588 if len(bheads) > 2:
2592 if len(bheads) > 2:
2589 raise util.Abort(_(
2593 raise util.Abort(_(
2590 'branch \'%s\' has %d heads - '
2594 'branch \'%s\' has %d heads - '
2591 'please merge with an explicit rev\n'
2595 'please merge with an explicit rev\n'
2592 '(run \'hg heads .\' to see heads)')
2596 '(run \'hg heads .\' to see heads)')
2593 % (branch, len(bheads)))
2597 % (branch, len(bheads)))
2594
2598
2595 parent = repo.dirstate.parents()[0]
2599 parent = repo.dirstate.parents()[0]
2596 if len(bheads) == 1:
2600 if len(bheads) == 1:
2597 if len(repo.heads()) > 1:
2601 if len(repo.heads()) > 1:
2598 raise util.Abort(_(
2602 raise util.Abort(_(
2599 'branch \'%s\' has one head - '
2603 'branch \'%s\' has one head - '
2600 'please merge with an explicit rev\n'
2604 'please merge with an explicit rev\n'
2601 '(run \'hg heads\' to see all heads)')
2605 '(run \'hg heads\' to see all heads)')
2602 % branch)
2606 % branch)
2603 msg = _('there is nothing to merge')
2607 msg = _('there is nothing to merge')
2604 if parent != repo.lookup(repo[None].branch()):
2608 if parent != repo.lookup(repo[None].branch()):
2605 msg = _('%s - use "hg update" instead') % msg
2609 msg = _('%s - use "hg update" instead') % msg
2606 raise util.Abort(msg)
2610 raise util.Abort(msg)
2607
2611
2608 if parent not in bheads:
2612 if parent not in bheads:
2609 raise util.Abort(_('working dir not at a head rev - '
2613 raise util.Abort(_('working dir not at a head rev - '
2610 'use "hg update" or merge with an explicit rev'))
2614 'use "hg update" or merge with an explicit rev'))
2611 node = parent == bheads[0] and bheads[-1] or bheads[0]
2615 node = parent == bheads[0] and bheads[-1] or bheads[0]
2612
2616
2613 if opts.get('preview'):
2617 if opts.get('preview'):
2614 # find nodes that are ancestors of p2 but not of p1
2618 # find nodes that are ancestors of p2 but not of p1
2615 p1 = repo.lookup('.')
2619 p1 = repo.lookup('.')
2616 p2 = repo.lookup(node)
2620 p2 = repo.lookup(node)
2617 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2621 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2618
2622
2619 displayer = cmdutil.show_changeset(ui, repo, opts)
2623 displayer = cmdutil.show_changeset(ui, repo, opts)
2620 for node in nodes:
2624 for node in nodes:
2621 displayer.show(repo[node])
2625 displayer.show(repo[node])
2622 displayer.close()
2626 displayer.close()
2623 return 0
2627 return 0
2624
2628
2625 return hg.merge(repo, node, force=opts.get('force'))
2629 return hg.merge(repo, node, force=opts.get('force'))
2626
2630
2627 def outgoing(ui, repo, dest=None, **opts):
2631 def outgoing(ui, repo, dest=None, **opts):
2628 """show changesets not found in the destination
2632 """show changesets not found in the destination
2629
2633
2630 Show changesets not found in the specified destination repository
2634 Show changesets not found in the specified destination repository
2631 or the default push location. These are the changesets that would
2635 or the default push location. These are the changesets that would
2632 be pushed if a push was requested.
2636 be pushed if a push was requested.
2633
2637
2634 See pull for details of valid destination formats.
2638 See pull for details of valid destination formats.
2635
2639
2636 Returns 0 if there are outgoing changes, 1 otherwise.
2640 Returns 0 if there are outgoing changes, 1 otherwise.
2637 """
2641 """
2638 limit = cmdutil.loglimit(opts)
2642 limit = cmdutil.loglimit(opts)
2639 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2643 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2640 dest, branches = hg.parseurl(dest, opts.get('branch'))
2644 dest, branches = hg.parseurl(dest, opts.get('branch'))
2641 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2645 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2642 if revs:
2646 if revs:
2643 revs = [repo.lookup(rev) for rev in revs]
2647 revs = [repo.lookup(rev) for rev in revs]
2644
2648
2645 other = hg.repository(hg.remoteui(repo, opts), dest)
2649 other = hg.repository(hg.remoteui(repo, opts), dest)
2646 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2650 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2647 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2651 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2648 if not o:
2652 if not o:
2649 ui.status(_("no changes found\n"))
2653 ui.status(_("no changes found\n"))
2650 return 1
2654 return 1
2651 o = repo.changelog.nodesbetween(o, revs)[0]
2655 o = repo.changelog.nodesbetween(o, revs)[0]
2652 if opts.get('newest_first'):
2656 if opts.get('newest_first'):
2653 o.reverse()
2657 o.reverse()
2654 displayer = cmdutil.show_changeset(ui, repo, opts)
2658 displayer = cmdutil.show_changeset(ui, repo, opts)
2655 count = 0
2659 count = 0
2656 for n in o:
2660 for n in o:
2657 if limit is not None and count >= limit:
2661 if limit is not None and count >= limit:
2658 break
2662 break
2659 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2663 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2660 if opts.get('no_merges') and len(parents) == 2:
2664 if opts.get('no_merges') and len(parents) == 2:
2661 continue
2665 continue
2662 count += 1
2666 count += 1
2663 displayer.show(repo[n])
2667 displayer.show(repo[n])
2664 displayer.close()
2668 displayer.close()
2665
2669
2666 def parents(ui, repo, file_=None, **opts):
2670 def parents(ui, repo, file_=None, **opts):
2667 """show the parents of the working directory or revision
2671 """show the parents of the working directory or revision
2668
2672
2669 Print the working directory's parent revisions. If a revision is
2673 Print the working directory's parent revisions. If a revision is
2670 given via -r/--rev, the parent of that revision will be printed.
2674 given via -r/--rev, the parent of that revision will be printed.
2671 If a file argument is given, the revision in which the file was
2675 If a file argument is given, the revision in which the file was
2672 last changed (before the working directory revision or the
2676 last changed (before the working directory revision or the
2673 argument to --rev if given) is printed.
2677 argument to --rev if given) is printed.
2674
2678
2675 Returns 0 on success.
2679 Returns 0 on success.
2676 """
2680 """
2677 rev = opts.get('rev')
2681 rev = opts.get('rev')
2678 if rev:
2682 if rev:
2679 ctx = repo[rev]
2683 ctx = repo[rev]
2680 else:
2684 else:
2681 ctx = repo[None]
2685 ctx = repo[None]
2682
2686
2683 if file_:
2687 if file_:
2684 m = cmdutil.match(repo, (file_,), opts)
2688 m = cmdutil.match(repo, (file_,), opts)
2685 if m.anypats() or len(m.files()) != 1:
2689 if m.anypats() or len(m.files()) != 1:
2686 raise util.Abort(_('can only specify an explicit filename'))
2690 raise util.Abort(_('can only specify an explicit filename'))
2687 file_ = m.files()[0]
2691 file_ = m.files()[0]
2688 filenodes = []
2692 filenodes = []
2689 for cp in ctx.parents():
2693 for cp in ctx.parents():
2690 if not cp:
2694 if not cp:
2691 continue
2695 continue
2692 try:
2696 try:
2693 filenodes.append(cp.filenode(file_))
2697 filenodes.append(cp.filenode(file_))
2694 except error.LookupError:
2698 except error.LookupError:
2695 pass
2699 pass
2696 if not filenodes:
2700 if not filenodes:
2697 raise util.Abort(_("'%s' not found in manifest!") % file_)
2701 raise util.Abort(_("'%s' not found in manifest!") % file_)
2698 fl = repo.file(file_)
2702 fl = repo.file(file_)
2699 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2703 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2700 else:
2704 else:
2701 p = [cp.node() for cp in ctx.parents()]
2705 p = [cp.node() for cp in ctx.parents()]
2702
2706
2703 displayer = cmdutil.show_changeset(ui, repo, opts)
2707 displayer = cmdutil.show_changeset(ui, repo, opts)
2704 for n in p:
2708 for n in p:
2705 if n != nullid:
2709 if n != nullid:
2706 displayer.show(repo[n])
2710 displayer.show(repo[n])
2707 displayer.close()
2711 displayer.close()
2708
2712
2709 def paths(ui, repo, search=None):
2713 def paths(ui, repo, search=None):
2710 """show aliases for remote repositories
2714 """show aliases for remote repositories
2711
2715
2712 Show definition of symbolic path name NAME. If no name is given,
2716 Show definition of symbolic path name NAME. If no name is given,
2713 show definition of all available names.
2717 show definition of all available names.
2714
2718
2715 Path names are defined in the [paths] section of
2719 Path names are defined in the [paths] section of
2716 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2720 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2717 repository, ``.hg/hgrc`` is used, too.
2721 repository, ``.hg/hgrc`` is used, too.
2718
2722
2719 The path names ``default`` and ``default-push`` have a special
2723 The path names ``default`` and ``default-push`` have a special
2720 meaning. When performing a push or pull operation, they are used
2724 meaning. When performing a push or pull operation, they are used
2721 as fallbacks if no location is specified on the command-line.
2725 as fallbacks if no location is specified on the command-line.
2722 When ``default-push`` is set, it will be used for push and
2726 When ``default-push`` is set, it will be used for push and
2723 ``default`` will be used for pull; otherwise ``default`` is used
2727 ``default`` will be used for pull; otherwise ``default`` is used
2724 as the fallback for both. When cloning a repository, the clone
2728 as the fallback for both. When cloning a repository, the clone
2725 source is written as ``default`` in ``.hg/hgrc``. Note that
2729 source is written as ``default`` in ``.hg/hgrc``. Note that
2726 ``default`` and ``default-push`` apply to all inbound (e.g.
2730 ``default`` and ``default-push`` apply to all inbound (e.g.
2727 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2731 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2728 :hg:`bundle`) operations.
2732 :hg:`bundle`) operations.
2729
2733
2730 See :hg:`help urls` for more information.
2734 See :hg:`help urls` for more information.
2731 """
2735 """
2732 if search:
2736 if search:
2733 for name, path in ui.configitems("paths"):
2737 for name, path in ui.configitems("paths"):
2734 if name == search:
2738 if name == search:
2735 ui.write("%s\n" % url.hidepassword(path))
2739 ui.write("%s\n" % url.hidepassword(path))
2736 return
2740 return
2737 ui.warn(_("not found!\n"))
2741 ui.warn(_("not found!\n"))
2738 return 1
2742 return 1
2739 else:
2743 else:
2740 for name, path in ui.configitems("paths"):
2744 for name, path in ui.configitems("paths"):
2741 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2745 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2742
2746
2743 def postincoming(ui, repo, modheads, optupdate, checkout):
2747 def postincoming(ui, repo, modheads, optupdate, checkout):
2744 if modheads == 0:
2748 if modheads == 0:
2745 return
2749 return
2746 if optupdate:
2750 if optupdate:
2747 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2751 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2748 return hg.update(repo, checkout)
2752 return hg.update(repo, checkout)
2749 else:
2753 else:
2750 ui.status(_("not updating, since new heads added\n"))
2754 ui.status(_("not updating, since new heads added\n"))
2751 if modheads > 1:
2755 if modheads > 1:
2752 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2756 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2753 else:
2757 else:
2754 ui.status(_("(run 'hg update' to get a working copy)\n"))
2758 ui.status(_("(run 'hg update' to get a working copy)\n"))
2755
2759
2756 def pull(ui, repo, source="default", **opts):
2760 def pull(ui, repo, source="default", **opts):
2757 """pull changes from the specified source
2761 """pull changes from the specified source
2758
2762
2759 Pull changes from a remote repository to a local one.
2763 Pull changes from a remote repository to a local one.
2760
2764
2761 This finds all changes from the repository at the specified path
2765 This finds all changes from the repository at the specified path
2762 or URL and adds them to a local repository (the current one unless
2766 or URL and adds them to a local repository (the current one unless
2763 -R is specified). By default, this does not update the copy of the
2767 -R is specified). By default, this does not update the copy of the
2764 project in the working directory.
2768 project in the working directory.
2765
2769
2766 Use :hg:`incoming` if you want to see what would have been added
2770 Use :hg:`incoming` if you want to see what would have been added
2767 by a pull at the time you issued this command. If you then decide
2771 by a pull at the time you issued this command. If you then decide
2768 to add those changes to the repository, you should use :hg:`pull
2772 to add those changes to the repository, you should use :hg:`pull
2769 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2773 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2770
2774
2771 If SOURCE is omitted, the 'default' path will be used.
2775 If SOURCE is omitted, the 'default' path will be used.
2772 See :hg:`help urls` for more information.
2776 See :hg:`help urls` for more information.
2773
2777
2774 Returns 0 on success, 1 if an update had unresolved files.
2778 Returns 0 on success, 1 if an update had unresolved files.
2775 """
2779 """
2776 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2780 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2777 other = hg.repository(hg.remoteui(repo, opts), source)
2781 other = hg.repository(hg.remoteui(repo, opts), source)
2778 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2782 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2779 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2783 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2780 if revs:
2784 if revs:
2781 try:
2785 try:
2782 revs = [other.lookup(rev) for rev in revs]
2786 revs = [other.lookup(rev) for rev in revs]
2783 except error.CapabilityError:
2787 except error.CapabilityError:
2784 err = _("Other repository doesn't support revision lookup, "
2788 err = _("Other repository doesn't support revision lookup, "
2785 "so a rev cannot be specified.")
2789 "so a rev cannot be specified.")
2786 raise util.Abort(err)
2790 raise util.Abort(err)
2787
2791
2788 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2792 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2789 if checkout:
2793 if checkout:
2790 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2794 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2791 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2795 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2792
2796
2793 def push(ui, repo, dest=None, **opts):
2797 def push(ui, repo, dest=None, **opts):
2794 """push changes to the specified destination
2798 """push changes to the specified destination
2795
2799
2796 Push changesets from the local repository to the specified
2800 Push changesets from the local repository to the specified
2797 destination.
2801 destination.
2798
2802
2799 This operation is symmetrical to pull: it is identical to a pull
2803 This operation is symmetrical to pull: it is identical to a pull
2800 in the destination repository from the current one.
2804 in the destination repository from the current one.
2801
2805
2802 By default, push will not allow creation of new heads at the
2806 By default, push will not allow creation of new heads at the
2803 destination, since multiple heads would make it unclear which head
2807 destination, since multiple heads would make it unclear which head
2804 to use. In this situation, it is recommended to pull and merge
2808 to use. In this situation, it is recommended to pull and merge
2805 before pushing.
2809 before pushing.
2806
2810
2807 Use --new-branch if you want to allow push to create a new named
2811 Use --new-branch if you want to allow push to create a new named
2808 branch that is not present at the destination. This allows you to
2812 branch that is not present at the destination. This allows you to
2809 only create a new branch without forcing other changes.
2813 only create a new branch without forcing other changes.
2810
2814
2811 Use -f/--force to override the default behavior and push all
2815 Use -f/--force to override the default behavior and push all
2812 changesets on all branches.
2816 changesets on all branches.
2813
2817
2814 If -r/--rev is used, the specified revision and all its ancestors
2818 If -r/--rev is used, the specified revision and all its ancestors
2815 will be pushed to the remote repository.
2819 will be pushed to the remote repository.
2816
2820
2817 Please see :hg:`help urls` for important details about ``ssh://``
2821 Please see :hg:`help urls` for important details about ``ssh://``
2818 URLs. If DESTINATION is omitted, a default path will be used.
2822 URLs. If DESTINATION is omitted, a default path will be used.
2819
2823
2820 Returns 0 if push was successful, 1 if nothing to push.
2824 Returns 0 if push was successful, 1 if nothing to push.
2821 """
2825 """
2822 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2826 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2823 dest, branches = hg.parseurl(dest, opts.get('branch'))
2827 dest, branches = hg.parseurl(dest, opts.get('branch'))
2824 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2828 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2825 other = hg.repository(hg.remoteui(repo, opts), dest)
2829 other = hg.repository(hg.remoteui(repo, opts), dest)
2826 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2830 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2827 if revs:
2831 if revs:
2828 revs = [repo.lookup(rev) for rev in revs]
2832 revs = [repo.lookup(rev) for rev in revs]
2829
2833
2830 # push subrepos depth-first for coherent ordering
2834 # push subrepos depth-first for coherent ordering
2831 c = repo['']
2835 c = repo['']
2832 subs = c.substate # only repos that are committed
2836 subs = c.substate # only repos that are committed
2833 for s in sorted(subs):
2837 for s in sorted(subs):
2834 if not c.sub(s).push(opts.get('force')):
2838 if not c.sub(s).push(opts.get('force')):
2835 return False
2839 return False
2836
2840
2837 r = repo.push(other, opts.get('force'), revs=revs,
2841 r = repo.push(other, opts.get('force'), revs=revs,
2838 newbranch=opts.get('new_branch'))
2842 newbranch=opts.get('new_branch'))
2839 return r == 0
2843 return r == 0
2840
2844
2841 def recover(ui, repo):
2845 def recover(ui, repo):
2842 """roll back an interrupted transaction
2846 """roll back an interrupted transaction
2843
2847
2844 Recover from an interrupted commit or pull.
2848 Recover from an interrupted commit or pull.
2845
2849
2846 This command tries to fix the repository status after an
2850 This command tries to fix the repository status after an
2847 interrupted operation. It should only be necessary when Mercurial
2851 interrupted operation. It should only be necessary when Mercurial
2848 suggests it.
2852 suggests it.
2849
2853
2850 Returns 0 if successful, 1 if nothing to recover or verify fails.
2854 Returns 0 if successful, 1 if nothing to recover or verify fails.
2851 """
2855 """
2852 if repo.recover():
2856 if repo.recover():
2853 return hg.verify(repo)
2857 return hg.verify(repo)
2854 return 1
2858 return 1
2855
2859
2856 def remove(ui, repo, *pats, **opts):
2860 def remove(ui, repo, *pats, **opts):
2857 """remove the specified files on the next commit
2861 """remove the specified files on the next commit
2858
2862
2859 Schedule the indicated files for removal from the repository.
2863 Schedule the indicated files for removal from the repository.
2860
2864
2861 This only removes files from the current branch, not from the
2865 This only removes files from the current branch, not from the
2862 entire project history. -A/--after can be used to remove only
2866 entire project history. -A/--after can be used to remove only
2863 files that have already been deleted, -f/--force can be used to
2867 files that have already been deleted, -f/--force can be used to
2864 force deletion, and -Af can be used to remove files from the next
2868 force deletion, and -Af can be used to remove files from the next
2865 revision without deleting them from the working directory.
2869 revision without deleting them from the working directory.
2866
2870
2867 The following table details the behavior of remove for different
2871 The following table details the behavior of remove for different
2868 file states (columns) and option combinations (rows). The file
2872 file states (columns) and option combinations (rows). The file
2869 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2873 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2870 reported by :hg:`status`). The actions are Warn, Remove (from
2874 reported by :hg:`status`). The actions are Warn, Remove (from
2871 branch) and Delete (from disk)::
2875 branch) and Delete (from disk)::
2872
2876
2873 A C M !
2877 A C M !
2874 none W RD W R
2878 none W RD W R
2875 -f R RD RD R
2879 -f R RD RD R
2876 -A W W W R
2880 -A W W W R
2877 -Af R R R R
2881 -Af R R R R
2878
2882
2879 This command schedules the files to be removed at the next commit.
2883 This command schedules the files to be removed at the next commit.
2880 To undo a remove before that, see :hg:`revert`.
2884 To undo a remove before that, see :hg:`revert`.
2881
2885
2882 Returns 0 on success, 1 if any warnings encountered.
2886 Returns 0 on success, 1 if any warnings encountered.
2883 """
2887 """
2884
2888
2885 ret = 0
2889 ret = 0
2886 after, force = opts.get('after'), opts.get('force')
2890 after, force = opts.get('after'), opts.get('force')
2887 if not pats and not after:
2891 if not pats and not after:
2888 raise util.Abort(_('no files specified'))
2892 raise util.Abort(_('no files specified'))
2889
2893
2890 m = cmdutil.match(repo, pats, opts)
2894 m = cmdutil.match(repo, pats, opts)
2891 s = repo.status(match=m, clean=True)
2895 s = repo.status(match=m, clean=True)
2892 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2896 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2893
2897
2894 for f in m.files():
2898 for f in m.files():
2895 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2899 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2896 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2900 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2897 ret = 1
2901 ret = 1
2898
2902
2899 def warn(files, reason):
2903 def warn(files, reason):
2900 for f in files:
2904 for f in files:
2901 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2905 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2902 % (m.rel(f), reason))
2906 % (m.rel(f), reason))
2903 ret = 1
2907 ret = 1
2904
2908
2905 if force:
2909 if force:
2906 remove, forget = modified + deleted + clean, added
2910 remove, forget = modified + deleted + clean, added
2907 elif after:
2911 elif after:
2908 remove, forget = deleted, []
2912 remove, forget = deleted, []
2909 warn(modified + added + clean, _('still exists'))
2913 warn(modified + added + clean, _('still exists'))
2910 else:
2914 else:
2911 remove, forget = deleted + clean, []
2915 remove, forget = deleted + clean, []
2912 warn(modified, _('is modified'))
2916 warn(modified, _('is modified'))
2913 warn(added, _('has been marked for add'))
2917 warn(added, _('has been marked for add'))
2914
2918
2915 for f in sorted(remove + forget):
2919 for f in sorted(remove + forget):
2916 if ui.verbose or not m.exact(f):
2920 if ui.verbose or not m.exact(f):
2917 ui.status(_('removing %s\n') % m.rel(f))
2921 ui.status(_('removing %s\n') % m.rel(f))
2918
2922
2919 repo[None].forget(forget)
2923 repo[None].forget(forget)
2920 repo[None].remove(remove, unlink=not after)
2924 repo[None].remove(remove, unlink=not after)
2921 return ret
2925 return ret
2922
2926
2923 def rename(ui, repo, *pats, **opts):
2927 def rename(ui, repo, *pats, **opts):
2924 """rename files; equivalent of copy + remove
2928 """rename files; equivalent of copy + remove
2925
2929
2926 Mark dest as copies of sources; mark sources for deletion. If dest
2930 Mark dest as copies of sources; mark sources for deletion. If dest
2927 is a directory, copies are put in that directory. If dest is a
2931 is a directory, copies are put in that directory. If dest is a
2928 file, there can only be one source.
2932 file, there can only be one source.
2929
2933
2930 By default, this command copies the contents of files as they
2934 By default, this command copies the contents of files as they
2931 exist in the working directory. If invoked with -A/--after, the
2935 exist in the working directory. If invoked with -A/--after, the
2932 operation is recorded, but no copying is performed.
2936 operation is recorded, but no copying is performed.
2933
2937
2934 This command takes effect at the next commit. To undo a rename
2938 This command takes effect at the next commit. To undo a rename
2935 before that, see :hg:`revert`.
2939 before that, see :hg:`revert`.
2936
2940
2937 Returns 0 on success, 1 if errors are encountered.
2941 Returns 0 on success, 1 if errors are encountered.
2938 """
2942 """
2939 wlock = repo.wlock(False)
2943 wlock = repo.wlock(False)
2940 try:
2944 try:
2941 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2945 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2942 finally:
2946 finally:
2943 wlock.release()
2947 wlock.release()
2944
2948
2945 def resolve(ui, repo, *pats, **opts):
2949 def resolve(ui, repo, *pats, **opts):
2946 """various operations to help finish a merge
2950 """various operations to help finish a merge
2947
2951
2948 This command includes several actions that are often useful while
2952 This command includes several actions that are often useful while
2949 performing a merge, after running ``merge`` but before running
2953 performing a merge, after running ``merge`` but before running
2950 ``commit``. (It is only meaningful if your working directory has
2954 ``commit``. (It is only meaningful if your working directory has
2951 two parents.) It is most relevant for merges with unresolved
2955 two parents.) It is most relevant for merges with unresolved
2952 conflicts, which are typically a result of non-interactive merging with
2956 conflicts, which are typically a result of non-interactive merging with
2953 ``internal:merge`` or a command-line merge tool like ``diff3``.
2957 ``internal:merge`` or a command-line merge tool like ``diff3``.
2954
2958
2955 The available actions are:
2959 The available actions are:
2956
2960
2957 1) list files that were merged with conflicts (U, for unresolved)
2961 1) list files that were merged with conflicts (U, for unresolved)
2958 and without conflicts (R, for resolved): ``hg resolve -l``
2962 and without conflicts (R, for resolved): ``hg resolve -l``
2959 (this is like ``status`` for merges)
2963 (this is like ``status`` for merges)
2960 2) record that you have resolved conflicts in certain files:
2964 2) record that you have resolved conflicts in certain files:
2961 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2965 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2962 3) forget that you have resolved conflicts in certain files:
2966 3) forget that you have resolved conflicts in certain files:
2963 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2967 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2964 4) discard your current attempt(s) at resolving conflicts and
2968 4) discard your current attempt(s) at resolving conflicts and
2965 restart the merge from scratch: ``hg resolve file...``
2969 restart the merge from scratch: ``hg resolve file...``
2966 (or ``-a`` for all unresolved files)
2970 (or ``-a`` for all unresolved files)
2967
2971
2968 Note that Mercurial will not let you commit files with unresolved merge
2972 Note that Mercurial will not let you commit files with unresolved merge
2969 conflicts. You must use ``hg resolve -m ...`` before you can commit
2973 conflicts. You must use ``hg resolve -m ...`` before you can commit
2970 after a conflicting merge.
2974 after a conflicting merge.
2971
2975
2972 Returns 0 on success, 1 if any files fail a resolve attempt.
2976 Returns 0 on success, 1 if any files fail a resolve attempt.
2973 """
2977 """
2974
2978
2975 all, mark, unmark, show, nostatus = \
2979 all, mark, unmark, show, nostatus = \
2976 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2980 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2977
2981
2978 if (show and (mark or unmark)) or (mark and unmark):
2982 if (show and (mark or unmark)) or (mark and unmark):
2979 raise util.Abort(_("too many options specified"))
2983 raise util.Abort(_("too many options specified"))
2980 if pats and all:
2984 if pats and all:
2981 raise util.Abort(_("can't specify --all and patterns"))
2985 raise util.Abort(_("can't specify --all and patterns"))
2982 if not (all or pats or show or mark or unmark):
2986 if not (all or pats or show or mark or unmark):
2983 raise util.Abort(_('no files or directories specified; '
2987 raise util.Abort(_('no files or directories specified; '
2984 'use --all to remerge all files'))
2988 'use --all to remerge all files'))
2985
2989
2986 ms = mergemod.mergestate(repo)
2990 ms = mergemod.mergestate(repo)
2987 m = cmdutil.match(repo, pats, opts)
2991 m = cmdutil.match(repo, pats, opts)
2988 ret = 0
2992 ret = 0
2989
2993
2990 for f in ms:
2994 for f in ms:
2991 if m(f):
2995 if m(f):
2992 if show:
2996 if show:
2993 if nostatus:
2997 if nostatus:
2994 ui.write("%s\n" % f)
2998 ui.write("%s\n" % f)
2995 else:
2999 else:
2996 ui.write("%s %s\n" % (ms[f].upper(), f),
3000 ui.write("%s %s\n" % (ms[f].upper(), f),
2997 label='resolve.' +
3001 label='resolve.' +
2998 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3002 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2999 elif mark:
3003 elif mark:
3000 ms.mark(f, "r")
3004 ms.mark(f, "r")
3001 elif unmark:
3005 elif unmark:
3002 ms.mark(f, "u")
3006 ms.mark(f, "u")
3003 else:
3007 else:
3004 wctx = repo[None]
3008 wctx = repo[None]
3005 mctx = wctx.parents()[-1]
3009 mctx = wctx.parents()[-1]
3006
3010
3007 # backup pre-resolve (merge uses .orig for its own purposes)
3011 # backup pre-resolve (merge uses .orig for its own purposes)
3008 a = repo.wjoin(f)
3012 a = repo.wjoin(f)
3009 util.copyfile(a, a + ".resolve")
3013 util.copyfile(a, a + ".resolve")
3010
3014
3011 # resolve file
3015 # resolve file
3012 if ms.resolve(f, wctx, mctx):
3016 if ms.resolve(f, wctx, mctx):
3013 ret = 1
3017 ret = 1
3014
3018
3015 # replace filemerge's .orig file with our resolve file
3019 # replace filemerge's .orig file with our resolve file
3016 util.rename(a + ".resolve", a + ".orig")
3020 util.rename(a + ".resolve", a + ".orig")
3017 return ret
3021 return ret
3018
3022
3019 def revert(ui, repo, *pats, **opts):
3023 def revert(ui, repo, *pats, **opts):
3020 """restore individual files or directories to an earlier state
3024 """restore individual files or directories to an earlier state
3021
3025
3022 NOTE: This command is most likely not what you are looking for. revert
3026 NOTE: This command is most likely not what you are looking for. revert
3023 will partially overwrite content in the working directory without changing
3027 will partially overwrite content in the working directory without changing
3024 the working directory parents. Use :hg:`update -r rev` to check out earlier
3028 the working directory parents. Use :hg:`update -r rev` to check out earlier
3025 revisions, or :hg:`update --clean .` to undo a merge which has added
3029 revisions, or :hg:`update --clean .` to undo a merge which has added
3026 another parent.
3030 another parent.
3027
3031
3028 With no revision specified, revert the named files or directories
3032 With no revision specified, revert the named files or directories
3029 to the contents they had in the parent of the working directory.
3033 to the contents they had in the parent of the working directory.
3030 This restores the contents of the affected files to an unmodified
3034 This restores the contents of the affected files to an unmodified
3031 state and unschedules adds, removes, copies, and renames. If the
3035 state and unschedules adds, removes, copies, and renames. If the
3032 working directory has two parents, you must explicitly specify a
3036 working directory has two parents, you must explicitly specify a
3033 revision.
3037 revision.
3034
3038
3035 Using the -r/--rev option, revert the given files or directories
3039 Using the -r/--rev option, revert the given files or directories
3036 to their contents as of a specific revision. This can be helpful
3040 to their contents as of a specific revision. This can be helpful
3037 to "roll back" some or all of an earlier change. See :hg:`help
3041 to "roll back" some or all of an earlier change. See :hg:`help
3038 dates` for a list of formats valid for -d/--date.
3042 dates` for a list of formats valid for -d/--date.
3039
3043
3040 Revert modifies the working directory. It does not commit any
3044 Revert modifies the working directory. It does not commit any
3041 changes, or change the parent of the working directory. If you
3045 changes, or change the parent of the working directory. If you
3042 revert to a revision other than the parent of the working
3046 revert to a revision other than the parent of the working
3043 directory, the reverted files will thus appear modified
3047 directory, the reverted files will thus appear modified
3044 afterwards.
3048 afterwards.
3045
3049
3046 If a file has been deleted, it is restored. If the executable mode
3050 If a file has been deleted, it is restored. If the executable mode
3047 of a file was changed, it is reset.
3051 of a file was changed, it is reset.
3048
3052
3049 If names are given, all files matching the names are reverted.
3053 If names are given, all files matching the names are reverted.
3050 If no arguments are given, no files are reverted.
3054 If no arguments are given, no files are reverted.
3051
3055
3052 Modified files are saved with a .orig suffix before reverting.
3056 Modified files are saved with a .orig suffix before reverting.
3053 To disable these backups, use --no-backup.
3057 To disable these backups, use --no-backup.
3054
3058
3055 Returns 0 on success.
3059 Returns 0 on success.
3056 """
3060 """
3057
3061
3058 if opts["date"]:
3062 if opts["date"]:
3059 if opts["rev"]:
3063 if opts["rev"]:
3060 raise util.Abort(_("you can't specify a revision and a date"))
3064 raise util.Abort(_("you can't specify a revision and a date"))
3061 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3065 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3062
3066
3063 if not pats and not opts.get('all'):
3067 if not pats and not opts.get('all'):
3064 raise util.Abort(_('no files or directories specified; '
3068 raise util.Abort(_('no files or directories specified; '
3065 'use --all to revert the whole repo'))
3069 'use --all to revert the whole repo'))
3066
3070
3067 parent, p2 = repo.dirstate.parents()
3071 parent, p2 = repo.dirstate.parents()
3068 if not opts.get('rev') and p2 != nullid:
3072 if not opts.get('rev') and p2 != nullid:
3069 raise util.Abort(_('uncommitted merge - please provide a '
3073 raise util.Abort(_('uncommitted merge - please provide a '
3070 'specific revision'))
3074 'specific revision'))
3071 ctx = repo[opts.get('rev')]
3075 ctx = repo[opts.get('rev')]
3072 node = ctx.node()
3076 node = ctx.node()
3073 mf = ctx.manifest()
3077 mf = ctx.manifest()
3074 if node == parent:
3078 if node == parent:
3075 pmf = mf
3079 pmf = mf
3076 else:
3080 else:
3077 pmf = None
3081 pmf = None
3078
3082
3079 # need all matching names in dirstate and manifest of target rev,
3083 # need all matching names in dirstate and manifest of target rev,
3080 # so have to walk both. do not print errors if files exist in one
3084 # so have to walk both. do not print errors if files exist in one
3081 # but not other.
3085 # but not other.
3082
3086
3083 names = {}
3087 names = {}
3084
3088
3085 wlock = repo.wlock()
3089 wlock = repo.wlock()
3086 try:
3090 try:
3087 # walk dirstate.
3091 # walk dirstate.
3088
3092
3089 m = cmdutil.match(repo, pats, opts)
3093 m = cmdutil.match(repo, pats, opts)
3090 m.bad = lambda x, y: False
3094 m.bad = lambda x, y: False
3091 for abs in repo.walk(m):
3095 for abs in repo.walk(m):
3092 names[abs] = m.rel(abs), m.exact(abs)
3096 names[abs] = m.rel(abs), m.exact(abs)
3093
3097
3094 # walk target manifest.
3098 # walk target manifest.
3095
3099
3096 def badfn(path, msg):
3100 def badfn(path, msg):
3097 if path in names:
3101 if path in names:
3098 return
3102 return
3099 path_ = path + '/'
3103 path_ = path + '/'
3100 for f in names:
3104 for f in names:
3101 if f.startswith(path_):
3105 if f.startswith(path_):
3102 return
3106 return
3103 ui.warn("%s: %s\n" % (m.rel(path), msg))
3107 ui.warn("%s: %s\n" % (m.rel(path), msg))
3104
3108
3105 m = cmdutil.match(repo, pats, opts)
3109 m = cmdutil.match(repo, pats, opts)
3106 m.bad = badfn
3110 m.bad = badfn
3107 for abs in repo[node].walk(m):
3111 for abs in repo[node].walk(m):
3108 if abs not in names:
3112 if abs not in names:
3109 names[abs] = m.rel(abs), m.exact(abs)
3113 names[abs] = m.rel(abs), m.exact(abs)
3110
3114
3111 m = cmdutil.matchfiles(repo, names)
3115 m = cmdutil.matchfiles(repo, names)
3112 changes = repo.status(match=m)[:4]
3116 changes = repo.status(match=m)[:4]
3113 modified, added, removed, deleted = map(set, changes)
3117 modified, added, removed, deleted = map(set, changes)
3114
3118
3115 # if f is a rename, also revert the source
3119 # if f is a rename, also revert the source
3116 cwd = repo.getcwd()
3120 cwd = repo.getcwd()
3117 for f in added:
3121 for f in added:
3118 src = repo.dirstate.copied(f)
3122 src = repo.dirstate.copied(f)
3119 if src and src not in names and repo.dirstate[src] == 'r':
3123 if src and src not in names and repo.dirstate[src] == 'r':
3120 removed.add(src)
3124 removed.add(src)
3121 names[src] = (repo.pathto(src, cwd), True)
3125 names[src] = (repo.pathto(src, cwd), True)
3122
3126
3123 def removeforget(abs):
3127 def removeforget(abs):
3124 if repo.dirstate[abs] == 'a':
3128 if repo.dirstate[abs] == 'a':
3125 return _('forgetting %s\n')
3129 return _('forgetting %s\n')
3126 return _('removing %s\n')
3130 return _('removing %s\n')
3127
3131
3128 revert = ([], _('reverting %s\n'))
3132 revert = ([], _('reverting %s\n'))
3129 add = ([], _('adding %s\n'))
3133 add = ([], _('adding %s\n'))
3130 remove = ([], removeforget)
3134 remove = ([], removeforget)
3131 undelete = ([], _('undeleting %s\n'))
3135 undelete = ([], _('undeleting %s\n'))
3132
3136
3133 disptable = (
3137 disptable = (
3134 # dispatch table:
3138 # dispatch table:
3135 # file state
3139 # file state
3136 # action if in target manifest
3140 # action if in target manifest
3137 # action if not in target manifest
3141 # action if not in target manifest
3138 # make backup if in target manifest
3142 # make backup if in target manifest
3139 # make backup if not in target manifest
3143 # make backup if not in target manifest
3140 (modified, revert, remove, True, True),
3144 (modified, revert, remove, True, True),
3141 (added, revert, remove, True, False),
3145 (added, revert, remove, True, False),
3142 (removed, undelete, None, False, False),
3146 (removed, undelete, None, False, False),
3143 (deleted, revert, remove, False, False),
3147 (deleted, revert, remove, False, False),
3144 )
3148 )
3145
3149
3146 for abs, (rel, exact) in sorted(names.items()):
3150 for abs, (rel, exact) in sorted(names.items()):
3147 mfentry = mf.get(abs)
3151 mfentry = mf.get(abs)
3148 target = repo.wjoin(abs)
3152 target = repo.wjoin(abs)
3149 def handle(xlist, dobackup):
3153 def handle(xlist, dobackup):
3150 xlist[0].append(abs)
3154 xlist[0].append(abs)
3151 if dobackup and not opts.get('no_backup') and util.lexists(target):
3155 if dobackup and not opts.get('no_backup') and util.lexists(target):
3152 bakname = "%s.orig" % rel
3156 bakname = "%s.orig" % rel
3153 ui.note(_('saving current version of %s as %s\n') %
3157 ui.note(_('saving current version of %s as %s\n') %
3154 (rel, bakname))
3158 (rel, bakname))
3155 if not opts.get('dry_run'):
3159 if not opts.get('dry_run'):
3156 util.copyfile(target, bakname)
3160 util.copyfile(target, bakname)
3157 if ui.verbose or not exact:
3161 if ui.verbose or not exact:
3158 msg = xlist[1]
3162 msg = xlist[1]
3159 if not isinstance(msg, basestring):
3163 if not isinstance(msg, basestring):
3160 msg = msg(abs)
3164 msg = msg(abs)
3161 ui.status(msg % rel)
3165 ui.status(msg % rel)
3162 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3166 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3163 if abs not in table:
3167 if abs not in table:
3164 continue
3168 continue
3165 # file has changed in dirstate
3169 # file has changed in dirstate
3166 if mfentry:
3170 if mfentry:
3167 handle(hitlist, backuphit)
3171 handle(hitlist, backuphit)
3168 elif misslist is not None:
3172 elif misslist is not None:
3169 handle(misslist, backupmiss)
3173 handle(misslist, backupmiss)
3170 break
3174 break
3171 else:
3175 else:
3172 if abs not in repo.dirstate:
3176 if abs not in repo.dirstate:
3173 if mfentry:
3177 if mfentry:
3174 handle(add, True)
3178 handle(add, True)
3175 elif exact:
3179 elif exact:
3176 ui.warn(_('file not managed: %s\n') % rel)
3180 ui.warn(_('file not managed: %s\n') % rel)
3177 continue
3181 continue
3178 # file has not changed in dirstate
3182 # file has not changed in dirstate
3179 if node == parent:
3183 if node == parent:
3180 if exact:
3184 if exact:
3181 ui.warn(_('no changes needed to %s\n') % rel)
3185 ui.warn(_('no changes needed to %s\n') % rel)
3182 continue
3186 continue
3183 if pmf is None:
3187 if pmf is None:
3184 # only need parent manifest in this unlikely case,
3188 # only need parent manifest in this unlikely case,
3185 # so do not read by default
3189 # so do not read by default
3186 pmf = repo[parent].manifest()
3190 pmf = repo[parent].manifest()
3187 if abs in pmf:
3191 if abs in pmf:
3188 if mfentry:
3192 if mfentry:
3189 # if version of file is same in parent and target
3193 # if version of file is same in parent and target
3190 # manifests, do nothing
3194 # manifests, do nothing
3191 if (pmf[abs] != mfentry or
3195 if (pmf[abs] != mfentry or
3192 pmf.flags(abs) != mf.flags(abs)):
3196 pmf.flags(abs) != mf.flags(abs)):
3193 handle(revert, False)
3197 handle(revert, False)
3194 else:
3198 else:
3195 handle(remove, False)
3199 handle(remove, False)
3196
3200
3197 if not opts.get('dry_run'):
3201 if not opts.get('dry_run'):
3198 def checkout(f):
3202 def checkout(f):
3199 fc = ctx[f]
3203 fc = ctx[f]
3200 repo.wwrite(f, fc.data(), fc.flags())
3204 repo.wwrite(f, fc.data(), fc.flags())
3201
3205
3202 audit_path = util.path_auditor(repo.root)
3206 audit_path = util.path_auditor(repo.root)
3203 for f in remove[0]:
3207 for f in remove[0]:
3204 if repo.dirstate[f] == 'a':
3208 if repo.dirstate[f] == 'a':
3205 repo.dirstate.forget(f)
3209 repo.dirstate.forget(f)
3206 continue
3210 continue
3207 audit_path(f)
3211 audit_path(f)
3208 try:
3212 try:
3209 util.unlink(repo.wjoin(f))
3213 util.unlink(repo.wjoin(f))
3210 except OSError:
3214 except OSError:
3211 pass
3215 pass
3212 repo.dirstate.remove(f)
3216 repo.dirstate.remove(f)
3213
3217
3214 normal = None
3218 normal = None
3215 if node == parent:
3219 if node == parent:
3216 # We're reverting to our parent. If possible, we'd like status
3220 # We're reverting to our parent. If possible, we'd like status
3217 # to report the file as clean. We have to use normallookup for
3221 # to report the file as clean. We have to use normallookup for
3218 # merges to avoid losing information about merged/dirty files.
3222 # merges to avoid losing information about merged/dirty files.
3219 if p2 != nullid:
3223 if p2 != nullid:
3220 normal = repo.dirstate.normallookup
3224 normal = repo.dirstate.normallookup
3221 else:
3225 else:
3222 normal = repo.dirstate.normal
3226 normal = repo.dirstate.normal
3223 for f in revert[0]:
3227 for f in revert[0]:
3224 checkout(f)
3228 checkout(f)
3225 if normal:
3229 if normal:
3226 normal(f)
3230 normal(f)
3227
3231
3228 for f in add[0]:
3232 for f in add[0]:
3229 checkout(f)
3233 checkout(f)
3230 repo.dirstate.add(f)
3234 repo.dirstate.add(f)
3231
3235
3232 normal = repo.dirstate.normallookup
3236 normal = repo.dirstate.normallookup
3233 if node == parent and p2 == nullid:
3237 if node == parent and p2 == nullid:
3234 normal = repo.dirstate.normal
3238 normal = repo.dirstate.normal
3235 for f in undelete[0]:
3239 for f in undelete[0]:
3236 checkout(f)
3240 checkout(f)
3237 normal(f)
3241 normal(f)
3238
3242
3239 finally:
3243 finally:
3240 wlock.release()
3244 wlock.release()
3241
3245
3242 def rollback(ui, repo, **opts):
3246 def rollback(ui, repo, **opts):
3243 """roll back the last transaction (dangerous)
3247 """roll back the last transaction (dangerous)
3244
3248
3245 This command should be used with care. There is only one level of
3249 This command should be used with care. There is only one level of
3246 rollback, and there is no way to undo a rollback. It will also
3250 rollback, and there is no way to undo a rollback. It will also
3247 restore the dirstate at the time of the last transaction, losing
3251 restore the dirstate at the time of the last transaction, losing
3248 any dirstate changes since that time. This command does not alter
3252 any dirstate changes since that time. This command does not alter
3249 the working directory.
3253 the working directory.
3250
3254
3251 Transactions are used to encapsulate the effects of all commands
3255 Transactions are used to encapsulate the effects of all commands
3252 that create new changesets or propagate existing changesets into a
3256 that create new changesets or propagate existing changesets into a
3253 repository. For example, the following commands are transactional,
3257 repository. For example, the following commands are transactional,
3254 and their effects can be rolled back:
3258 and their effects can be rolled back:
3255
3259
3256 - commit
3260 - commit
3257 - import
3261 - import
3258 - pull
3262 - pull
3259 - push (with this repository as the destination)
3263 - push (with this repository as the destination)
3260 - unbundle
3264 - unbundle
3261
3265
3262 This command is not intended for use on public repositories. Once
3266 This command is not intended for use on public repositories. Once
3263 changes are visible for pull by other users, rolling a transaction
3267 changes are visible for pull by other users, rolling a transaction
3264 back locally is ineffective (someone else may already have pulled
3268 back locally is ineffective (someone else may already have pulled
3265 the changes). Furthermore, a race is possible with readers of the
3269 the changes). Furthermore, a race is possible with readers of the
3266 repository; for example an in-progress pull from the repository
3270 repository; for example an in-progress pull from the repository
3267 may fail if a rollback is performed.
3271 may fail if a rollback is performed.
3268
3272
3269 Returns 0 on success, 1 if no rollback data is available.
3273 Returns 0 on success, 1 if no rollback data is available.
3270 """
3274 """
3271 return repo.rollback(opts.get('dry_run'))
3275 return repo.rollback(opts.get('dry_run'))
3272
3276
3273 def root(ui, repo):
3277 def root(ui, repo):
3274 """print the root (top) of the current working directory
3278 """print the root (top) of the current working directory
3275
3279
3276 Print the root directory of the current repository.
3280 Print the root directory of the current repository.
3277
3281
3278 Returns 0 on success.
3282 Returns 0 on success.
3279 """
3283 """
3280 ui.write(repo.root + "\n")
3284 ui.write(repo.root + "\n")
3281
3285
3282 def serve(ui, repo, **opts):
3286 def serve(ui, repo, **opts):
3283 """start stand-alone webserver
3287 """start stand-alone webserver
3284
3288
3285 Start a local HTTP repository browser and pull server. You can use
3289 Start a local HTTP repository browser and pull server. You can use
3286 this for ad-hoc sharing and browing of repositories. It is
3290 this for ad-hoc sharing and browing of repositories. It is
3287 recommended to use a real web server to serve a repository for
3291 recommended to use a real web server to serve a repository for
3288 longer periods of time.
3292 longer periods of time.
3289
3293
3290 Please note that the server does not implement access control.
3294 Please note that the server does not implement access control.
3291 This means that, by default, anybody can read from the server and
3295 This means that, by default, anybody can read from the server and
3292 nobody can write to it by default. Set the ``web.allow_push``
3296 nobody can write to it by default. Set the ``web.allow_push``
3293 option to ``*`` to allow everybody to push to the server. You
3297 option to ``*`` to allow everybody to push to the server. You
3294 should use a real web server if you need to authenticate users.
3298 should use a real web server if you need to authenticate users.
3295
3299
3296 By default, the server logs accesses to stdout and errors to
3300 By default, the server logs accesses to stdout and errors to
3297 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3301 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3298 files.
3302 files.
3299
3303
3300 To have the server choose a free port number to listen on, specify
3304 To have the server choose a free port number to listen on, specify
3301 a port number of 0; in this case, the server will print the port
3305 a port number of 0; in this case, the server will print the port
3302 number it uses.
3306 number it uses.
3303
3307
3304 Returns 0 on success.
3308 Returns 0 on success.
3305 """
3309 """
3306
3310
3307 if opts["stdio"]:
3311 if opts["stdio"]:
3308 if repo is None:
3312 if repo is None:
3309 raise error.RepoError(_("There is no Mercurial repository here"
3313 raise error.RepoError(_("There is no Mercurial repository here"
3310 " (.hg not found)"))
3314 " (.hg not found)"))
3311 s = sshserver.sshserver(ui, repo)
3315 s = sshserver.sshserver(ui, repo)
3312 s.serve_forever()
3316 s.serve_forever()
3313
3317
3314 # this way we can check if something was given in the command-line
3318 # this way we can check if something was given in the command-line
3315 if opts.get('port'):
3319 if opts.get('port'):
3316 opts['port'] = int(opts.get('port'))
3320 opts['port'] = int(opts.get('port'))
3317
3321
3318 baseui = repo and repo.baseui or ui
3322 baseui = repo and repo.baseui or ui
3319 optlist = ("name templates style address port prefix ipv6"
3323 optlist = ("name templates style address port prefix ipv6"
3320 " accesslog errorlog certificate encoding")
3324 " accesslog errorlog certificate encoding")
3321 for o in optlist.split():
3325 for o in optlist.split():
3322 val = opts.get(o, '')
3326 val = opts.get(o, '')
3323 if val in (None, ''): # should check against default options instead
3327 if val in (None, ''): # should check against default options instead
3324 continue
3328 continue
3325 baseui.setconfig("web", o, val)
3329 baseui.setconfig("web", o, val)
3326 if repo and repo.ui != baseui:
3330 if repo and repo.ui != baseui:
3327 repo.ui.setconfig("web", o, val)
3331 repo.ui.setconfig("web", o, val)
3328
3332
3329 o = opts.get('web_conf') or opts.get('webdir_conf')
3333 o = opts.get('web_conf') or opts.get('webdir_conf')
3330 if not o:
3334 if not o:
3331 if not repo:
3335 if not repo:
3332 raise error.RepoError(_("There is no Mercurial repository"
3336 raise error.RepoError(_("There is no Mercurial repository"
3333 " here (.hg not found)"))
3337 " here (.hg not found)"))
3334 o = repo.root
3338 o = repo.root
3335
3339
3336 app = hgweb.hgweb(o, baseui=ui)
3340 app = hgweb.hgweb(o, baseui=ui)
3337
3341
3338 class service(object):
3342 class service(object):
3339 def init(self):
3343 def init(self):
3340 util.set_signal_handler()
3344 util.set_signal_handler()
3341 self.httpd = hgweb.server.create_server(ui, app)
3345 self.httpd = hgweb.server.create_server(ui, app)
3342
3346
3343 if opts['port'] and not ui.verbose:
3347 if opts['port'] and not ui.verbose:
3344 return
3348 return
3345
3349
3346 if self.httpd.prefix:
3350 if self.httpd.prefix:
3347 prefix = self.httpd.prefix.strip('/') + '/'
3351 prefix = self.httpd.prefix.strip('/') + '/'
3348 else:
3352 else:
3349 prefix = ''
3353 prefix = ''
3350
3354
3351 port = ':%d' % self.httpd.port
3355 port = ':%d' % self.httpd.port
3352 if port == ':80':
3356 if port == ':80':
3353 port = ''
3357 port = ''
3354
3358
3355 bindaddr = self.httpd.addr
3359 bindaddr = self.httpd.addr
3356 if bindaddr == '0.0.0.0':
3360 if bindaddr == '0.0.0.0':
3357 bindaddr = '*'
3361 bindaddr = '*'
3358 elif ':' in bindaddr: # IPv6
3362 elif ':' in bindaddr: # IPv6
3359 bindaddr = '[%s]' % bindaddr
3363 bindaddr = '[%s]' % bindaddr
3360
3364
3361 fqaddr = self.httpd.fqaddr
3365 fqaddr = self.httpd.fqaddr
3362 if ':' in fqaddr:
3366 if ':' in fqaddr:
3363 fqaddr = '[%s]' % fqaddr
3367 fqaddr = '[%s]' % fqaddr
3364 if opts['port']:
3368 if opts['port']:
3365 write = ui.status
3369 write = ui.status
3366 else:
3370 else:
3367 write = ui.write
3371 write = ui.write
3368 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3372 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3369 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3373 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3370
3374
3371 def run(self):
3375 def run(self):
3372 self.httpd.serve_forever()
3376 self.httpd.serve_forever()
3373
3377
3374 service = service()
3378 service = service()
3375
3379
3376 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3380 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3377
3381
3378 def status(ui, repo, *pats, **opts):
3382 def status(ui, repo, *pats, **opts):
3379 """show changed files in the working directory
3383 """show changed files in the working directory
3380
3384
3381 Show status of files in the repository. If names are given, only
3385 Show status of files in the repository. If names are given, only
3382 files that match are shown. Files that are clean or ignored or
3386 files that match are shown. Files that are clean or ignored or
3383 the source of a copy/move operation, are not listed unless
3387 the source of a copy/move operation, are not listed unless
3384 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3388 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3385 Unless options described with "show only ..." are given, the
3389 Unless options described with "show only ..." are given, the
3386 options -mardu are used.
3390 options -mardu are used.
3387
3391
3388 Option -q/--quiet hides untracked (unknown and ignored) files
3392 Option -q/--quiet hides untracked (unknown and ignored) files
3389 unless explicitly requested with -u/--unknown or -i/--ignored.
3393 unless explicitly requested with -u/--unknown or -i/--ignored.
3390
3394
3391 NOTE: status may appear to disagree with diff if permissions have
3395 NOTE: status may appear to disagree with diff if permissions have
3392 changed or a merge has occurred. The standard diff format does not
3396 changed or a merge has occurred. The standard diff format does not
3393 report permission changes and diff only reports changes relative
3397 report permission changes and diff only reports changes relative
3394 to one merge parent.
3398 to one merge parent.
3395
3399
3396 If one revision is given, it is used as the base revision.
3400 If one revision is given, it is used as the base revision.
3397 If two revisions are given, the differences between them are
3401 If two revisions are given, the differences between them are
3398 shown. The --change option can also be used as a shortcut to list
3402 shown. The --change option can also be used as a shortcut to list
3399 the changed files of a revision from its first parent.
3403 the changed files of a revision from its first parent.
3400
3404
3401 The codes used to show the status of files are::
3405 The codes used to show the status of files are::
3402
3406
3403 M = modified
3407 M = modified
3404 A = added
3408 A = added
3405 R = removed
3409 R = removed
3406 C = clean
3410 C = clean
3407 ! = missing (deleted by non-hg command, but still tracked)
3411 ! = missing (deleted by non-hg command, but still tracked)
3408 ? = not tracked
3412 ? = not tracked
3409 I = ignored
3413 I = ignored
3410 = origin of the previous file listed as A (added)
3414 = origin of the previous file listed as A (added)
3411
3415
3412 Returns 0 on success.
3416 Returns 0 on success.
3413 """
3417 """
3414
3418
3415 revs = opts.get('rev')
3419 revs = opts.get('rev')
3416 change = opts.get('change')
3420 change = opts.get('change')
3417
3421
3418 if revs and change:
3422 if revs and change:
3419 msg = _('cannot specify --rev and --change at the same time')
3423 msg = _('cannot specify --rev and --change at the same time')
3420 raise util.Abort(msg)
3424 raise util.Abort(msg)
3421 elif change:
3425 elif change:
3422 node2 = repo.lookup(change)
3426 node2 = repo.lookup(change)
3423 node1 = repo[node2].parents()[0].node()
3427 node1 = repo[node2].parents()[0].node()
3424 else:
3428 else:
3425 node1, node2 = cmdutil.revpair(repo, revs)
3429 node1, node2 = cmdutil.revpair(repo, revs)
3426
3430
3427 cwd = (pats and repo.getcwd()) or ''
3431 cwd = (pats and repo.getcwd()) or ''
3428 end = opts.get('print0') and '\0' or '\n'
3432 end = opts.get('print0') and '\0' or '\n'
3429 copy = {}
3433 copy = {}
3430 states = 'modified added removed deleted unknown ignored clean'.split()
3434 states = 'modified added removed deleted unknown ignored clean'.split()
3431 show = [k for k in states if opts.get(k)]
3435 show = [k for k in states if opts.get(k)]
3432 if opts.get('all'):
3436 if opts.get('all'):
3433 show += ui.quiet and (states[:4] + ['clean']) or states
3437 show += ui.quiet and (states[:4] + ['clean']) or states
3434 if not show:
3438 if not show:
3435 show = ui.quiet and states[:4] or states[:5]
3439 show = ui.quiet and states[:4] or states[:5]
3436
3440
3437 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3441 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3438 'ignored' in show, 'clean' in show, 'unknown' in show)
3442 'ignored' in show, 'clean' in show, 'unknown' in show)
3439 changestates = zip(states, 'MAR!?IC', stat)
3443 changestates = zip(states, 'MAR!?IC', stat)
3440
3444
3441 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3445 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3442 ctxn = repo[nullid]
3446 ctxn = repo[nullid]
3443 ctx1 = repo[node1]
3447 ctx1 = repo[node1]
3444 ctx2 = repo[node2]
3448 ctx2 = repo[node2]
3445 added = stat[1]
3449 added = stat[1]
3446 if node2 is None:
3450 if node2 is None:
3447 added = stat[0] + stat[1] # merged?
3451 added = stat[0] + stat[1] # merged?
3448
3452
3449 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3453 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3450 if k in added:
3454 if k in added:
3451 copy[k] = v
3455 copy[k] = v
3452 elif v in added:
3456 elif v in added:
3453 copy[v] = k
3457 copy[v] = k
3454
3458
3455 for state, char, files in changestates:
3459 for state, char, files in changestates:
3456 if state in show:
3460 if state in show:
3457 format = "%s %%s%s" % (char, end)
3461 format = "%s %%s%s" % (char, end)
3458 if opts.get('no_status'):
3462 if opts.get('no_status'):
3459 format = "%%s%s" % end
3463 format = "%%s%s" % end
3460
3464
3461 for f in files:
3465 for f in files:
3462 ui.write(format % repo.pathto(f, cwd),
3466 ui.write(format % repo.pathto(f, cwd),
3463 label='status.' + state)
3467 label='status.' + state)
3464 if f in copy:
3468 if f in copy:
3465 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3469 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3466 label='status.copied')
3470 label='status.copied')
3467
3471
3468 def summary(ui, repo, **opts):
3472 def summary(ui, repo, **opts):
3469 """summarize working directory state
3473 """summarize working directory state
3470
3474
3471 This generates a brief summary of the working directory state,
3475 This generates a brief summary of the working directory state,
3472 including parents, branch, commit status, and available updates.
3476 including parents, branch, commit status, and available updates.
3473
3477
3474 With the --remote option, this will check the default paths for
3478 With the --remote option, this will check the default paths for
3475 incoming and outgoing changes. This can be time-consuming.
3479 incoming and outgoing changes. This can be time-consuming.
3476
3480
3477 Returns 0 on success.
3481 Returns 0 on success.
3478 """
3482 """
3479
3483
3480 ctx = repo[None]
3484 ctx = repo[None]
3481 parents = ctx.parents()
3485 parents = ctx.parents()
3482 pnode = parents[0].node()
3486 pnode = parents[0].node()
3483
3487
3484 for p in parents:
3488 for p in parents:
3485 # label with log.changeset (instead of log.parent) since this
3489 # label with log.changeset (instead of log.parent) since this
3486 # shows a working directory parent *changeset*:
3490 # shows a working directory parent *changeset*:
3487 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3491 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3488 label='log.changeset')
3492 label='log.changeset')
3489 ui.write(' '.join(p.tags()), label='log.tag')
3493 ui.write(' '.join(p.tags()), label='log.tag')
3490 if p.rev() == -1:
3494 if p.rev() == -1:
3491 if not len(repo):
3495 if not len(repo):
3492 ui.write(_(' (empty repository)'))
3496 ui.write(_(' (empty repository)'))
3493 else:
3497 else:
3494 ui.write(_(' (no revision checked out)'))
3498 ui.write(_(' (no revision checked out)'))
3495 ui.write('\n')
3499 ui.write('\n')
3496 if p.description():
3500 if p.description():
3497 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3501 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3498 label='log.summary')
3502 label='log.summary')
3499
3503
3500 branch = ctx.branch()
3504 branch = ctx.branch()
3501 bheads = repo.branchheads(branch)
3505 bheads = repo.branchheads(branch)
3502 m = _('branch: %s\n') % branch
3506 m = _('branch: %s\n') % branch
3503 if branch != 'default':
3507 if branch != 'default':
3504 ui.write(m, label='log.branch')
3508 ui.write(m, label='log.branch')
3505 else:
3509 else:
3506 ui.status(m, label='log.branch')
3510 ui.status(m, label='log.branch')
3507
3511
3508 st = list(repo.status(unknown=True))[:6]
3512 st = list(repo.status(unknown=True))[:6]
3509
3513
3510 c = repo.dirstate.copies()
3514 c = repo.dirstate.copies()
3511 copied, renamed = [], []
3515 copied, renamed = [], []
3512 for d, s in c.iteritems():
3516 for d, s in c.iteritems():
3513 if s in st[2]:
3517 if s in st[2]:
3514 st[2].remove(s)
3518 st[2].remove(s)
3515 renamed.append(d)
3519 renamed.append(d)
3516 else:
3520 else:
3517 copied.append(d)
3521 copied.append(d)
3518 if d in st[1]:
3522 if d in st[1]:
3519 st[1].remove(d)
3523 st[1].remove(d)
3520 st.insert(3, renamed)
3524 st.insert(3, renamed)
3521 st.insert(4, copied)
3525 st.insert(4, copied)
3522
3526
3523 ms = mergemod.mergestate(repo)
3527 ms = mergemod.mergestate(repo)
3524 st.append([f for f in ms if ms[f] == 'u'])
3528 st.append([f for f in ms if ms[f] == 'u'])
3525
3529
3526 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3530 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3527 st.append(subs)
3531 st.append(subs)
3528
3532
3529 labels = [ui.label(_('%d modified'), 'status.modified'),
3533 labels = [ui.label(_('%d modified'), 'status.modified'),
3530 ui.label(_('%d added'), 'status.added'),
3534 ui.label(_('%d added'), 'status.added'),
3531 ui.label(_('%d removed'), 'status.removed'),
3535 ui.label(_('%d removed'), 'status.removed'),
3532 ui.label(_('%d renamed'), 'status.copied'),
3536 ui.label(_('%d renamed'), 'status.copied'),
3533 ui.label(_('%d copied'), 'status.copied'),
3537 ui.label(_('%d copied'), 'status.copied'),
3534 ui.label(_('%d deleted'), 'status.deleted'),
3538 ui.label(_('%d deleted'), 'status.deleted'),
3535 ui.label(_('%d unknown'), 'status.unknown'),
3539 ui.label(_('%d unknown'), 'status.unknown'),
3536 ui.label(_('%d ignored'), 'status.ignored'),
3540 ui.label(_('%d ignored'), 'status.ignored'),
3537 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3541 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3538 ui.label(_('%d subrepos'), 'status.modified')]
3542 ui.label(_('%d subrepos'), 'status.modified')]
3539 t = []
3543 t = []
3540 for s, l in zip(st, labels):
3544 for s, l in zip(st, labels):
3541 if s:
3545 if s:
3542 t.append(l % len(s))
3546 t.append(l % len(s))
3543
3547
3544 t = ', '.join(t)
3548 t = ', '.join(t)
3545 cleanworkdir = False
3549 cleanworkdir = False
3546
3550
3547 if len(parents) > 1:
3551 if len(parents) > 1:
3548 t += _(' (merge)')
3552 t += _(' (merge)')
3549 elif branch != parents[0].branch():
3553 elif branch != parents[0].branch():
3550 t += _(' (new branch)')
3554 t += _(' (new branch)')
3551 elif (parents[0].extra().get('close') and
3555 elif (parents[0].extra().get('close') and
3552 pnode in repo.branchheads(branch, closed=True)):
3556 pnode in repo.branchheads(branch, closed=True)):
3553 t += _(' (head closed)')
3557 t += _(' (head closed)')
3554 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3558 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3555 t += _(' (clean)')
3559 t += _(' (clean)')
3556 cleanworkdir = True
3560 cleanworkdir = True
3557 elif pnode not in bheads:
3561 elif pnode not in bheads:
3558 t += _(' (new branch head)')
3562 t += _(' (new branch head)')
3559
3563
3560 if cleanworkdir:
3564 if cleanworkdir:
3561 ui.status(_('commit: %s\n') % t.strip())
3565 ui.status(_('commit: %s\n') % t.strip())
3562 else:
3566 else:
3563 ui.write(_('commit: %s\n') % t.strip())
3567 ui.write(_('commit: %s\n') % t.strip())
3564
3568
3565 # all ancestors of branch heads - all ancestors of parent = new csets
3569 # all ancestors of branch heads - all ancestors of parent = new csets
3566 new = [0] * len(repo)
3570 new = [0] * len(repo)
3567 cl = repo.changelog
3571 cl = repo.changelog
3568 for a in [cl.rev(n) for n in bheads]:
3572 for a in [cl.rev(n) for n in bheads]:
3569 new[a] = 1
3573 new[a] = 1
3570 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3574 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3571 new[a] = 1
3575 new[a] = 1
3572 for a in [p.rev() for p in parents]:
3576 for a in [p.rev() for p in parents]:
3573 if a >= 0:
3577 if a >= 0:
3574 new[a] = 0
3578 new[a] = 0
3575 for a in cl.ancestors(*[p.rev() for p in parents]):
3579 for a in cl.ancestors(*[p.rev() for p in parents]):
3576 new[a] = 0
3580 new[a] = 0
3577 new = sum(new)
3581 new = sum(new)
3578
3582
3579 if new == 0:
3583 if new == 0:
3580 ui.status(_('update: (current)\n'))
3584 ui.status(_('update: (current)\n'))
3581 elif pnode not in bheads:
3585 elif pnode not in bheads:
3582 ui.write(_('update: %d new changesets (update)\n') % new)
3586 ui.write(_('update: %d new changesets (update)\n') % new)
3583 else:
3587 else:
3584 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3588 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3585 (new, len(bheads)))
3589 (new, len(bheads)))
3586
3590
3587 if opts.get('remote'):
3591 if opts.get('remote'):
3588 t = []
3592 t = []
3589 source, branches = hg.parseurl(ui.expandpath('default'))
3593 source, branches = hg.parseurl(ui.expandpath('default'))
3590 other = hg.repository(hg.remoteui(repo, {}), source)
3594 other = hg.repository(hg.remoteui(repo, {}), source)
3591 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3595 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3592 ui.debug('comparing with %s\n' % url.hidepassword(source))
3596 ui.debug('comparing with %s\n' % url.hidepassword(source))
3593 repo.ui.pushbuffer()
3597 repo.ui.pushbuffer()
3594 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3598 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3595 repo.ui.popbuffer()
3599 repo.ui.popbuffer()
3596 if incoming:
3600 if incoming:
3597 t.append(_('1 or more incoming'))
3601 t.append(_('1 or more incoming'))
3598
3602
3599 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3603 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3600 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3604 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3601 other = hg.repository(hg.remoteui(repo, {}), dest)
3605 other = hg.repository(hg.remoteui(repo, {}), dest)
3602 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3606 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3603 repo.ui.pushbuffer()
3607 repo.ui.pushbuffer()
3604 o = discovery.findoutgoing(repo, other)
3608 o = discovery.findoutgoing(repo, other)
3605 repo.ui.popbuffer()
3609 repo.ui.popbuffer()
3606 o = repo.changelog.nodesbetween(o, None)[0]
3610 o = repo.changelog.nodesbetween(o, None)[0]
3607 if o:
3611 if o:
3608 t.append(_('%d outgoing') % len(o))
3612 t.append(_('%d outgoing') % len(o))
3609
3613
3610 if t:
3614 if t:
3611 ui.write(_('remote: %s\n') % (', '.join(t)))
3615 ui.write(_('remote: %s\n') % (', '.join(t)))
3612 else:
3616 else:
3613 ui.status(_('remote: (synced)\n'))
3617 ui.status(_('remote: (synced)\n'))
3614
3618
3615 def tag(ui, repo, name1, *names, **opts):
3619 def tag(ui, repo, name1, *names, **opts):
3616 """add one or more tags for the current or given revision
3620 """add one or more tags for the current or given revision
3617
3621
3618 Name a particular revision using <name>.
3622 Name a particular revision using <name>.
3619
3623
3620 Tags are used to name particular revisions of the repository and are
3624 Tags are used to name particular revisions of the repository and are
3621 very useful to compare different revisions, to go back to significant
3625 very useful to compare different revisions, to go back to significant
3622 earlier versions or to mark branch points as releases, etc.
3626 earlier versions or to mark branch points as releases, etc.
3623
3627
3624 If no revision is given, the parent of the working directory is
3628 If no revision is given, the parent of the working directory is
3625 used, or tip if no revision is checked out.
3629 used, or tip if no revision is checked out.
3626
3630
3627 To facilitate version control, distribution, and merging of tags,
3631 To facilitate version control, distribution, and merging of tags,
3628 they are stored as a file named ".hgtags" which is managed
3632 they are stored as a file named ".hgtags" which is managed
3629 similarly to other project files and can be hand-edited if
3633 similarly to other project files and can be hand-edited if
3630 necessary. The file '.hg/localtags' is used for local tags (not
3634 necessary. The file '.hg/localtags' is used for local tags (not
3631 shared among repositories).
3635 shared among repositories).
3632
3636
3633 See :hg:`help dates` for a list of formats valid for -d/--date.
3637 See :hg:`help dates` for a list of formats valid for -d/--date.
3634
3638
3635 Since tag names have priority over branch names during revision
3639 Since tag names have priority over branch names during revision
3636 lookup, using an existing branch name as a tag name is discouraged.
3640 lookup, using an existing branch name as a tag name is discouraged.
3637
3641
3638 Returns 0 on success.
3642 Returns 0 on success.
3639 """
3643 """
3640
3644
3641 rev_ = "."
3645 rev_ = "."
3642 names = [t.strip() for t in (name1,) + names]
3646 names = [t.strip() for t in (name1,) + names]
3643 if len(names) != len(set(names)):
3647 if len(names) != len(set(names)):
3644 raise util.Abort(_('tag names must be unique'))
3648 raise util.Abort(_('tag names must be unique'))
3645 for n in names:
3649 for n in names:
3646 if n in ['tip', '.', 'null']:
3650 if n in ['tip', '.', 'null']:
3647 raise util.Abort(_('the name \'%s\' is reserved') % n)
3651 raise util.Abort(_('the name \'%s\' is reserved') % n)
3648 if opts.get('rev') and opts.get('remove'):
3652 if opts.get('rev') and opts.get('remove'):
3649 raise util.Abort(_("--rev and --remove are incompatible"))
3653 raise util.Abort(_("--rev and --remove are incompatible"))
3650 if opts.get('rev'):
3654 if opts.get('rev'):
3651 rev_ = opts['rev']
3655 rev_ = opts['rev']
3652 message = opts.get('message')
3656 message = opts.get('message')
3653 if opts.get('remove'):
3657 if opts.get('remove'):
3654 expectedtype = opts.get('local') and 'local' or 'global'
3658 expectedtype = opts.get('local') and 'local' or 'global'
3655 for n in names:
3659 for n in names:
3656 if not repo.tagtype(n):
3660 if not repo.tagtype(n):
3657 raise util.Abort(_('tag \'%s\' does not exist') % n)
3661 raise util.Abort(_('tag \'%s\' does not exist') % n)
3658 if repo.tagtype(n) != expectedtype:
3662 if repo.tagtype(n) != expectedtype:
3659 if expectedtype == 'global':
3663 if expectedtype == 'global':
3660 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3664 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3661 else:
3665 else:
3662 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3666 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3663 rev_ = nullid
3667 rev_ = nullid
3664 if not message:
3668 if not message:
3665 # we don't translate commit messages
3669 # we don't translate commit messages
3666 message = 'Removed tag %s' % ', '.join(names)
3670 message = 'Removed tag %s' % ', '.join(names)
3667 elif not opts.get('force'):
3671 elif not opts.get('force'):
3668 for n in names:
3672 for n in names:
3669 if n in repo.tags():
3673 if n in repo.tags():
3670 raise util.Abort(_('tag \'%s\' already exists '
3674 raise util.Abort(_('tag \'%s\' already exists '
3671 '(use -f to force)') % n)
3675 '(use -f to force)') % n)
3672 if not rev_ and repo.dirstate.parents()[1] != nullid:
3676 if not rev_ and repo.dirstate.parents()[1] != nullid:
3673 raise util.Abort(_('uncommitted merge - please provide a '
3677 raise util.Abort(_('uncommitted merge - please provide a '
3674 'specific revision'))
3678 'specific revision'))
3675 r = repo[rev_].node()
3679 r = repo[rev_].node()
3676
3680
3677 if not message:
3681 if not message:
3678 # we don't translate commit messages
3682 # we don't translate commit messages
3679 message = ('Added tag %s for changeset %s' %
3683 message = ('Added tag %s for changeset %s' %
3680 (', '.join(names), short(r)))
3684 (', '.join(names), short(r)))
3681
3685
3682 date = opts.get('date')
3686 date = opts.get('date')
3683 if date:
3687 if date:
3684 date = util.parsedate(date)
3688 date = util.parsedate(date)
3685
3689
3686 if opts.get('edit'):
3690 if opts.get('edit'):
3687 message = ui.edit(message, ui.username())
3691 message = ui.edit(message, ui.username())
3688
3692
3689 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3693 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3690
3694
3691 def tags(ui, repo):
3695 def tags(ui, repo):
3692 """list repository tags
3696 """list repository tags
3693
3697
3694 This lists both regular and local tags. When the -v/--verbose
3698 This lists both regular and local tags. When the -v/--verbose
3695 switch is used, a third column "local" is printed for local tags.
3699 switch is used, a third column "local" is printed for local tags.
3696
3700
3697 Returns 0 on success.
3701 Returns 0 on success.
3698 """
3702 """
3699
3703
3700 hexfunc = ui.debugflag and hex or short
3704 hexfunc = ui.debugflag and hex or short
3701 tagtype = ""
3705 tagtype = ""
3702
3706
3703 for t, n in reversed(repo.tagslist()):
3707 for t, n in reversed(repo.tagslist()):
3704 if ui.quiet:
3708 if ui.quiet:
3705 ui.write("%s\n" % t)
3709 ui.write("%s\n" % t)
3706 continue
3710 continue
3707
3711
3708 try:
3712 try:
3709 hn = hexfunc(n)
3713 hn = hexfunc(n)
3710 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3714 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3711 except error.LookupError:
3715 except error.LookupError:
3712 r = " ?:%s" % hn
3716 r = " ?:%s" % hn
3713 else:
3717 else:
3714 spaces = " " * (30 - encoding.colwidth(t))
3718 spaces = " " * (30 - encoding.colwidth(t))
3715 if ui.verbose:
3719 if ui.verbose:
3716 if repo.tagtype(t) == 'local':
3720 if repo.tagtype(t) == 'local':
3717 tagtype = " local"
3721 tagtype = " local"
3718 else:
3722 else:
3719 tagtype = ""
3723 tagtype = ""
3720 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3724 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3721
3725
3722 def tip(ui, repo, **opts):
3726 def tip(ui, repo, **opts):
3723 """show the tip revision
3727 """show the tip revision
3724
3728
3725 The tip revision (usually just called the tip) is the changeset
3729 The tip revision (usually just called the tip) is the changeset
3726 most recently added to the repository (and therefore the most
3730 most recently added to the repository (and therefore the most
3727 recently changed head).
3731 recently changed head).
3728
3732
3729 If you have just made a commit, that commit will be the tip. If
3733 If you have just made a commit, that commit will be the tip. If
3730 you have just pulled changes from another repository, the tip of
3734 you have just pulled changes from another repository, the tip of
3731 that repository becomes the current tip. The "tip" tag is special
3735 that repository becomes the current tip. The "tip" tag is special
3732 and cannot be renamed or assigned to a different changeset.
3736 and cannot be renamed or assigned to a different changeset.
3733
3737
3734 Returns 0 on success.
3738 Returns 0 on success.
3735 """
3739 """
3736 displayer = cmdutil.show_changeset(ui, repo, opts)
3740 displayer = cmdutil.show_changeset(ui, repo, opts)
3737 displayer.show(repo[len(repo) - 1])
3741 displayer.show(repo[len(repo) - 1])
3738 displayer.close()
3742 displayer.close()
3739
3743
3740 def unbundle(ui, repo, fname1, *fnames, **opts):
3744 def unbundle(ui, repo, fname1, *fnames, **opts):
3741 """apply one or more changegroup files
3745 """apply one or more changegroup files
3742
3746
3743 Apply one or more compressed changegroup files generated by the
3747 Apply one or more compressed changegroup files generated by the
3744 bundle command.
3748 bundle command.
3745
3749
3746 Returns 0 on success, 1 if an update has unresolved files.
3750 Returns 0 on success, 1 if an update has unresolved files.
3747 """
3751 """
3748 fnames = (fname1,) + fnames
3752 fnames = (fname1,) + fnames
3749
3753
3750 lock = repo.lock()
3754 lock = repo.lock()
3751 try:
3755 try:
3752 for fname in fnames:
3756 for fname in fnames:
3753 f = url.open(ui, fname)
3757 f = url.open(ui, fname)
3754 gen = changegroup.readbundle(f, fname)
3758 gen = changegroup.readbundle(f, fname)
3755 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3759 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3756 lock=lock)
3760 lock=lock)
3757 finally:
3761 finally:
3758 lock.release()
3762 lock.release()
3759
3763
3760 return postincoming(ui, repo, modheads, opts.get('update'), None)
3764 return postincoming(ui, repo, modheads, opts.get('update'), None)
3761
3765
3762 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3766 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3763 """update working directory (or switch revisions)
3767 """update working directory (or switch revisions)
3764
3768
3765 Update the repository's working directory to the specified
3769 Update the repository's working directory to the specified
3766 changeset.
3770 changeset.
3767
3771
3768 If no changeset is specified, attempt to update to the head of the
3772 If no changeset is specified, attempt to update to the head of the
3769 current branch. If this head is a descendant of the working
3773 current branch. If this head is a descendant of the working
3770 directory's parent, update to it, otherwise abort.
3774 directory's parent, update to it, otherwise abort.
3771
3775
3772 The following rules apply when the working directory contains
3776 The following rules apply when the working directory contains
3773 uncommitted changes:
3777 uncommitted changes:
3774
3778
3775 1. If neither -c/--check nor -C/--clean is specified, and if
3779 1. If neither -c/--check nor -C/--clean is specified, and if
3776 the requested changeset is an ancestor or descendant of
3780 the requested changeset is an ancestor or descendant of
3777 the working directory's parent, the uncommitted changes
3781 the working directory's parent, the uncommitted changes
3778 are merged into the requested changeset and the merged
3782 are merged into the requested changeset and the merged
3779 result is left uncommitted. If the requested changeset is
3783 result is left uncommitted. If the requested changeset is
3780 not an ancestor or descendant (that is, it is on another
3784 not an ancestor or descendant (that is, it is on another
3781 branch), the update is aborted and the uncommitted changes
3785 branch), the update is aborted and the uncommitted changes
3782 are preserved.
3786 are preserved.
3783
3787
3784 2. With the -c/--check option, the update is aborted and the
3788 2. With the -c/--check option, the update is aborted and the
3785 uncommitted changes are preserved.
3789 uncommitted changes are preserved.
3786
3790
3787 3. With the -C/--clean option, uncommitted changes are discarded and
3791 3. With the -C/--clean option, uncommitted changes are discarded and
3788 the working directory is updated to the requested changeset.
3792 the working directory is updated to the requested changeset.
3789
3793
3790 Use null as the changeset to remove the working directory (like
3794 Use null as the changeset to remove the working directory (like
3791 :hg:`clone -U`).
3795 :hg:`clone -U`).
3792
3796
3793 If you want to update just one file to an older changeset, use :hg:`revert`.
3797 If you want to update just one file to an older changeset, use :hg:`revert`.
3794
3798
3795 See :hg:`help dates` for a list of formats valid for -d/--date.
3799 See :hg:`help dates` for a list of formats valid for -d/--date.
3796
3800
3797 Returns 0 on success, 1 if there are unresolved files.
3801 Returns 0 on success, 1 if there are unresolved files.
3798 """
3802 """
3799 if rev and node:
3803 if rev and node:
3800 raise util.Abort(_("please specify just one revision"))
3804 raise util.Abort(_("please specify just one revision"))
3801
3805
3802 if not rev:
3806 if not rev:
3803 rev = node
3807 rev = node
3804
3808
3805 if check and clean:
3809 if check and clean:
3806 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3810 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3807
3811
3808 if check:
3812 if check:
3809 # we could use dirty() but we can ignore merge and branch trivia
3813 # we could use dirty() but we can ignore merge and branch trivia
3810 c = repo[None]
3814 c = repo[None]
3811 if c.modified() or c.added() or c.removed():
3815 if c.modified() or c.added() or c.removed():
3812 raise util.Abort(_("uncommitted local changes"))
3816 raise util.Abort(_("uncommitted local changes"))
3813
3817
3814 if date:
3818 if date:
3815 if rev:
3819 if rev:
3816 raise util.Abort(_("you can't specify a revision and a date"))
3820 raise util.Abort(_("you can't specify a revision and a date"))
3817 rev = cmdutil.finddate(ui, repo, date)
3821 rev = cmdutil.finddate(ui, repo, date)
3818
3822
3819 if clean or check:
3823 if clean or check:
3820 return hg.clean(repo, rev)
3824 return hg.clean(repo, rev)
3821 else:
3825 else:
3822 return hg.update(repo, rev)
3826 return hg.update(repo, rev)
3823
3827
3824 def verify(ui, repo):
3828 def verify(ui, repo):
3825 """verify the integrity of the repository
3829 """verify the integrity of the repository
3826
3830
3827 Verify the integrity of the current repository.
3831 Verify the integrity of the current repository.
3828
3832
3829 This will perform an extensive check of the repository's
3833 This will perform an extensive check of the repository's
3830 integrity, validating the hashes and checksums of each entry in
3834 integrity, validating the hashes and checksums of each entry in
3831 the changelog, manifest, and tracked files, as well as the
3835 the changelog, manifest, and tracked files, as well as the
3832 integrity of their crosslinks and indices.
3836 integrity of their crosslinks and indices.
3833
3837
3834 Returns 0 on success, 1 if errors are encountered.
3838 Returns 0 on success, 1 if errors are encountered.
3835 """
3839 """
3836 return hg.verify(repo)
3840 return hg.verify(repo)
3837
3841
3838 def version_(ui):
3842 def version_(ui):
3839 """output version and copyright information"""
3843 """output version and copyright information"""
3840 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3844 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3841 % util.version())
3845 % util.version())
3842 ui.status(_(
3846 ui.status(_(
3843 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3847 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3844 "This is free software; see the source for copying conditions. "
3848 "This is free software; see the source for copying conditions. "
3845 "There is NO\nwarranty; "
3849 "There is NO\nwarranty; "
3846 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3850 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3847 ))
3851 ))
3848
3852
3849 # Command options and aliases are listed here, alphabetically
3853 # Command options and aliases are listed here, alphabetically
3850
3854
3851 globalopts = [
3855 globalopts = [
3852 ('R', 'repository', '',
3856 ('R', 'repository', '',
3853 _('repository root directory or name of overlay bundle file'),
3857 _('repository root directory or name of overlay bundle file'),
3854 _('REPO')),
3858 _('REPO')),
3855 ('', 'cwd', '',
3859 ('', 'cwd', '',
3856 _('change working directory'), _('DIR')),
3860 _('change working directory'), _('DIR')),
3857 ('y', 'noninteractive', None,
3861 ('y', 'noninteractive', None,
3858 _('do not prompt, assume \'yes\' for any required answers')),
3862 _('do not prompt, assume \'yes\' for any required answers')),
3859 ('q', 'quiet', None, _('suppress output')),
3863 ('q', 'quiet', None, _('suppress output')),
3860 ('v', 'verbose', None, _('enable additional output')),
3864 ('v', 'verbose', None, _('enable additional output')),
3861 ('', 'config', [],
3865 ('', 'config', [],
3862 _('set/override config option (use \'section.name=value\')'),
3866 _('set/override config option (use \'section.name=value\')'),
3863 _('CONFIG')),
3867 _('CONFIG')),
3864 ('', 'debug', None, _('enable debugging output')),
3868 ('', 'debug', None, _('enable debugging output')),
3865 ('', 'debugger', None, _('start debugger')),
3869 ('', 'debugger', None, _('start debugger')),
3866 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3870 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3867 _('ENCODE')),
3871 _('ENCODE')),
3868 ('', 'encodingmode', encoding.encodingmode,
3872 ('', 'encodingmode', encoding.encodingmode,
3869 _('set the charset encoding mode'), _('MODE')),
3873 _('set the charset encoding mode'), _('MODE')),
3870 ('', 'traceback', None, _('always print a traceback on exception')),
3874 ('', 'traceback', None, _('always print a traceback on exception')),
3871 ('', 'time', None, _('time how long the command takes')),
3875 ('', 'time', None, _('time how long the command takes')),
3872 ('', 'profile', None, _('print command execution profile')),
3876 ('', 'profile', None, _('print command execution profile')),
3873 ('', 'version', None, _('output version information and exit')),
3877 ('', 'version', None, _('output version information and exit')),
3874 ('h', 'help', None, _('display help and exit')),
3878 ('h', 'help', None, _('display help and exit')),
3875 ]
3879 ]
3876
3880
3877 dryrunopts = [('n', 'dry-run', None,
3881 dryrunopts = [('n', 'dry-run', None,
3878 _('do not perform actions, just print output'))]
3882 _('do not perform actions, just print output'))]
3879
3883
3880 remoteopts = [
3884 remoteopts = [
3881 ('e', 'ssh', '',
3885 ('e', 'ssh', '',
3882 _('specify ssh command to use'), _('CMD')),
3886 _('specify ssh command to use'), _('CMD')),
3883 ('', 'remotecmd', '',
3887 ('', 'remotecmd', '',
3884 _('specify hg command to run on the remote side'), _('CMD')),
3888 _('specify hg command to run on the remote side'), _('CMD')),
3885 ]
3889 ]
3886
3890
3887 walkopts = [
3891 walkopts = [
3888 ('I', 'include', [],
3892 ('I', 'include', [],
3889 _('include names matching the given patterns'), _('PATTERN')),
3893 _('include names matching the given patterns'), _('PATTERN')),
3890 ('X', 'exclude', [],
3894 ('X', 'exclude', [],
3891 _('exclude names matching the given patterns'), _('PATTERN')),
3895 _('exclude names matching the given patterns'), _('PATTERN')),
3892 ]
3896 ]
3893
3897
3894 commitopts = [
3898 commitopts = [
3895 ('m', 'message', '',
3899 ('m', 'message', '',
3896 _('use text as commit message'), _('TEXT')),
3900 _('use text as commit message'), _('TEXT')),
3897 ('l', 'logfile', '',
3901 ('l', 'logfile', '',
3898 _('read commit message from file'), _('FILE')),
3902 _('read commit message from file'), _('FILE')),
3899 ]
3903 ]
3900
3904
3901 commitopts2 = [
3905 commitopts2 = [
3902 ('d', 'date', '',
3906 ('d', 'date', '',
3903 _('record datecode as commit date'), _('DATE')),
3907 _('record datecode as commit date'), _('DATE')),
3904 ('u', 'user', '',
3908 ('u', 'user', '',
3905 _('record the specified user as committer'), _('USER')),
3909 _('record the specified user as committer'), _('USER')),
3906 ]
3910 ]
3907
3911
3908 templateopts = [
3912 templateopts = [
3909 ('', 'style', '',
3913 ('', 'style', '',
3910 _('display using template map file'), _('STYLE')),
3914 _('display using template map file'), _('STYLE')),
3911 ('', 'template', '',
3915 ('', 'template', '',
3912 _('display with template'), _('TEMPLATE')),
3916 _('display with template'), _('TEMPLATE')),
3913 ]
3917 ]
3914
3918
3915 logopts = [
3919 logopts = [
3916 ('p', 'patch', None, _('show patch')),
3920 ('p', 'patch', None, _('show patch')),
3917 ('g', 'git', None, _('use git extended diff format')),
3921 ('g', 'git', None, _('use git extended diff format')),
3918 ('l', 'limit', '',
3922 ('l', 'limit', '',
3919 _('limit number of changes displayed'), _('NUM')),
3923 _('limit number of changes displayed'), _('NUM')),
3920 ('M', 'no-merges', None, _('do not show merges')),
3924 ('M', 'no-merges', None, _('do not show merges')),
3921 ('', 'stat', None, _('output diffstat-style summary of changes')),
3925 ('', 'stat', None, _('output diffstat-style summary of changes')),
3922 ] + templateopts
3926 ] + templateopts
3923
3927
3924 diffopts = [
3928 diffopts = [
3925 ('a', 'text', None, _('treat all files as text')),
3929 ('a', 'text', None, _('treat all files as text')),
3926 ('g', 'git', None, _('use git extended diff format')),
3930 ('g', 'git', None, _('use git extended diff format')),
3927 ('', 'nodates', None, _('omit dates from diff headers'))
3931 ('', 'nodates', None, _('omit dates from diff headers'))
3928 ]
3932 ]
3929
3933
3930 diffopts2 = [
3934 diffopts2 = [
3931 ('p', 'show-function', None, _('show which function each change is in')),
3935 ('p', 'show-function', None, _('show which function each change is in')),
3932 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3936 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3933 ('w', 'ignore-all-space', None,
3937 ('w', 'ignore-all-space', None,
3934 _('ignore white space when comparing lines')),
3938 _('ignore white space when comparing lines')),
3935 ('b', 'ignore-space-change', None,
3939 ('b', 'ignore-space-change', None,
3936 _('ignore changes in the amount of white space')),
3940 _('ignore changes in the amount of white space')),
3937 ('B', 'ignore-blank-lines', None,
3941 ('B', 'ignore-blank-lines', None,
3938 _('ignore changes whose lines are all blank')),
3942 _('ignore changes whose lines are all blank')),
3939 ('U', 'unified', '',
3943 ('U', 'unified', '',
3940 _('number of lines of context to show'), _('NUM')),
3944 _('number of lines of context to show'), _('NUM')),
3941 ('', 'stat', None, _('output diffstat-style summary of changes')),
3945 ('', 'stat', None, _('output diffstat-style summary of changes')),
3942 ]
3946 ]
3943
3947
3944 similarityopts = [
3948 similarityopts = [
3945 ('s', 'similarity', '',
3949 ('s', 'similarity', '',
3946 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3950 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3947 ]
3951 ]
3948
3952
3949 table = {
3953 table = {
3950 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3954 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3951 "addremove":
3955 "addremove":
3952 (addremove, similarityopts + walkopts + dryrunopts,
3956 (addremove, similarityopts + walkopts + dryrunopts,
3953 _('[OPTION]... [FILE]...')),
3957 _('[OPTION]... [FILE]...')),
3954 "^annotate|blame":
3958 "^annotate|blame":
3955 (annotate,
3959 (annotate,
3956 [('r', 'rev', '',
3960 [('r', 'rev', '',
3957 _('annotate the specified revision'), _('REV')),
3961 _('annotate the specified revision'), _('REV')),
3958 ('', 'follow', None,
3962 ('', 'follow', None,
3959 _('follow copies/renames and list the filename (DEPRECATED)')),
3963 _('follow copies/renames and list the filename (DEPRECATED)')),
3960 ('', 'no-follow', None, _("don't follow copies and renames")),
3964 ('', 'no-follow', None, _("don't follow copies and renames")),
3961 ('a', 'text', None, _('treat all files as text')),
3965 ('a', 'text', None, _('treat all files as text')),
3962 ('u', 'user', None, _('list the author (long with -v)')),
3966 ('u', 'user', None, _('list the author (long with -v)')),
3963 ('f', 'file', None, _('list the filename')),
3967 ('f', 'file', None, _('list the filename')),
3964 ('d', 'date', None, _('list the date (short with -q)')),
3968 ('d', 'date', None, _('list the date (short with -q)')),
3965 ('n', 'number', None, _('list the revision number (default)')),
3969 ('n', 'number', None, _('list the revision number (default)')),
3966 ('c', 'changeset', None, _('list the changeset')),
3970 ('c', 'changeset', None, _('list the changeset')),
3967 ('l', 'line-number', None,
3971 ('l', 'line-number', None,
3968 _('show line number at the first appearance'))
3972 _('show line number at the first appearance'))
3969 ] + walkopts,
3973 ] + walkopts,
3970 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3974 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3971 "archive":
3975 "archive":
3972 (archive,
3976 (archive,
3973 [('', 'no-decode', None, _('do not pass files through decoders')),
3977 [('', 'no-decode', None, _('do not pass files through decoders')),
3974 ('p', 'prefix', '',
3978 ('p', 'prefix', '',
3975 _('directory prefix for files in archive'), _('PREFIX')),
3979 _('directory prefix for files in archive'), _('PREFIX')),
3976 ('r', 'rev', '',
3980 ('r', 'rev', '',
3977 _('revision to distribute'), _('REV')),
3981 _('revision to distribute'), _('REV')),
3978 ('t', 'type', '',
3982 ('t', 'type', '',
3979 _('type of distribution to create'), _('TYPE')),
3983 _('type of distribution to create'), _('TYPE')),
3980 ] + walkopts,
3984 ] + walkopts,
3981 _('[OPTION]... DEST')),
3985 _('[OPTION]... DEST')),
3982 "backout":
3986 "backout":
3983 (backout,
3987 (backout,
3984 [('', 'merge', None,
3988 [('', 'merge', None,
3985 _('merge with old dirstate parent after backout')),
3989 _('merge with old dirstate parent after backout')),
3986 ('', 'parent', '',
3990 ('', 'parent', '',
3987 _('parent to choose when backing out merge'), _('REV')),
3991 _('parent to choose when backing out merge'), _('REV')),
3988 ('r', 'rev', '',
3992 ('r', 'rev', '',
3989 _('revision to backout'), _('REV')),
3993 _('revision to backout'), _('REV')),
3990 ] + walkopts + commitopts + commitopts2,
3994 ] + walkopts + commitopts + commitopts2,
3991 _('[OPTION]... [-r] REV')),
3995 _('[OPTION]... [-r] REV')),
3992 "bisect":
3996 "bisect":
3993 (bisect,
3997 (bisect,
3994 [('r', 'reset', False, _('reset bisect state')),
3998 [('r', 'reset', False, _('reset bisect state')),
3995 ('g', 'good', False, _('mark changeset good')),
3999 ('g', 'good', False, _('mark changeset good')),
3996 ('b', 'bad', False, _('mark changeset bad')),
4000 ('b', 'bad', False, _('mark changeset bad')),
3997 ('s', 'skip', False, _('skip testing changeset')),
4001 ('s', 'skip', False, _('skip testing changeset')),
3998 ('c', 'command', '',
4002 ('c', 'command', '',
3999 _('use command to check changeset state'), _('CMD')),
4003 _('use command to check changeset state'), _('CMD')),
4000 ('U', 'noupdate', False, _('do not update to target'))],
4004 ('U', 'noupdate', False, _('do not update to target'))],
4001 _("[-gbsr] [-U] [-c CMD] [REV]")),
4005 _("[-gbsr] [-U] [-c CMD] [REV]")),
4002 "branch":
4006 "branch":
4003 (branch,
4007 (branch,
4004 [('f', 'force', None,
4008 [('f', 'force', None,
4005 _('set branch name even if it shadows an existing branch')),
4009 _('set branch name even if it shadows an existing branch')),
4006 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4010 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4007 _('[-fC] [NAME]')),
4011 _('[-fC] [NAME]')),
4008 "branches":
4012 "branches":
4009 (branches,
4013 (branches,
4010 [('a', 'active', False,
4014 [('a', 'active', False,
4011 _('show only branches that have unmerged heads')),
4015 _('show only branches that have unmerged heads')),
4012 ('c', 'closed', False,
4016 ('c', 'closed', False,
4013 _('show normal and closed branches'))],
4017 _('show normal and closed branches'))],
4014 _('[-ac]')),
4018 _('[-ac]')),
4015 "bundle":
4019 "bundle":
4016 (bundle,
4020 (bundle,
4017 [('f', 'force', None,
4021 [('f', 'force', None,
4018 _('run even when the destination is unrelated')),
4022 _('run even when the destination is unrelated')),
4019 ('r', 'rev', [],
4023 ('r', 'rev', [],
4020 _('a changeset intended to be added to the destination'),
4024 _('a changeset intended to be added to the destination'),
4021 _('REV')),
4025 _('REV')),
4022 ('b', 'branch', [],
4026 ('b', 'branch', [],
4023 _('a specific branch you would like to bundle'),
4027 _('a specific branch you would like to bundle'),
4024 _('BRANCH')),
4028 _('BRANCH')),
4025 ('', 'base', [],
4029 ('', 'base', [],
4026 _('a base changeset assumed to be available at the destination'),
4030 _('a base changeset assumed to be available at the destination'),
4027 _('REV')),
4031 _('REV')),
4028 ('a', 'all', None, _('bundle all changesets in the repository')),
4032 ('a', 'all', None, _('bundle all changesets in the repository')),
4029 ('t', 'type', 'bzip2',
4033 ('t', 'type', 'bzip2',
4030 _('bundle compression type to use'), _('TYPE')),
4034 _('bundle compression type to use'), _('TYPE')),
4031 ] + remoteopts,
4035 ] + remoteopts,
4032 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4036 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4033 "cat":
4037 "cat":
4034 (cat,
4038 (cat,
4035 [('o', 'output', '',
4039 [('o', 'output', '',
4036 _('print output to file with formatted name'), _('FORMAT')),
4040 _('print output to file with formatted name'), _('FORMAT')),
4037 ('r', 'rev', '',
4041 ('r', 'rev', '',
4038 _('print the given revision'), _('REV')),
4042 _('print the given revision'), _('REV')),
4039 ('', 'decode', None, _('apply any matching decode filter')),
4043 ('', 'decode', None, _('apply any matching decode filter')),
4040 ] + walkopts,
4044 ] + walkopts,
4041 _('[OPTION]... FILE...')),
4045 _('[OPTION]... FILE...')),
4042 "^clone":
4046 "^clone":
4043 (clone,
4047 (clone,
4044 [('U', 'noupdate', None,
4048 [('U', 'noupdate', None,
4045 _('the clone will include an empty working copy (only a repository)')),
4049 _('the clone will include an empty working copy (only a repository)')),
4046 ('u', 'updaterev', '',
4050 ('u', 'updaterev', '',
4047 _('revision, tag or branch to check out'), _('REV')),
4051 _('revision, tag or branch to check out'), _('REV')),
4048 ('r', 'rev', [],
4052 ('r', 'rev', [],
4049 _('include the specified changeset'), _('REV')),
4053 _('include the specified changeset'), _('REV')),
4050 ('b', 'branch', [],
4054 ('b', 'branch', [],
4051 _('clone only the specified branch'), _('BRANCH')),
4055 _('clone only the specified branch'), _('BRANCH')),
4052 ('', 'pull', None, _('use pull protocol to copy metadata')),
4056 ('', 'pull', None, _('use pull protocol to copy metadata')),
4053 ('', 'uncompressed', None,
4057 ('', 'uncompressed', None,
4054 _('use uncompressed transfer (fast over LAN)')),
4058 _('use uncompressed transfer (fast over LAN)')),
4055 ] + remoteopts,
4059 ] + remoteopts,
4056 _('[OPTION]... SOURCE [DEST]')),
4060 _('[OPTION]... SOURCE [DEST]')),
4057 "^commit|ci":
4061 "^commit|ci":
4058 (commit,
4062 (commit,
4059 [('A', 'addremove', None,
4063 [('A', 'addremove', None,
4060 _('mark new/missing files as added/removed before committing')),
4064 _('mark new/missing files as added/removed before committing')),
4061 ('', 'close-branch', None,
4065 ('', 'close-branch', None,
4062 _('mark a branch as closed, hiding it from the branch list')),
4066 _('mark a branch as closed, hiding it from the branch list')),
4063 ] + walkopts + commitopts + commitopts2,
4067 ] + walkopts + commitopts + commitopts2,
4064 _('[OPTION]... [FILE]...')),
4068 _('[OPTION]... [FILE]...')),
4065 "copy|cp":
4069 "copy|cp":
4066 (copy,
4070 (copy,
4067 [('A', 'after', None, _('record a copy that has already occurred')),
4071 [('A', 'after', None, _('record a copy that has already occurred')),
4068 ('f', 'force', None,
4072 ('f', 'force', None,
4069 _('forcibly copy over an existing managed file')),
4073 _('forcibly copy over an existing managed file')),
4070 ] + walkopts + dryrunopts,
4074 ] + walkopts + dryrunopts,
4071 _('[OPTION]... [SOURCE]... DEST')),
4075 _('[OPTION]... [SOURCE]... DEST')),
4072 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4076 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4073 "debugbuilddag":
4077 "debugbuilddag":
4074 (debugbuilddag,
4078 (debugbuilddag,
4075 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4079 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4076 ('a', 'appended-file', None, _('add single file all revs append to')),
4080 ('a', 'appended-file', None, _('add single file all revs append to')),
4077 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4081 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4078 ('n', 'new-file', None, _('add new file at each rev')),
4082 ('n', 'new-file', None, _('add new file at each rev')),
4079 ],
4083 ],
4080 _('[OPTION]... TEXT')),
4084 _('[OPTION]... TEXT')),
4081 "debugcheckstate": (debugcheckstate, [], ''),
4085 "debugcheckstate": (debugcheckstate, [], ''),
4082 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4086 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4083 "debugcomplete":
4087 "debugcomplete":
4084 (debugcomplete,
4088 (debugcomplete,
4085 [('o', 'options', None, _('show the command options'))],
4089 [('o', 'options', None, _('show the command options'))],
4086 _('[-o] CMD')),
4090 _('[-o] CMD')),
4087 "debugdag":
4091 "debugdag":
4088 (debugdag,
4092 (debugdag,
4089 [('t', 'tags', None, _('use tags as labels')),
4093 [('t', 'tags', None, _('use tags as labels')),
4090 ('b', 'branches', None, _('annotate with branch names')),
4094 ('b', 'branches', None, _('annotate with branch names')),
4091 ('', 'dots', None, _('use dots for runs')),
4095 ('', 'dots', None, _('use dots for runs')),
4092 ('s', 'spaces', None, _('separate elements by spaces')),
4096 ('s', 'spaces', None, _('separate elements by spaces')),
4093 ],
4097 ],
4094 _('[OPTION]... [FILE [REV]...]')),
4098 _('[OPTION]... [FILE [REV]...]')),
4095 "debugdate":
4099 "debugdate":
4096 (debugdate,
4100 (debugdate,
4097 [('e', 'extended', None, _('try extended date formats'))],
4101 [('e', 'extended', None, _('try extended date formats'))],
4098 _('[-e] DATE [RANGE]')),
4102 _('[-e] DATE [RANGE]')),
4099 "debugdata": (debugdata, [], _('FILE REV')),
4103 "debugdata": (debugdata, [], _('FILE REV')),
4100 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4104 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4101 "debugindex": (debugindex, [], _('FILE')),
4105 "debugindex": (debugindex, [], _('FILE')),
4102 "debugindexdot": (debugindexdot, [], _('FILE')),
4106 "debugindexdot": (debugindexdot, [], _('FILE')),
4103 "debuginstall": (debuginstall, [], ''),
4107 "debuginstall": (debuginstall, [], ''),
4104 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4108 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4105 "debugrebuildstate":
4109 "debugrebuildstate":
4106 (debugrebuildstate,
4110 (debugrebuildstate,
4107 [('r', 'rev', '',
4111 [('r', 'rev', '',
4108 _('revision to rebuild to'), _('REV'))],
4112 _('revision to rebuild to'), _('REV'))],
4109 _('[-r REV] [REV]')),
4113 _('[-r REV] [REV]')),
4110 "debugrename":
4114 "debugrename":
4111 (debugrename,
4115 (debugrename,
4112 [('r', 'rev', '',
4116 [('r', 'rev', '',
4113 _('revision to debug'), _('REV'))],
4117 _('revision to debug'), _('REV'))],
4114 _('[-r REV] FILE')),
4118 _('[-r REV] FILE')),
4115 "debugrevspec":
4119 "debugrevspec":
4116 (debugrevspec, [], ('REVSPEC')),
4120 (debugrevspec, [], ('REVSPEC')),
4117 "debugsetparents":
4121 "debugsetparents":
4118 (debugsetparents, [], _('REV1 [REV2]')),
4122 (debugsetparents, [], _('REV1 [REV2]')),
4119 "debugstate":
4123 "debugstate":
4120 (debugstate,
4124 (debugstate,
4121 [('', 'nodates', None, _('do not display the saved mtime'))],
4125 [('', 'nodates', None, _('do not display the saved mtime'))],
4122 _('[OPTION]...')),
4126 _('[OPTION]...')),
4123 "debugsub":
4127 "debugsub":
4124 (debugsub,
4128 (debugsub,
4125 [('r', 'rev', '',
4129 [('r', 'rev', '',
4126 _('revision to check'), _('REV'))],
4130 _('revision to check'), _('REV'))],
4127 _('[-r REV] [REV]')),
4131 _('[-r REV] [REV]')),
4128 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4132 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4129 "^diff":
4133 "^diff":
4130 (diff,
4134 (diff,
4131 [('r', 'rev', [],
4135 [('r', 'rev', [],
4132 _('revision'), _('REV')),
4136 _('revision'), _('REV')),
4133 ('c', 'change', '',
4137 ('c', 'change', '',
4134 _('change made by revision'), _('REV'))
4138 _('change made by revision'), _('REV'))
4135 ] + diffopts + diffopts2 + walkopts,
4139 ] + diffopts + diffopts2 + walkopts,
4136 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4140 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4137 "^export":
4141 "^export":
4138 (export,
4142 (export,
4139 [('o', 'output', '',
4143 [('o', 'output', '',
4140 _('print output to file with formatted name'), _('FORMAT')),
4144 _('print output to file with formatted name'), _('FORMAT')),
4141 ('', 'switch-parent', None, _('diff against the second parent')),
4145 ('', 'switch-parent', None, _('diff against the second parent')),
4142 ('r', 'rev', [],
4146 ('r', 'rev', [],
4143 _('revisions to export'), _('REV')),
4147 _('revisions to export'), _('REV')),
4144 ] + diffopts,
4148 ] + diffopts,
4145 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4149 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4146 "^forget":
4150 "^forget":
4147 (forget,
4151 (forget,
4148 [] + walkopts,
4152 [] + walkopts,
4149 _('[OPTION]... FILE...')),
4153 _('[OPTION]... FILE...')),
4150 "grep":
4154 "grep":
4151 (grep,
4155 (grep,
4152 [('0', 'print0', None, _('end fields with NUL')),
4156 [('0', 'print0', None, _('end fields with NUL')),
4153 ('', 'all', None, _('print all revisions that match')),
4157 ('', 'all', None, _('print all revisions that match')),
4154 ('f', 'follow', None,
4158 ('f', 'follow', None,
4155 _('follow changeset history,'
4159 _('follow changeset history,'
4156 ' or file history across copies and renames')),
4160 ' or file history across copies and renames')),
4157 ('i', 'ignore-case', None, _('ignore case when matching')),
4161 ('i', 'ignore-case', None, _('ignore case when matching')),
4158 ('l', 'files-with-matches', None,
4162 ('l', 'files-with-matches', None,
4159 _('print only filenames and revisions that match')),
4163 _('print only filenames and revisions that match')),
4160 ('n', 'line-number', None, _('print matching line numbers')),
4164 ('n', 'line-number', None, _('print matching line numbers')),
4161 ('r', 'rev', [],
4165 ('r', 'rev', [],
4162 _('only search files changed within revision range'), _('REV')),
4166 _('only search files changed within revision range'), _('REV')),
4163 ('u', 'user', None, _('list the author (long with -v)')),
4167 ('u', 'user', None, _('list the author (long with -v)')),
4164 ('d', 'date', None, _('list the date (short with -q)')),
4168 ('d', 'date', None, _('list the date (short with -q)')),
4165 ] + walkopts,
4169 ] + walkopts,
4166 _('[OPTION]... PATTERN [FILE]...')),
4170 _('[OPTION]... PATTERN [FILE]...')),
4167 "heads":
4171 "heads":
4168 (heads,
4172 (heads,
4169 [('r', 'rev', '',
4173 [('r', 'rev', '',
4170 _('show only heads which are descendants of REV'), _('REV')),
4174 _('show only heads which are descendants of REV'), _('REV')),
4171 ('t', 'topo', False, _('show topological heads only')),
4175 ('t', 'topo', False, _('show topological heads only')),
4172 ('a', 'active', False,
4176 ('a', 'active', False,
4173 _('show active branchheads only [DEPRECATED]')),
4177 _('show active branchheads only [DEPRECATED]')),
4174 ('c', 'closed', False,
4178 ('c', 'closed', False,
4175 _('show normal and closed branch heads')),
4179 _('show normal and closed branch heads')),
4176 ] + templateopts,
4180 ] + templateopts,
4177 _('[-ac] [-r REV] [REV]...')),
4181 _('[-ac] [-r REV] [REV]...')),
4178 "help": (help_, [], _('[TOPIC]')),
4182 "help": (help_, [], _('[TOPIC]')),
4179 "identify|id":
4183 "identify|id":
4180 (identify,
4184 (identify,
4181 [('r', 'rev', '',
4185 [('r', 'rev', '',
4182 _('identify the specified revision'), _('REV')),
4186 _('identify the specified revision'), _('REV')),
4183 ('n', 'num', None, _('show local revision number')),
4187 ('n', 'num', None, _('show local revision number')),
4184 ('i', 'id', None, _('show global revision id')),
4188 ('i', 'id', None, _('show global revision id')),
4185 ('b', 'branch', None, _('show branch')),
4189 ('b', 'branch', None, _('show branch')),
4186 ('t', 'tags', None, _('show tags'))],
4190 ('t', 'tags', None, _('show tags'))],
4187 _('[-nibt] [-r REV] [SOURCE]')),
4191 _('[-nibt] [-r REV] [SOURCE]')),
4188 "import|patch":
4192 "import|patch":
4189 (import_,
4193 (import_,
4190 [('p', 'strip', 1,
4194 [('p', 'strip', 1,
4191 _('directory strip option for patch. This has the same '
4195 _('directory strip option for patch. This has the same '
4192 'meaning as the corresponding patch option'),
4196 'meaning as the corresponding patch option'),
4193 _('NUM')),
4197 _('NUM')),
4194 ('b', 'base', '',
4198 ('b', 'base', '',
4195 _('base path'), _('PATH')),
4199 _('base path'), _('PATH')),
4196 ('f', 'force', None,
4200 ('f', 'force', None,
4197 _('skip check for outstanding uncommitted changes')),
4201 _('skip check for outstanding uncommitted changes')),
4198 ('', 'no-commit', None,
4202 ('', 'no-commit', None,
4199 _("don't commit, just update the working directory")),
4203 _("don't commit, just update the working directory")),
4200 ('', 'exact', None,
4204 ('', 'exact', None,
4201 _('apply patch to the nodes from which it was generated')),
4205 _('apply patch to the nodes from which it was generated')),
4202 ('', 'import-branch', None,
4206 ('', 'import-branch', None,
4203 _('use any branch information in patch (implied by --exact)'))] +
4207 _('use any branch information in patch (implied by --exact)'))] +
4204 commitopts + commitopts2 + similarityopts,
4208 commitopts + commitopts2 + similarityopts,
4205 _('[OPTION]... PATCH...')),
4209 _('[OPTION]... PATCH...')),
4206 "incoming|in":
4210 "incoming|in":
4207 (incoming,
4211 (incoming,
4208 [('f', 'force', None,
4212 [('f', 'force', None,
4209 _('run even if remote repository is unrelated')),
4213 _('run even if remote repository is unrelated')),
4210 ('n', 'newest-first', None, _('show newest record first')),
4214 ('n', 'newest-first', None, _('show newest record first')),
4211 ('', 'bundle', '',
4215 ('', 'bundle', '',
4212 _('file to store the bundles into'), _('FILE')),
4216 _('file to store the bundles into'), _('FILE')),
4213 ('r', 'rev', [],
4217 ('r', 'rev', [],
4214 _('a remote changeset intended to be added'), _('REV')),
4218 _('a remote changeset intended to be added'), _('REV')),
4215 ('b', 'branch', [],
4219 ('b', 'branch', [],
4216 _('a specific branch you would like to pull'), _('BRANCH')),
4220 _('a specific branch you would like to pull'), _('BRANCH')),
4217 ] + logopts + remoteopts,
4221 ] + logopts + remoteopts,
4218 _('[-p] [-n] [-M] [-f] [-r REV]...'
4222 _('[-p] [-n] [-M] [-f] [-r REV]...'
4219 ' [--bundle FILENAME] [SOURCE]')),
4223 ' [--bundle FILENAME] [SOURCE]')),
4220 "^init":
4224 "^init":
4221 (init,
4225 (init,
4222 remoteopts,
4226 remoteopts,
4223 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4227 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4224 "locate":
4228 "locate":
4225 (locate,
4229 (locate,
4226 [('r', 'rev', '',
4230 [('r', 'rev', '',
4227 _('search the repository as it is in REV'), _('REV')),
4231 _('search the repository as it is in REV'), _('REV')),
4228 ('0', 'print0', None,
4232 ('0', 'print0', None,
4229 _('end filenames with NUL, for use with xargs')),
4233 _('end filenames with NUL, for use with xargs')),
4230 ('f', 'fullpath', None,
4234 ('f', 'fullpath', None,
4231 _('print complete paths from the filesystem root')),
4235 _('print complete paths from the filesystem root')),
4232 ] + walkopts,
4236 ] + walkopts,
4233 _('[OPTION]... [PATTERN]...')),
4237 _('[OPTION]... [PATTERN]...')),
4234 "^log|history":
4238 "^log|history":
4235 (log,
4239 (log,
4236 [('f', 'follow', None,
4240 [('f', 'follow', None,
4237 _('follow changeset history,'
4241 _('follow changeset history,'
4238 ' or file history across copies and renames')),
4242 ' or file history across copies and renames')),
4239 ('', 'follow-first', None,
4243 ('', 'follow-first', None,
4240 _('only follow the first parent of merge changesets')),
4244 _('only follow the first parent of merge changesets')),
4241 ('d', 'date', '',
4245 ('d', 'date', '',
4242 _('show revisions matching date spec'), _('DATE')),
4246 _('show revisions matching date spec'), _('DATE')),
4243 ('C', 'copies', None, _('show copied files')),
4247 ('C', 'copies', None, _('show copied files')),
4244 ('k', 'keyword', [],
4248 ('k', 'keyword', [],
4245 _('do case-insensitive search for a given text'), _('TEXT')),
4249 _('do case-insensitive search for a given text'), _('TEXT')),
4246 ('r', 'rev', [],
4250 ('r', 'rev', [],
4247 _('show the specified revision or range'), _('REV')),
4251 _('show the specified revision or range'), _('REV')),
4248 ('', 'removed', None, _('include revisions where files were removed')),
4252 ('', 'removed', None, _('include revisions where files were removed')),
4249 ('m', 'only-merges', None, _('show only merges')),
4253 ('m', 'only-merges', None, _('show only merges')),
4250 ('u', 'user', [],
4254 ('u', 'user', [],
4251 _('revisions committed by user'), _('USER')),
4255 _('revisions committed by user'), _('USER')),
4252 ('', 'only-branch', [],
4256 ('', 'only-branch', [],
4253 _('show only changesets within the given named branch (DEPRECATED)'),
4257 _('show only changesets within the given named branch (DEPRECATED)'),
4254 _('BRANCH')),
4258 _('BRANCH')),
4255 ('b', 'branch', [],
4259 ('b', 'branch', [],
4256 _('show changesets within the given named branch'), _('BRANCH')),
4260 _('show changesets within the given named branch'), _('BRANCH')),
4257 ('P', 'prune', [],
4261 ('P', 'prune', [],
4258 _('do not display revision or any of its ancestors'), _('REV')),
4262 _('do not display revision or any of its ancestors'), _('REV')),
4259 ] + logopts + walkopts,
4263 ] + logopts + walkopts,
4260 _('[OPTION]... [FILE]')),
4264 _('[OPTION]... [FILE]')),
4261 "manifest":
4265 "manifest":
4262 (manifest,
4266 (manifest,
4263 [('r', 'rev', '',
4267 [('r', 'rev', '',
4264 _('revision to display'), _('REV'))],
4268 _('revision to display'), _('REV'))],
4265 _('[-r REV]')),
4269 _('[-r REV]')),
4266 "^merge":
4270 "^merge":
4267 (merge,
4271 (merge,
4268 [('f', 'force', None, _('force a merge with outstanding changes')),
4272 [('f', 'force', None, _('force a merge with outstanding changes')),
4269 ('r', 'rev', '',
4273 ('r', 'rev', '',
4270 _('revision to merge'), _('REV')),
4274 _('revision to merge'), _('REV')),
4271 ('P', 'preview', None,
4275 ('P', 'preview', None,
4272 _('review revisions to merge (no merge is performed)'))],
4276 _('review revisions to merge (no merge is performed)'))],
4273 _('[-P] [-f] [[-r] REV]')),
4277 _('[-P] [-f] [[-r] REV]')),
4274 "outgoing|out":
4278 "outgoing|out":
4275 (outgoing,
4279 (outgoing,
4276 [('f', 'force', None,
4280 [('f', 'force', None,
4277 _('run even when the destination is unrelated')),
4281 _('run even when the destination is unrelated')),
4278 ('r', 'rev', [],
4282 ('r', 'rev', [],
4279 _('a changeset intended to be included in the destination'),
4283 _('a changeset intended to be included in the destination'),
4280 _('REV')),
4284 _('REV')),
4281 ('n', 'newest-first', None, _('show newest record first')),
4285 ('n', 'newest-first', None, _('show newest record first')),
4282 ('b', 'branch', [],
4286 ('b', 'branch', [],
4283 _('a specific branch you would like to push'), _('BRANCH')),
4287 _('a specific branch you would like to push'), _('BRANCH')),
4284 ] + logopts + remoteopts,
4288 ] + logopts + remoteopts,
4285 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4289 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4286 "parents":
4290 "parents":
4287 (parents,
4291 (parents,
4288 [('r', 'rev', '',
4292 [('r', 'rev', '',
4289 _('show parents of the specified revision'), _('REV')),
4293 _('show parents of the specified revision'), _('REV')),
4290 ] + templateopts,
4294 ] + templateopts,
4291 _('[-r REV] [FILE]')),
4295 _('[-r REV] [FILE]')),
4292 "paths": (paths, [], _('[NAME]')),
4296 "paths": (paths, [], _('[NAME]')),
4293 "^pull":
4297 "^pull":
4294 (pull,
4298 (pull,
4295 [('u', 'update', None,
4299 [('u', 'update', None,
4296 _('update to new branch head if changesets were pulled')),
4300 _('update to new branch head if changesets were pulled')),
4297 ('f', 'force', None,
4301 ('f', 'force', None,
4298 _('run even when remote repository is unrelated')),
4302 _('run even when remote repository is unrelated')),
4299 ('r', 'rev', [],
4303 ('r', 'rev', [],
4300 _('a remote changeset intended to be added'), _('REV')),
4304 _('a remote changeset intended to be added'), _('REV')),
4301 ('b', 'branch', [],
4305 ('b', 'branch', [],
4302 _('a specific branch you would like to pull'), _('BRANCH')),
4306 _('a specific branch you would like to pull'), _('BRANCH')),
4303 ] + remoteopts,
4307 ] + remoteopts,
4304 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4308 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4305 "^push":
4309 "^push":
4306 (push,
4310 (push,
4307 [('f', 'force', None, _('force push')),
4311 [('f', 'force', None, _('force push')),
4308 ('r', 'rev', [],
4312 ('r', 'rev', [],
4309 _('a changeset intended to be included in the destination'),
4313 _('a changeset intended to be included in the destination'),
4310 _('REV')),
4314 _('REV')),
4311 ('b', 'branch', [],
4315 ('b', 'branch', [],
4312 _('a specific branch you would like to push'), _('BRANCH')),
4316 _('a specific branch you would like to push'), _('BRANCH')),
4313 ('', 'new-branch', False, _('allow pushing a new branch')),
4317 ('', 'new-branch', False, _('allow pushing a new branch')),
4314 ] + remoteopts,
4318 ] + remoteopts,
4315 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4319 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4316 "recover": (recover, []),
4320 "recover": (recover, []),
4317 "^remove|rm":
4321 "^remove|rm":
4318 (remove,
4322 (remove,
4319 [('A', 'after', None, _('record delete for missing files')),
4323 [('A', 'after', None, _('record delete for missing files')),
4320 ('f', 'force', None,
4324 ('f', 'force', None,
4321 _('remove (and delete) file even if added or modified')),
4325 _('remove (and delete) file even if added or modified')),
4322 ] + walkopts,
4326 ] + walkopts,
4323 _('[OPTION]... FILE...')),
4327 _('[OPTION]... FILE...')),
4324 "rename|mv":
4328 "rename|mv":
4325 (rename,
4329 (rename,
4326 [('A', 'after', None, _('record a rename that has already occurred')),
4330 [('A', 'after', None, _('record a rename that has already occurred')),
4327 ('f', 'force', None,
4331 ('f', 'force', None,
4328 _('forcibly copy over an existing managed file')),
4332 _('forcibly copy over an existing managed file')),
4329 ] + walkopts + dryrunopts,
4333 ] + walkopts + dryrunopts,
4330 _('[OPTION]... SOURCE... DEST')),
4334 _('[OPTION]... SOURCE... DEST')),
4331 "resolve":
4335 "resolve":
4332 (resolve,
4336 (resolve,
4333 [('a', 'all', None, _('select all unresolved files')),
4337 [('a', 'all', None, _('select all unresolved files')),
4334 ('l', 'list', None, _('list state of files needing merge')),
4338 ('l', 'list', None, _('list state of files needing merge')),
4335 ('m', 'mark', None, _('mark files as resolved')),
4339 ('m', 'mark', None, _('mark files as resolved')),
4336 ('u', 'unmark', None, _('unmark files as resolved')),
4340 ('u', 'unmark', None, _('unmark files as resolved')),
4337 ('n', 'no-status', None, _('hide status prefix'))]
4341 ('n', 'no-status', None, _('hide status prefix'))]
4338 + walkopts,
4342 + walkopts,
4339 _('[OPTION]... [FILE]...')),
4343 _('[OPTION]... [FILE]...')),
4340 "revert":
4344 "revert":
4341 (revert,
4345 (revert,
4342 [('a', 'all', None, _('revert all changes when no arguments given')),
4346 [('a', 'all', None, _('revert all changes when no arguments given')),
4343 ('d', 'date', '',
4347 ('d', 'date', '',
4344 _('tipmost revision matching date'), _('DATE')),
4348 _('tipmost revision matching date'), _('DATE')),
4345 ('r', 'rev', '',
4349 ('r', 'rev', '',
4346 _('revert to the specified revision'), _('REV')),
4350 _('revert to the specified revision'), _('REV')),
4347 ('', 'no-backup', None, _('do not save backup copies of files')),
4351 ('', 'no-backup', None, _('do not save backup copies of files')),
4348 ] + walkopts + dryrunopts,
4352 ] + walkopts + dryrunopts,
4349 _('[OPTION]... [-r REV] [NAME]...')),
4353 _('[OPTION]... [-r REV] [NAME]...')),
4350 "rollback": (rollback, dryrunopts),
4354 "rollback": (rollback, dryrunopts),
4351 "root": (root, []),
4355 "root": (root, []),
4352 "^serve":
4356 "^serve":
4353 (serve,
4357 (serve,
4354 [('A', 'accesslog', '',
4358 [('A', 'accesslog', '',
4355 _('name of access log file to write to'), _('FILE')),
4359 _('name of access log file to write to'), _('FILE')),
4356 ('d', 'daemon', None, _('run server in background')),
4360 ('d', 'daemon', None, _('run server in background')),
4357 ('', 'daemon-pipefds', '',
4361 ('', 'daemon-pipefds', '',
4358 _('used internally by daemon mode'), _('NUM')),
4362 _('used internally by daemon mode'), _('NUM')),
4359 ('E', 'errorlog', '',
4363 ('E', 'errorlog', '',
4360 _('name of error log file to write to'), _('FILE')),
4364 _('name of error log file to write to'), _('FILE')),
4361 # use string type, then we can check if something was passed
4365 # use string type, then we can check if something was passed
4362 ('p', 'port', '',
4366 ('p', 'port', '',
4363 _('port to listen on (default: 8000)'), _('PORT')),
4367 _('port to listen on (default: 8000)'), _('PORT')),
4364 ('a', 'address', '',
4368 ('a', 'address', '',
4365 _('address to listen on (default: all interfaces)'), _('ADDR')),
4369 _('address to listen on (default: all interfaces)'), _('ADDR')),
4366 ('', 'prefix', '',
4370 ('', 'prefix', '',
4367 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4371 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4368 ('n', 'name', '',
4372 ('n', 'name', '',
4369 _('name to show in web pages (default: working directory)'),
4373 _('name to show in web pages (default: working directory)'),
4370 _('NAME')),
4374 _('NAME')),
4371 ('', 'web-conf', '',
4375 ('', 'web-conf', '',
4372 _('name of the hgweb config file (serve more than one repository)'),
4376 _('name of the hgweb config file (serve more than one repository)'),
4373 _('FILE')),
4377 _('FILE')),
4374 ('', 'webdir-conf', '',
4378 ('', 'webdir-conf', '',
4375 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4379 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4376 ('', 'pid-file', '',
4380 ('', 'pid-file', '',
4377 _('name of file to write process ID to'), _('FILE')),
4381 _('name of file to write process ID to'), _('FILE')),
4378 ('', 'stdio', None, _('for remote clients')),
4382 ('', 'stdio', None, _('for remote clients')),
4379 ('t', 'templates', '',
4383 ('t', 'templates', '',
4380 _('web templates to use'), _('TEMPLATE')),
4384 _('web templates to use'), _('TEMPLATE')),
4381 ('', 'style', '',
4385 ('', 'style', '',
4382 _('template style to use'), _('STYLE')),
4386 _('template style to use'), _('STYLE')),
4383 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4387 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4384 ('', 'certificate', '',
4388 ('', 'certificate', '',
4385 _('SSL certificate file'), _('FILE'))],
4389 _('SSL certificate file'), _('FILE'))],
4386 _('[OPTION]...')),
4390 _('[OPTION]...')),
4387 "showconfig|debugconfig":
4391 "showconfig|debugconfig":
4388 (showconfig,
4392 (showconfig,
4389 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4393 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4390 _('[-u] [NAME]...')),
4394 _('[-u] [NAME]...')),
4391 "^summary|sum":
4395 "^summary|sum":
4392 (summary,
4396 (summary,
4393 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4397 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4394 "^status|st":
4398 "^status|st":
4395 (status,
4399 (status,
4396 [('A', 'all', None, _('show status of all files')),
4400 [('A', 'all', None, _('show status of all files')),
4397 ('m', 'modified', None, _('show only modified files')),
4401 ('m', 'modified', None, _('show only modified files')),
4398 ('a', 'added', None, _('show only added files')),
4402 ('a', 'added', None, _('show only added files')),
4399 ('r', 'removed', None, _('show only removed files')),
4403 ('r', 'removed', None, _('show only removed files')),
4400 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4404 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4401 ('c', 'clean', None, _('show only files without changes')),
4405 ('c', 'clean', None, _('show only files without changes')),
4402 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4406 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4403 ('i', 'ignored', None, _('show only ignored files')),
4407 ('i', 'ignored', None, _('show only ignored files')),
4404 ('n', 'no-status', None, _('hide status prefix')),
4408 ('n', 'no-status', None, _('hide status prefix')),
4405 ('C', 'copies', None, _('show source of copied files')),
4409 ('C', 'copies', None, _('show source of copied files')),
4406 ('0', 'print0', None,
4410 ('0', 'print0', None,
4407 _('end filenames with NUL, for use with xargs')),
4411 _('end filenames with NUL, for use with xargs')),
4408 ('', 'rev', [],
4412 ('', 'rev', [],
4409 _('show difference from revision'), _('REV')),
4413 _('show difference from revision'), _('REV')),
4410 ('', 'change', '',
4414 ('', 'change', '',
4411 _('list the changed files of a revision'), _('REV')),
4415 _('list the changed files of a revision'), _('REV')),
4412 ] + walkopts,
4416 ] + walkopts,
4413 _('[OPTION]... [FILE]...')),
4417 _('[OPTION]... [FILE]...')),
4414 "tag":
4418 "tag":
4415 (tag,
4419 (tag,
4416 [('f', 'force', None, _('replace existing tag')),
4420 [('f', 'force', None, _('replace existing tag')),
4417 ('l', 'local', None, _('make the tag local')),
4421 ('l', 'local', None, _('make the tag local')),
4418 ('r', 'rev', '',
4422 ('r', 'rev', '',
4419 _('revision to tag'), _('REV')),
4423 _('revision to tag'), _('REV')),
4420 ('', 'remove', None, _('remove a tag')),
4424 ('', 'remove', None, _('remove a tag')),
4421 # -l/--local is already there, commitopts cannot be used
4425 # -l/--local is already there, commitopts cannot be used
4422 ('e', 'edit', None, _('edit commit message')),
4426 ('e', 'edit', None, _('edit commit message')),
4423 ('m', 'message', '',
4427 ('m', 'message', '',
4424 _('use <text> as commit message'), _('TEXT')),
4428 _('use <text> as commit message'), _('TEXT')),
4425 ] + commitopts2,
4429 ] + commitopts2,
4426 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4430 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4427 "tags": (tags, [], ''),
4431 "tags": (tags, [], ''),
4428 "tip":
4432 "tip":
4429 (tip,
4433 (tip,
4430 [('p', 'patch', None, _('show patch')),
4434 [('p', 'patch', None, _('show patch')),
4431 ('g', 'git', None, _('use git extended diff format')),
4435 ('g', 'git', None, _('use git extended diff format')),
4432 ] + templateopts,
4436 ] + templateopts,
4433 _('[-p] [-g]')),
4437 _('[-p] [-g]')),
4434 "unbundle":
4438 "unbundle":
4435 (unbundle,
4439 (unbundle,
4436 [('u', 'update', None,
4440 [('u', 'update', None,
4437 _('update to new branch head if changesets were unbundled'))],
4441 _('update to new branch head if changesets were unbundled'))],
4438 _('[-u] FILE...')),
4442 _('[-u] FILE...')),
4439 "^update|up|checkout|co":
4443 "^update|up|checkout|co":
4440 (update,
4444 (update,
4441 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4445 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4442 ('c', 'check', None, _('check for uncommitted changes')),
4446 ('c', 'check', None, _('check for uncommitted changes')),
4443 ('d', 'date', '',
4447 ('d', 'date', '',
4444 _('tipmost revision matching date'), _('DATE')),
4448 _('tipmost revision matching date'), _('DATE')),
4445 ('r', 'rev', '',
4449 ('r', 'rev', '',
4446 _('revision'), _('REV'))],
4450 _('revision'), _('REV'))],
4447 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4451 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4448 "verify": (verify, []),
4452 "verify": (verify, []),
4449 "version": (version_, []),
4453 "version": (version_, []),
4450 }
4454 }
4451
4455
4452 norepo = ("clone init version help debugcommands debugcomplete debugdata"
4456 norepo = ("clone init version help debugcommands debugcomplete debugdata"
4453 " debugindex debugindexdot debugdate debuginstall debugfsinfo"
4457 " debugindex debugindexdot debugdate debuginstall debugfsinfo"
4454 " debugpushkey")
4458 " debugpushkey")
4455 optionalrepo = ("identify paths serve showconfig debugancestor debugdag")
4459 optionalrepo = ("identify paths serve showconfig debugancestor debugdag")
General Comments 0
You need to be logged in to leave comments. Login now