##// END OF EJS Templates
imported patch rollback-help
Matt Mackall -
r5575:8788ff63 default
parent child Browse files
Show More
@@ -1,3175 +1,3172 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import os, re, sys, urllib
10 import os, re, sys, urllib
11 import hg, util, revlog, bundlerepo, extensions
11 import hg, util, revlog, bundlerepo, extensions
12 import difflib, patch, time, help, mdiff, tempfile
12 import difflib, patch, time, help, mdiff, tempfile
13 import errno, version, socket
13 import errno, version, socket
14 import archival, changegroup, cmdutil, hgweb.server, sshserver
14 import archival, changegroup, cmdutil, hgweb.server, sshserver
15
15
16 # Commands start here, listed alphabetically
16 # Commands start here, listed alphabetically
17
17
18 def add(ui, repo, *pats, **opts):
18 def add(ui, repo, *pats, **opts):
19 """add the specified files on the next commit
19 """add the specified files on the next commit
20
20
21 Schedule files to be version controlled and added to the repository.
21 Schedule files to be version controlled and added to the repository.
22
22
23 The files will be added to the repository at the next commit. To
23 The files will be added to the repository at the next commit. To
24 undo an add before that, see hg revert.
24 undo an add before that, see hg revert.
25
25
26 If no names are given, add all files in the repository.
26 If no names are given, add all files in the repository.
27 """
27 """
28
28
29 names = []
29 names = []
30 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
30 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
31 if exact:
31 if exact:
32 if ui.verbose:
32 if ui.verbose:
33 ui.status(_('adding %s\n') % rel)
33 ui.status(_('adding %s\n') % rel)
34 names.append(abs)
34 names.append(abs)
35 elif abs not in repo.dirstate:
35 elif abs not in repo.dirstate:
36 ui.status(_('adding %s\n') % rel)
36 ui.status(_('adding %s\n') % rel)
37 names.append(abs)
37 names.append(abs)
38 if not opts.get('dry_run'):
38 if not opts.get('dry_run'):
39 repo.add(names)
39 repo.add(names)
40
40
41 def addremove(ui, repo, *pats, **opts):
41 def addremove(ui, repo, *pats, **opts):
42 """add all new files, delete all missing files
42 """add all new files, delete all missing files
43
43
44 Add all new files and remove all missing files from the repository.
44 Add all new files and remove all missing files from the repository.
45
45
46 New files are ignored if they match any of the patterns in .hgignore. As
46 New files are ignored if they match any of the patterns in .hgignore. As
47 with add, these changes take effect at the next commit.
47 with add, these changes take effect at the next commit.
48
48
49 Use the -s option to detect renamed files. With a parameter > 0,
49 Use the -s option to detect renamed files. With a parameter > 0,
50 this compares every removed file with every added file and records
50 this compares every removed file with every added file and records
51 those similar enough as renames. This option takes a percentage
51 those similar enough as renames. This option takes a percentage
52 between 0 (disabled) and 100 (files must be identical) as its
52 between 0 (disabled) and 100 (files must be identical) as its
53 parameter. Detecting renamed files this way can be expensive.
53 parameter. Detecting renamed files this way can be expensive.
54 """
54 """
55 try:
55 try:
56 sim = float(opts.get('similarity') or 0)
56 sim = float(opts.get('similarity') or 0)
57 except ValueError:
57 except ValueError:
58 raise util.Abort(_('similarity must be a number'))
58 raise util.Abort(_('similarity must be a number'))
59 if sim < 0 or sim > 100:
59 if sim < 0 or sim > 100:
60 raise util.Abort(_('similarity must be between 0 and 100'))
60 raise util.Abort(_('similarity must be between 0 and 100'))
61 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
61 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
62
62
63 def annotate(ui, repo, *pats, **opts):
63 def annotate(ui, repo, *pats, **opts):
64 """show changeset information per file line
64 """show changeset information per file line
65
65
66 List changes in files, showing the revision id responsible for each line
66 List changes in files, showing the revision id responsible for each line
67
67
68 This command is useful to discover who did a change or when a change took
68 This command is useful to discover who did a change or when a change took
69 place.
69 place.
70
70
71 Without the -a option, annotate will avoid processing files it
71 Without the -a option, annotate will avoid processing files it
72 detects as binary. With -a, annotate will generate an annotation
72 detects as binary. With -a, annotate will generate an annotation
73 anyway, probably with undesirable results.
73 anyway, probably with undesirable results.
74 """
74 """
75 getdate = util.cachefunc(lambda x: util.datestr(x[0].date()))
75 getdate = util.cachefunc(lambda x: util.datestr(x[0].date()))
76
76
77 if not pats:
77 if not pats:
78 raise util.Abort(_('at least one file name or pattern required'))
78 raise util.Abort(_('at least one file name or pattern required'))
79
79
80 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
80 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
81 ('number', lambda x: str(x[0].rev())),
81 ('number', lambda x: str(x[0].rev())),
82 ('changeset', lambda x: short(x[0].node())),
82 ('changeset', lambda x: short(x[0].node())),
83 ('date', getdate),
83 ('date', getdate),
84 ('follow', lambda x: x[0].path()),
84 ('follow', lambda x: x[0].path()),
85 ]
85 ]
86
86
87 if (not opts['user'] and not opts['changeset'] and not opts['date']
87 if (not opts['user'] and not opts['changeset'] and not opts['date']
88 and not opts['follow']):
88 and not opts['follow']):
89 opts['number'] = 1
89 opts['number'] = 1
90
90
91 linenumber = opts.get('line_number') is not None
91 linenumber = opts.get('line_number') is not None
92 if (linenumber and (not opts['changeset']) and (not opts['number'])):
92 if (linenumber and (not opts['changeset']) and (not opts['number'])):
93 raise util.Abort(_('at least one of -n/-c is required for -l'))
93 raise util.Abort(_('at least one of -n/-c is required for -l'))
94
94
95 funcmap = [func for op, func in opmap if opts.get(op)]
95 funcmap = [func for op, func in opmap if opts.get(op)]
96 if linenumber:
96 if linenumber:
97 lastfunc = funcmap[-1]
97 lastfunc = funcmap[-1]
98 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
98 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
99
99
100 ctx = repo.changectx(opts['rev'])
100 ctx = repo.changectx(opts['rev'])
101
101
102 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
102 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
103 node=ctx.node()):
103 node=ctx.node()):
104 fctx = ctx.filectx(abs)
104 fctx = ctx.filectx(abs)
105 if not opts['text'] and util.binary(fctx.data()):
105 if not opts['text'] and util.binary(fctx.data()):
106 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
106 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
107 continue
107 continue
108
108
109 lines = fctx.annotate(follow=opts.get('follow'),
109 lines = fctx.annotate(follow=opts.get('follow'),
110 linenumber=linenumber)
110 linenumber=linenumber)
111 pieces = []
111 pieces = []
112
112
113 for f in funcmap:
113 for f in funcmap:
114 l = [f(n) for n, dummy in lines]
114 l = [f(n) for n, dummy in lines]
115 if l:
115 if l:
116 m = max(map(len, l))
116 m = max(map(len, l))
117 pieces.append(["%*s" % (m, x) for x in l])
117 pieces.append(["%*s" % (m, x) for x in l])
118
118
119 if pieces:
119 if pieces:
120 for p, l in zip(zip(*pieces), lines):
120 for p, l in zip(zip(*pieces), lines):
121 ui.write("%s: %s" % (" ".join(p), l[1]))
121 ui.write("%s: %s" % (" ".join(p), l[1]))
122
122
123 def archive(ui, repo, dest, **opts):
123 def archive(ui, repo, dest, **opts):
124 '''create unversioned archive of a repository revision
124 '''create unversioned archive of a repository revision
125
125
126 By default, the revision used is the parent of the working
126 By default, the revision used is the parent of the working
127 directory; use "-r" to specify a different revision.
127 directory; use "-r" to specify a different revision.
128
128
129 To specify the type of archive to create, use "-t". Valid
129 To specify the type of archive to create, use "-t". Valid
130 types are:
130 types are:
131
131
132 "files" (default): a directory full of files
132 "files" (default): a directory full of files
133 "tar": tar archive, uncompressed
133 "tar": tar archive, uncompressed
134 "tbz2": tar archive, compressed using bzip2
134 "tbz2": tar archive, compressed using bzip2
135 "tgz": tar archive, compressed using gzip
135 "tgz": tar archive, compressed using gzip
136 "uzip": zip archive, uncompressed
136 "uzip": zip archive, uncompressed
137 "zip": zip archive, compressed using deflate
137 "zip": zip archive, compressed using deflate
138
138
139 The exact name of the destination archive or directory is given
139 The exact name of the destination archive or directory is given
140 using a format string; see "hg help export" for details.
140 using a format string; see "hg help export" for details.
141
141
142 Each member added to an archive file has a directory prefix
142 Each member added to an archive file has a directory prefix
143 prepended. Use "-p" to specify a format string for the prefix.
143 prepended. Use "-p" to specify a format string for the prefix.
144 The default is the basename of the archive, with suffixes removed.
144 The default is the basename of the archive, with suffixes removed.
145 '''
145 '''
146
146
147 ctx = repo.changectx(opts['rev'])
147 ctx = repo.changectx(opts['rev'])
148 if not ctx:
148 if not ctx:
149 raise util.Abort(_('repository has no revisions'))
149 raise util.Abort(_('repository has no revisions'))
150 node = ctx.node()
150 node = ctx.node()
151 dest = cmdutil.make_filename(repo, dest, node)
151 dest = cmdutil.make_filename(repo, dest, node)
152 if os.path.realpath(dest) == repo.root:
152 if os.path.realpath(dest) == repo.root:
153 raise util.Abort(_('repository root cannot be destination'))
153 raise util.Abort(_('repository root cannot be destination'))
154 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
154 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
155 kind = opts.get('type') or 'files'
155 kind = opts.get('type') or 'files'
156 prefix = opts['prefix']
156 prefix = opts['prefix']
157 if dest == '-':
157 if dest == '-':
158 if kind == 'files':
158 if kind == 'files':
159 raise util.Abort(_('cannot archive plain files to stdout'))
159 raise util.Abort(_('cannot archive plain files to stdout'))
160 dest = sys.stdout
160 dest = sys.stdout
161 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
161 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
162 prefix = cmdutil.make_filename(repo, prefix, node)
162 prefix = cmdutil.make_filename(repo, prefix, node)
163 archival.archive(repo, dest, node, kind, not opts['no_decode'],
163 archival.archive(repo, dest, node, kind, not opts['no_decode'],
164 matchfn, prefix)
164 matchfn, prefix)
165
165
166 def backout(ui, repo, node=None, rev=None, **opts):
166 def backout(ui, repo, node=None, rev=None, **opts):
167 '''reverse effect of earlier changeset
167 '''reverse effect of earlier changeset
168
168
169 Commit the backed out changes as a new changeset. The new
169 Commit the backed out changes as a new changeset. The new
170 changeset is a child of the backed out changeset.
170 changeset is a child of the backed out changeset.
171
171
172 If you back out a changeset other than the tip, a new head is
172 If you back out a changeset other than the tip, a new head is
173 created. This head is the parent of the working directory. If
173 created. This head is the parent of the working directory. If
174 you back out an old changeset, your working directory will appear
174 you back out an old changeset, your working directory will appear
175 old after the backout. You should merge the backout changeset
175 old after the backout. You should merge the backout changeset
176 with another head.
176 with another head.
177
177
178 The --merge option remembers the parent of the working directory
178 The --merge option remembers the parent of the working directory
179 before starting the backout, then merges the new head with that
179 before starting the backout, then merges the new head with that
180 changeset afterwards. This saves you from doing the merge by
180 changeset afterwards. This saves you from doing the merge by
181 hand. The result of this merge is not committed, as for a normal
181 hand. The result of this merge is not committed, as for a normal
182 merge.'''
182 merge.'''
183 if rev and node:
183 if rev and node:
184 raise util.Abort(_("please specify just one revision"))
184 raise util.Abort(_("please specify just one revision"))
185
185
186 if not rev:
186 if not rev:
187 rev = node
187 rev = node
188
188
189 if not rev:
189 if not rev:
190 raise util.Abort(_("please specify a revision to backout"))
190 raise util.Abort(_("please specify a revision to backout"))
191
191
192 cmdutil.bail_if_changed(repo)
192 cmdutil.bail_if_changed(repo)
193 op1, op2 = repo.dirstate.parents()
193 op1, op2 = repo.dirstate.parents()
194 if op2 != nullid:
194 if op2 != nullid:
195 raise util.Abort(_('outstanding uncommitted merge'))
195 raise util.Abort(_('outstanding uncommitted merge'))
196 node = repo.lookup(rev)
196 node = repo.lookup(rev)
197
197
198 a = repo.changelog.ancestor(op1, node)
198 a = repo.changelog.ancestor(op1, node)
199 if a != node:
199 if a != node:
200 raise util.Abort(_('cannot back out change on a different branch'))
200 raise util.Abort(_('cannot back out change on a different branch'))
201
201
202 p1, p2 = repo.changelog.parents(node)
202 p1, p2 = repo.changelog.parents(node)
203 if p1 == nullid:
203 if p1 == nullid:
204 raise util.Abort(_('cannot back out a change with no parents'))
204 raise util.Abort(_('cannot back out a change with no parents'))
205 if p2 != nullid:
205 if p2 != nullid:
206 if not opts['parent']:
206 if not opts['parent']:
207 raise util.Abort(_('cannot back out a merge changeset without '
207 raise util.Abort(_('cannot back out a merge changeset without '
208 '--parent'))
208 '--parent'))
209 p = repo.lookup(opts['parent'])
209 p = repo.lookup(opts['parent'])
210 if p not in (p1, p2):
210 if p not in (p1, p2):
211 raise util.Abort(_('%s is not a parent of %s') %
211 raise util.Abort(_('%s is not a parent of %s') %
212 (short(p), short(node)))
212 (short(p), short(node)))
213 parent = p
213 parent = p
214 else:
214 else:
215 if opts['parent']:
215 if opts['parent']:
216 raise util.Abort(_('cannot use --parent on non-merge changeset'))
216 raise util.Abort(_('cannot use --parent on non-merge changeset'))
217 parent = p1
217 parent = p1
218
218
219 hg.clean(repo, node, show_stats=False)
219 hg.clean(repo, node, show_stats=False)
220 revert_opts = opts.copy()
220 revert_opts = opts.copy()
221 revert_opts['date'] = None
221 revert_opts['date'] = None
222 revert_opts['all'] = True
222 revert_opts['all'] = True
223 revert_opts['rev'] = hex(parent)
223 revert_opts['rev'] = hex(parent)
224 revert(ui, repo, **revert_opts)
224 revert(ui, repo, **revert_opts)
225 commit_opts = opts.copy()
225 commit_opts = opts.copy()
226 commit_opts['addremove'] = False
226 commit_opts['addremove'] = False
227 if not commit_opts['message'] and not commit_opts['logfile']:
227 if not commit_opts['message'] and not commit_opts['logfile']:
228 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
228 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
229 commit_opts['force_editor'] = True
229 commit_opts['force_editor'] = True
230 commit(ui, repo, **commit_opts)
230 commit(ui, repo, **commit_opts)
231 def nice(node):
231 def nice(node):
232 return '%d:%s' % (repo.changelog.rev(node), short(node))
232 return '%d:%s' % (repo.changelog.rev(node), short(node))
233 ui.status(_('changeset %s backs out changeset %s\n') %
233 ui.status(_('changeset %s backs out changeset %s\n') %
234 (nice(repo.changelog.tip()), nice(node)))
234 (nice(repo.changelog.tip()), nice(node)))
235 if op1 != node:
235 if op1 != node:
236 if opts['merge']:
236 if opts['merge']:
237 ui.status(_('merging with changeset %s\n') % nice(op1))
237 ui.status(_('merging with changeset %s\n') % nice(op1))
238 hg.merge(repo, hex(op1))
238 hg.merge(repo, hex(op1))
239 else:
239 else:
240 ui.status(_('the backout changeset is a new head - '
240 ui.status(_('the backout changeset is a new head - '
241 'do not forget to merge\n'))
241 'do not forget to merge\n'))
242 ui.status(_('(use "backout --merge" '
242 ui.status(_('(use "backout --merge" '
243 'if you want to auto-merge)\n'))
243 'if you want to auto-merge)\n'))
244
244
245 def branch(ui, repo, label=None, **opts):
245 def branch(ui, repo, label=None, **opts):
246 """set or show the current branch name
246 """set or show the current branch name
247
247
248 With no argument, show the current branch name. With one argument,
248 With no argument, show the current branch name. With one argument,
249 set the working directory branch name (the branch does not exist in
249 set the working directory branch name (the branch does not exist in
250 the repository until the next commit).
250 the repository until the next commit).
251
251
252 Unless --force is specified, branch will not let you set a
252 Unless --force is specified, branch will not let you set a
253 branch name that shadows an existing branch.
253 branch name that shadows an existing branch.
254 """
254 """
255
255
256 if label:
256 if label:
257 if not opts.get('force') and label in repo.branchtags():
257 if not opts.get('force') and label in repo.branchtags():
258 if label not in [p.branch() for p in repo.workingctx().parents()]:
258 if label not in [p.branch() for p in repo.workingctx().parents()]:
259 raise util.Abort(_('a branch of the same name already exists'
259 raise util.Abort(_('a branch of the same name already exists'
260 ' (use --force to override)'))
260 ' (use --force to override)'))
261 repo.dirstate.setbranch(util.fromlocal(label))
261 repo.dirstate.setbranch(util.fromlocal(label))
262 ui.status(_('marked working directory as branch %s\n') % label)
262 ui.status(_('marked working directory as branch %s\n') % label)
263 else:
263 else:
264 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
264 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
265
265
266 def branches(ui, repo, active=False):
266 def branches(ui, repo, active=False):
267 """list repository named branches
267 """list repository named branches
268
268
269 List the repository's named branches, indicating which ones are
269 List the repository's named branches, indicating which ones are
270 inactive. If active is specified, only show active branches.
270 inactive. If active is specified, only show active branches.
271
271
272 A branch is considered active if it contains unmerged heads.
272 A branch is considered active if it contains unmerged heads.
273 """
273 """
274 b = repo.branchtags()
274 b = repo.branchtags()
275 heads = dict.fromkeys(repo.heads(), 1)
275 heads = dict.fromkeys(repo.heads(), 1)
276 l = [((n in heads), repo.changelog.rev(n), n, t) for t, n in b.items()]
276 l = [((n in heads), repo.changelog.rev(n), n, t) for t, n in b.items()]
277 l.sort()
277 l.sort()
278 l.reverse()
278 l.reverse()
279 for ishead, r, n, t in l:
279 for ishead, r, n, t in l:
280 if active and not ishead:
280 if active and not ishead:
281 # If we're only displaying active branches, abort the loop on
281 # If we're only displaying active branches, abort the loop on
282 # encountering the first inactive head
282 # encountering the first inactive head
283 break
283 break
284 else:
284 else:
285 hexfunc = ui.debugflag and hex or short
285 hexfunc = ui.debugflag and hex or short
286 if ui.quiet:
286 if ui.quiet:
287 ui.write("%s\n" % t)
287 ui.write("%s\n" % t)
288 else:
288 else:
289 spaces = " " * (30 - util.locallen(t))
289 spaces = " " * (30 - util.locallen(t))
290 # The code only gets here if inactive branches are being
290 # The code only gets here if inactive branches are being
291 # displayed or the branch is active.
291 # displayed or the branch is active.
292 isinactive = ((not ishead) and " (inactive)") or ''
292 isinactive = ((not ishead) and " (inactive)") or ''
293 ui.write("%s%s %s:%s%s\n" % (t, spaces, r, hexfunc(n), isinactive))
293 ui.write("%s%s %s:%s%s\n" % (t, spaces, r, hexfunc(n), isinactive))
294
294
295 def bundle(ui, repo, fname, dest=None, **opts):
295 def bundle(ui, repo, fname, dest=None, **opts):
296 """create a changegroup file
296 """create a changegroup file
297
297
298 Generate a compressed changegroup file collecting changesets not
298 Generate a compressed changegroup file collecting changesets not
299 found in the other repository.
299 found in the other repository.
300
300
301 If no destination repository is specified the destination is assumed
301 If no destination repository is specified the destination is assumed
302 to have all the nodes specified by one or more --base parameters.
302 to have all the nodes specified by one or more --base parameters.
303
303
304 The bundle file can then be transferred using conventional means and
304 The bundle file can then be transferred using conventional means and
305 applied to another repository with the unbundle or pull command.
305 applied to another repository with the unbundle or pull command.
306 This is useful when direct push and pull are not available or when
306 This is useful when direct push and pull are not available or when
307 exporting an entire repository is undesirable.
307 exporting an entire repository is undesirable.
308
308
309 Applying bundles preserves all changeset contents including
309 Applying bundles preserves all changeset contents including
310 permissions, copy/rename information, and revision history.
310 permissions, copy/rename information, and revision history.
311 """
311 """
312 revs = opts.get('rev') or None
312 revs = opts.get('rev') or None
313 if revs:
313 if revs:
314 revs = [repo.lookup(rev) for rev in revs]
314 revs = [repo.lookup(rev) for rev in revs]
315 base = opts.get('base')
315 base = opts.get('base')
316 if base:
316 if base:
317 if dest:
317 if dest:
318 raise util.Abort(_("--base is incompatible with specifiying "
318 raise util.Abort(_("--base is incompatible with specifiying "
319 "a destination"))
319 "a destination"))
320 base = [repo.lookup(rev) for rev in base]
320 base = [repo.lookup(rev) for rev in base]
321 # create the right base
321 # create the right base
322 # XXX: nodesbetween / changegroup* should be "fixed" instead
322 # XXX: nodesbetween / changegroup* should be "fixed" instead
323 o = []
323 o = []
324 has = {nullid: None}
324 has = {nullid: None}
325 for n in base:
325 for n in base:
326 has.update(repo.changelog.reachable(n))
326 has.update(repo.changelog.reachable(n))
327 if revs:
327 if revs:
328 visit = list(revs)
328 visit = list(revs)
329 else:
329 else:
330 visit = repo.changelog.heads()
330 visit = repo.changelog.heads()
331 seen = {}
331 seen = {}
332 while visit:
332 while visit:
333 n = visit.pop(0)
333 n = visit.pop(0)
334 parents = [p for p in repo.changelog.parents(n) if p not in has]
334 parents = [p for p in repo.changelog.parents(n) if p not in has]
335 if len(parents) == 0:
335 if len(parents) == 0:
336 o.insert(0, n)
336 o.insert(0, n)
337 else:
337 else:
338 for p in parents:
338 for p in parents:
339 if p not in seen:
339 if p not in seen:
340 seen[p] = 1
340 seen[p] = 1
341 visit.append(p)
341 visit.append(p)
342 else:
342 else:
343 cmdutil.setremoteconfig(ui, opts)
343 cmdutil.setremoteconfig(ui, opts)
344 dest, revs, checkout = hg.parseurl(
344 dest, revs, checkout = hg.parseurl(
345 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
345 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
346 other = hg.repository(ui, dest)
346 other = hg.repository(ui, dest)
347 o = repo.findoutgoing(other, force=opts['force'])
347 o = repo.findoutgoing(other, force=opts['force'])
348
348
349 if revs:
349 if revs:
350 cg = repo.changegroupsubset(o, revs, 'bundle')
350 cg = repo.changegroupsubset(o, revs, 'bundle')
351 else:
351 else:
352 cg = repo.changegroup(o, 'bundle')
352 cg = repo.changegroup(o, 'bundle')
353 changegroup.writebundle(cg, fname, "HG10BZ")
353 changegroup.writebundle(cg, fname, "HG10BZ")
354
354
355 def cat(ui, repo, file1, *pats, **opts):
355 def cat(ui, repo, file1, *pats, **opts):
356 """output the current or given revision of files
356 """output the current or given revision of files
357
357
358 Print the specified files as they were at the given revision.
358 Print the specified files as they were at the given revision.
359 If no revision is given, the parent of the working directory is used,
359 If no revision is given, the parent of the working directory is used,
360 or tip if no revision is checked out.
360 or tip if no revision is checked out.
361
361
362 Output may be to a file, in which case the name of the file is
362 Output may be to a file, in which case the name of the file is
363 given using a format string. The formatting rules are the same as
363 given using a format string. The formatting rules are the same as
364 for the export command, with the following additions:
364 for the export command, with the following additions:
365
365
366 %s basename of file being printed
366 %s basename of file being printed
367 %d dirname of file being printed, or '.' if in repo root
367 %d dirname of file being printed, or '.' if in repo root
368 %p root-relative path name of file being printed
368 %p root-relative path name of file being printed
369 """
369 """
370 ctx = repo.changectx(opts['rev'])
370 ctx = repo.changectx(opts['rev'])
371 err = 1
371 err = 1
372 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
372 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
373 ctx.node()):
373 ctx.node()):
374 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
374 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
375 fp.write(ctx.filectx(abs).data())
375 fp.write(ctx.filectx(abs).data())
376 err = 0
376 err = 0
377 return err
377 return err
378
378
379 def clone(ui, source, dest=None, **opts):
379 def clone(ui, source, dest=None, **opts):
380 """make a copy of an existing repository
380 """make a copy of an existing repository
381
381
382 Create a copy of an existing repository in a new directory.
382 Create a copy of an existing repository in a new directory.
383
383
384 If no destination directory name is specified, it defaults to the
384 If no destination directory name is specified, it defaults to the
385 basename of the source.
385 basename of the source.
386
386
387 The location of the source is added to the new repository's
387 The location of the source is added to the new repository's
388 .hg/hgrc file, as the default to be used for future pulls.
388 .hg/hgrc file, as the default to be used for future pulls.
389
389
390 For efficiency, hardlinks are used for cloning whenever the source
390 For efficiency, hardlinks are used for cloning whenever the source
391 and destination are on the same filesystem (note this applies only
391 and destination are on the same filesystem (note this applies only
392 to the repository data, not to the checked out files). Some
392 to the repository data, not to the checked out files). Some
393 filesystems, such as AFS, implement hardlinking incorrectly, but
393 filesystems, such as AFS, implement hardlinking incorrectly, but
394 do not report errors. In these cases, use the --pull option to
394 do not report errors. In these cases, use the --pull option to
395 avoid hardlinking.
395 avoid hardlinking.
396
396
397 You can safely clone repositories and checked out files using full
397 You can safely clone repositories and checked out files using full
398 hardlinks with
398 hardlinks with
399
399
400 $ cp -al REPO REPOCLONE
400 $ cp -al REPO REPOCLONE
401
401
402 which is the fastest way to clone. However, the operation is not
402 which is the fastest way to clone. However, the operation is not
403 atomic (making sure REPO is not modified during the operation is
403 atomic (making sure REPO is not modified during the operation is
404 up to you) and you have to make sure your editor breaks hardlinks
404 up to you) and you have to make sure your editor breaks hardlinks
405 (Emacs and most Linux Kernel tools do so).
405 (Emacs and most Linux Kernel tools do so).
406
406
407 If you use the -r option to clone up to a specific revision, no
407 If you use the -r option to clone up to a specific revision, no
408 subsequent revisions will be present in the cloned repository.
408 subsequent revisions will be present in the cloned repository.
409 This option implies --pull, even on local repositories.
409 This option implies --pull, even on local repositories.
410
410
411 See pull for valid source format details.
411 See pull for valid source format details.
412
412
413 It is possible to specify an ssh:// URL as the destination, but no
413 It is possible to specify an ssh:// URL as the destination, but no
414 .hg/hgrc and working directory will be created on the remote side.
414 .hg/hgrc and working directory will be created on the remote side.
415 Look at the help text for the pull command for important details
415 Look at the help text for the pull command for important details
416 about ssh:// URLs.
416 about ssh:// URLs.
417 """
417 """
418 cmdutil.setremoteconfig(ui, opts)
418 cmdutil.setremoteconfig(ui, opts)
419 hg.clone(ui, source, dest,
419 hg.clone(ui, source, dest,
420 pull=opts['pull'],
420 pull=opts['pull'],
421 stream=opts['uncompressed'],
421 stream=opts['uncompressed'],
422 rev=opts['rev'],
422 rev=opts['rev'],
423 update=not opts['noupdate'])
423 update=not opts['noupdate'])
424
424
425 def commit(ui, repo, *pats, **opts):
425 def commit(ui, repo, *pats, **opts):
426 """commit the specified files or all outstanding changes
426 """commit the specified files or all outstanding changes
427
427
428 Commit changes to the given files into the repository.
428 Commit changes to the given files into the repository.
429
429
430 If a list of files is omitted, all changes reported by "hg status"
430 If a list of files is omitted, all changes reported by "hg status"
431 will be committed.
431 will be committed.
432
432
433 If no commit message is specified, the editor configured in your hgrc
433 If no commit message is specified, the editor configured in your hgrc
434 or in the EDITOR environment variable is started to enter a message.
434 or in the EDITOR environment variable is started to enter a message.
435 """
435 """
436 def commitfunc(ui, repo, files, message, match, opts):
436 def commitfunc(ui, repo, files, message, match, opts):
437 return repo.commit(files, message, opts['user'], opts['date'], match,
437 return repo.commit(files, message, opts['user'], opts['date'], match,
438 force_editor=opts.get('force_editor'))
438 force_editor=opts.get('force_editor'))
439 cmdutil.commit(ui, repo, commitfunc, pats, opts)
439 cmdutil.commit(ui, repo, commitfunc, pats, opts)
440
440
441 def docopy(ui, repo, pats, opts):
441 def docopy(ui, repo, pats, opts):
442 # called with the repo lock held
442 # called with the repo lock held
443 #
443 #
444 # hgsep => pathname that uses "/" to separate directories
444 # hgsep => pathname that uses "/" to separate directories
445 # ossep => pathname that uses os.sep to separate directories
445 # ossep => pathname that uses os.sep to separate directories
446 cwd = repo.getcwd()
446 cwd = repo.getcwd()
447 errors = 0
447 errors = 0
448 copied = []
448 copied = []
449 targets = {}
449 targets = {}
450
450
451 # abs: hgsep
451 # abs: hgsep
452 # rel: ossep
452 # rel: ossep
453 # return: hgsep
453 # return: hgsep
454 def okaytocopy(abs, rel, exact):
454 def okaytocopy(abs, rel, exact):
455 reasons = {'?': _('is not managed'),
455 reasons = {'?': _('is not managed'),
456 'r': _('has been marked for remove')}
456 'r': _('has been marked for remove')}
457 state = repo.dirstate[abs]
457 state = repo.dirstate[abs]
458 reason = reasons.get(state)
458 reason = reasons.get(state)
459 if reason:
459 if reason:
460 if exact:
460 if exact:
461 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
461 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
462 else:
462 else:
463 if state == 'a':
463 if state == 'a':
464 origsrc = repo.dirstate.copied(abs)
464 origsrc = repo.dirstate.copied(abs)
465 if origsrc is not None:
465 if origsrc is not None:
466 return origsrc
466 return origsrc
467 return abs
467 return abs
468
468
469 # origsrc: hgsep
469 # origsrc: hgsep
470 # abssrc: hgsep
470 # abssrc: hgsep
471 # relsrc: ossep
471 # relsrc: ossep
472 # otarget: ossep
472 # otarget: ossep
473 def copy(origsrc, abssrc, relsrc, otarget, exact):
473 def copy(origsrc, abssrc, relsrc, otarget, exact):
474 abstarget = util.canonpath(repo.root, cwd, otarget)
474 abstarget = util.canonpath(repo.root, cwd, otarget)
475 reltarget = repo.pathto(abstarget, cwd)
475 reltarget = repo.pathto(abstarget, cwd)
476 prevsrc = targets.get(abstarget)
476 prevsrc = targets.get(abstarget)
477 src = repo.wjoin(abssrc)
477 src = repo.wjoin(abssrc)
478 target = repo.wjoin(abstarget)
478 target = repo.wjoin(abstarget)
479 if prevsrc is not None:
479 if prevsrc is not None:
480 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
480 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
481 (reltarget, repo.pathto(abssrc, cwd),
481 (reltarget, repo.pathto(abssrc, cwd),
482 repo.pathto(prevsrc, cwd)))
482 repo.pathto(prevsrc, cwd)))
483 return
483 return
484 if (not opts['after'] and os.path.exists(target) or
484 if (not opts['after'] and os.path.exists(target) or
485 opts['after'] and repo.dirstate[abstarget] in 'mn'):
485 opts['after'] and repo.dirstate[abstarget] in 'mn'):
486 if not opts['force']:
486 if not opts['force']:
487 ui.warn(_('%s: not overwriting - file exists\n') %
487 ui.warn(_('%s: not overwriting - file exists\n') %
488 reltarget)
488 reltarget)
489 return
489 return
490 if not opts['after'] and not opts.get('dry_run'):
490 if not opts['after'] and not opts.get('dry_run'):
491 os.unlink(target)
491 os.unlink(target)
492 if opts['after']:
492 if opts['after']:
493 if not os.path.exists(target):
493 if not os.path.exists(target):
494 return
494 return
495 else:
495 else:
496 targetdir = os.path.dirname(target) or '.'
496 targetdir = os.path.dirname(target) or '.'
497 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
497 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
498 os.makedirs(targetdir)
498 os.makedirs(targetdir)
499 try:
499 try:
500 restore = repo.dirstate[abstarget] == 'r'
500 restore = repo.dirstate[abstarget] == 'r'
501 if restore and not opts.get('dry_run'):
501 if restore and not opts.get('dry_run'):
502 repo.undelete([abstarget])
502 repo.undelete([abstarget])
503 try:
503 try:
504 if not opts.get('dry_run'):
504 if not opts.get('dry_run'):
505 util.copyfile(src, target)
505 util.copyfile(src, target)
506 restore = False
506 restore = False
507 finally:
507 finally:
508 if restore:
508 if restore:
509 repo.remove([abstarget])
509 repo.remove([abstarget])
510 except IOError, inst:
510 except IOError, inst:
511 if inst.errno == errno.ENOENT:
511 if inst.errno == errno.ENOENT:
512 ui.warn(_('%s: deleted in working copy\n') % relsrc)
512 ui.warn(_('%s: deleted in working copy\n') % relsrc)
513 else:
513 else:
514 ui.warn(_('%s: cannot copy - %s\n') %
514 ui.warn(_('%s: cannot copy - %s\n') %
515 (relsrc, inst.strerror))
515 (relsrc, inst.strerror))
516 errors += 1
516 errors += 1
517 return
517 return
518 if ui.verbose or not exact:
518 if ui.verbose or not exact:
519 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
519 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
520 targets[abstarget] = abssrc
520 targets[abstarget] = abssrc
521 if abstarget != origsrc:
521 if abstarget != origsrc:
522 if repo.dirstate[origsrc] == 'a':
522 if repo.dirstate[origsrc] == 'a':
523 if not ui.quiet:
523 if not ui.quiet:
524 ui.warn(_("%s has not been committed yet, so no copy "
524 ui.warn(_("%s has not been committed yet, so no copy "
525 "data will be stored for %s.\n")
525 "data will be stored for %s.\n")
526 % (repo.pathto(origsrc, cwd), reltarget))
526 % (repo.pathto(origsrc, cwd), reltarget))
527 if abstarget not in repo.dirstate and not opts.get('dry_run'):
527 if abstarget not in repo.dirstate and not opts.get('dry_run'):
528 repo.add([abstarget])
528 repo.add([abstarget])
529 elif not opts.get('dry_run'):
529 elif not opts.get('dry_run'):
530 repo.copy(origsrc, abstarget)
530 repo.copy(origsrc, abstarget)
531 copied.append((abssrc, relsrc, exact))
531 copied.append((abssrc, relsrc, exact))
532
532
533 # pat: ossep
533 # pat: ossep
534 # dest ossep
534 # dest ossep
535 # srcs: list of (hgsep, hgsep, ossep, bool)
535 # srcs: list of (hgsep, hgsep, ossep, bool)
536 # return: function that takes hgsep and returns ossep
536 # return: function that takes hgsep and returns ossep
537 def targetpathfn(pat, dest, srcs):
537 def targetpathfn(pat, dest, srcs):
538 if os.path.isdir(pat):
538 if os.path.isdir(pat):
539 abspfx = util.canonpath(repo.root, cwd, pat)
539 abspfx = util.canonpath(repo.root, cwd, pat)
540 abspfx = util.localpath(abspfx)
540 abspfx = util.localpath(abspfx)
541 if destdirexists:
541 if destdirexists:
542 striplen = len(os.path.split(abspfx)[0])
542 striplen = len(os.path.split(abspfx)[0])
543 else:
543 else:
544 striplen = len(abspfx)
544 striplen = len(abspfx)
545 if striplen:
545 if striplen:
546 striplen += len(os.sep)
546 striplen += len(os.sep)
547 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
547 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
548 elif destdirexists:
548 elif destdirexists:
549 res = lambda p: os.path.join(dest,
549 res = lambda p: os.path.join(dest,
550 os.path.basename(util.localpath(p)))
550 os.path.basename(util.localpath(p)))
551 else:
551 else:
552 res = lambda p: dest
552 res = lambda p: dest
553 return res
553 return res
554
554
555 # pat: ossep
555 # pat: ossep
556 # dest ossep
556 # dest ossep
557 # srcs: list of (hgsep, hgsep, ossep, bool)
557 # srcs: list of (hgsep, hgsep, ossep, bool)
558 # return: function that takes hgsep and returns ossep
558 # return: function that takes hgsep and returns ossep
559 def targetpathafterfn(pat, dest, srcs):
559 def targetpathafterfn(pat, dest, srcs):
560 if util.patkind(pat, None)[0]:
560 if util.patkind(pat, None)[0]:
561 # a mercurial pattern
561 # a mercurial pattern
562 res = lambda p: os.path.join(dest,
562 res = lambda p: os.path.join(dest,
563 os.path.basename(util.localpath(p)))
563 os.path.basename(util.localpath(p)))
564 else:
564 else:
565 abspfx = util.canonpath(repo.root, cwd, pat)
565 abspfx = util.canonpath(repo.root, cwd, pat)
566 if len(abspfx) < len(srcs[0][0]):
566 if len(abspfx) < len(srcs[0][0]):
567 # A directory. Either the target path contains the last
567 # A directory. Either the target path contains the last
568 # component of the source path or it does not.
568 # component of the source path or it does not.
569 def evalpath(striplen):
569 def evalpath(striplen):
570 score = 0
570 score = 0
571 for s in srcs:
571 for s in srcs:
572 t = os.path.join(dest, util.localpath(s[0])[striplen:])
572 t = os.path.join(dest, util.localpath(s[0])[striplen:])
573 if os.path.exists(t):
573 if os.path.exists(t):
574 score += 1
574 score += 1
575 return score
575 return score
576
576
577 abspfx = util.localpath(abspfx)
577 abspfx = util.localpath(abspfx)
578 striplen = len(abspfx)
578 striplen = len(abspfx)
579 if striplen:
579 if striplen:
580 striplen += len(os.sep)
580 striplen += len(os.sep)
581 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
581 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
582 score = evalpath(striplen)
582 score = evalpath(striplen)
583 striplen1 = len(os.path.split(abspfx)[0])
583 striplen1 = len(os.path.split(abspfx)[0])
584 if striplen1:
584 if striplen1:
585 striplen1 += len(os.sep)
585 striplen1 += len(os.sep)
586 if evalpath(striplen1) > score:
586 if evalpath(striplen1) > score:
587 striplen = striplen1
587 striplen = striplen1
588 res = lambda p: os.path.join(dest,
588 res = lambda p: os.path.join(dest,
589 util.localpath(p)[striplen:])
589 util.localpath(p)[striplen:])
590 else:
590 else:
591 # a file
591 # a file
592 if destdirexists:
592 if destdirexists:
593 res = lambda p: os.path.join(dest,
593 res = lambda p: os.path.join(dest,
594 os.path.basename(util.localpath(p)))
594 os.path.basename(util.localpath(p)))
595 else:
595 else:
596 res = lambda p: dest
596 res = lambda p: dest
597 return res
597 return res
598
598
599
599
600 pats = util.expand_glob(pats)
600 pats = util.expand_glob(pats)
601 if not pats:
601 if not pats:
602 raise util.Abort(_('no source or destination specified'))
602 raise util.Abort(_('no source or destination specified'))
603 if len(pats) == 1:
603 if len(pats) == 1:
604 raise util.Abort(_('no destination specified'))
604 raise util.Abort(_('no destination specified'))
605 dest = pats.pop()
605 dest = pats.pop()
606 destdirexists = os.path.isdir(dest)
606 destdirexists = os.path.isdir(dest)
607 if not destdirexists:
607 if not destdirexists:
608 if len(pats) > 1 or util.patkind(pats[0], None)[0]:
608 if len(pats) > 1 or util.patkind(pats[0], None)[0]:
609 raise util.Abort(_('with multiple sources, destination must be an '
609 raise util.Abort(_('with multiple sources, destination must be an '
610 'existing directory'))
610 'existing directory'))
611 if dest.endswith(os.sep) or os.altsep and dest.endswith(os.altsep):
611 if dest.endswith(os.sep) or os.altsep and dest.endswith(os.altsep):
612 raise util.Abort(_('destination %s is not a directory') % dest)
612 raise util.Abort(_('destination %s is not a directory') % dest)
613 if opts['after']:
613 if opts['after']:
614 tfn = targetpathafterfn
614 tfn = targetpathafterfn
615 else:
615 else:
616 tfn = targetpathfn
616 tfn = targetpathfn
617 copylist = []
617 copylist = []
618 for pat in pats:
618 for pat in pats:
619 srcs = []
619 srcs = []
620 for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts,
620 for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts,
621 globbed=True):
621 globbed=True):
622 origsrc = okaytocopy(abssrc, relsrc, exact)
622 origsrc = okaytocopy(abssrc, relsrc, exact)
623 if origsrc:
623 if origsrc:
624 srcs.append((origsrc, abssrc, relsrc, exact))
624 srcs.append((origsrc, abssrc, relsrc, exact))
625 if not srcs:
625 if not srcs:
626 continue
626 continue
627 copylist.append((tfn(pat, dest, srcs), srcs))
627 copylist.append((tfn(pat, dest, srcs), srcs))
628 if not copylist:
628 if not copylist:
629 raise util.Abort(_('no files to copy'))
629 raise util.Abort(_('no files to copy'))
630
630
631 for targetpath, srcs in copylist:
631 for targetpath, srcs in copylist:
632 for origsrc, abssrc, relsrc, exact in srcs:
632 for origsrc, abssrc, relsrc, exact in srcs:
633 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
633 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
634
634
635 if errors:
635 if errors:
636 ui.warn(_('(consider using --after)\n'))
636 ui.warn(_('(consider using --after)\n'))
637 return errors, copied
637 return errors, copied
638
638
639 def copy(ui, repo, *pats, **opts):
639 def copy(ui, repo, *pats, **opts):
640 """mark files as copied for the next commit
640 """mark files as copied for the next commit
641
641
642 Mark dest as having copies of source files. If dest is a
642 Mark dest as having copies of source files. If dest is a
643 directory, copies are put in that directory. If dest is a file,
643 directory, copies are put in that directory. If dest is a file,
644 there can only be one source.
644 there can only be one source.
645
645
646 By default, this command copies the contents of files as they
646 By default, this command copies the contents of files as they
647 stand in the working directory. If invoked with --after, the
647 stand in the working directory. If invoked with --after, the
648 operation is recorded, but no copying is performed.
648 operation is recorded, but no copying is performed.
649
649
650 This command takes effect in the next commit. To undo a copy
650 This command takes effect in the next commit. To undo a copy
651 before that, see hg revert.
651 before that, see hg revert.
652 """
652 """
653 wlock = repo.wlock(False)
653 wlock = repo.wlock(False)
654 try:
654 try:
655 errs, copied = docopy(ui, repo, pats, opts)
655 errs, copied = docopy(ui, repo, pats, opts)
656 finally:
656 finally:
657 del wlock
657 del wlock
658 return errs
658 return errs
659
659
660 def debugancestor(ui, index, rev1, rev2):
660 def debugancestor(ui, index, rev1, rev2):
661 """find the ancestor revision of two revisions in a given index"""
661 """find the ancestor revision of two revisions in a given index"""
662 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
662 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
663 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
663 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
664 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
664 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
665
665
666 def debugcomplete(ui, cmd='', **opts):
666 def debugcomplete(ui, cmd='', **opts):
667 """returns the completion list associated with the given command"""
667 """returns the completion list associated with the given command"""
668
668
669 if opts['options']:
669 if opts['options']:
670 options = []
670 options = []
671 otables = [globalopts]
671 otables = [globalopts]
672 if cmd:
672 if cmd:
673 aliases, entry = cmdutil.findcmd(ui, cmd, table)
673 aliases, entry = cmdutil.findcmd(ui, cmd, table)
674 otables.append(entry[1])
674 otables.append(entry[1])
675 for t in otables:
675 for t in otables:
676 for o in t:
676 for o in t:
677 if o[0]:
677 if o[0]:
678 options.append('-%s' % o[0])
678 options.append('-%s' % o[0])
679 options.append('--%s' % o[1])
679 options.append('--%s' % o[1])
680 ui.write("%s\n" % "\n".join(options))
680 ui.write("%s\n" % "\n".join(options))
681 return
681 return
682
682
683 clist = cmdutil.findpossible(ui, cmd, table).keys()
683 clist = cmdutil.findpossible(ui, cmd, table).keys()
684 clist.sort()
684 clist.sort()
685 ui.write("%s\n" % "\n".join(clist))
685 ui.write("%s\n" % "\n".join(clist))
686
686
687 def debugrebuildstate(ui, repo, rev=""):
687 def debugrebuildstate(ui, repo, rev=""):
688 """rebuild the dirstate as it would look like for the given revision"""
688 """rebuild the dirstate as it would look like for the given revision"""
689 if rev == "":
689 if rev == "":
690 rev = repo.changelog.tip()
690 rev = repo.changelog.tip()
691 ctx = repo.changectx(rev)
691 ctx = repo.changectx(rev)
692 files = ctx.manifest()
692 files = ctx.manifest()
693 wlock = repo.wlock()
693 wlock = repo.wlock()
694 try:
694 try:
695 repo.dirstate.rebuild(rev, files)
695 repo.dirstate.rebuild(rev, files)
696 finally:
696 finally:
697 del wlock
697 del wlock
698
698
699 def debugcheckstate(ui, repo):
699 def debugcheckstate(ui, repo):
700 """validate the correctness of the current dirstate"""
700 """validate the correctness of the current dirstate"""
701 parent1, parent2 = repo.dirstate.parents()
701 parent1, parent2 = repo.dirstate.parents()
702 m1 = repo.changectx(parent1).manifest()
702 m1 = repo.changectx(parent1).manifest()
703 m2 = repo.changectx(parent2).manifest()
703 m2 = repo.changectx(parent2).manifest()
704 errors = 0
704 errors = 0
705 for f in repo.dirstate:
705 for f in repo.dirstate:
706 state = repo.dirstate[f]
706 state = repo.dirstate[f]
707 if state in "nr" and f not in m1:
707 if state in "nr" and f not in m1:
708 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
708 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
709 errors += 1
709 errors += 1
710 if state in "a" and f in m1:
710 if state in "a" and f in m1:
711 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
711 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
712 errors += 1
712 errors += 1
713 if state in "m" and f not in m1 and f not in m2:
713 if state in "m" and f not in m1 and f not in m2:
714 ui.warn(_("%s in state %s, but not in either manifest\n") %
714 ui.warn(_("%s in state %s, but not in either manifest\n") %
715 (f, state))
715 (f, state))
716 errors += 1
716 errors += 1
717 for f in m1:
717 for f in m1:
718 state = repo.dirstate[f]
718 state = repo.dirstate[f]
719 if state not in "nrm":
719 if state not in "nrm":
720 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
720 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
721 errors += 1
721 errors += 1
722 if errors:
722 if errors:
723 error = _(".hg/dirstate inconsistent with current parent's manifest")
723 error = _(".hg/dirstate inconsistent with current parent's manifest")
724 raise util.Abort(error)
724 raise util.Abort(error)
725
725
726 def showconfig(ui, repo, *values, **opts):
726 def showconfig(ui, repo, *values, **opts):
727 """show combined config settings from all hgrc files
727 """show combined config settings from all hgrc files
728
728
729 With no args, print names and values of all config items.
729 With no args, print names and values of all config items.
730
730
731 With one arg of the form section.name, print just the value of
731 With one arg of the form section.name, print just the value of
732 that config item.
732 that config item.
733
733
734 With multiple args, print names and values of all config items
734 With multiple args, print names and values of all config items
735 with matching section names."""
735 with matching section names."""
736
736
737 untrusted = bool(opts.get('untrusted'))
737 untrusted = bool(opts.get('untrusted'))
738 if values:
738 if values:
739 if len([v for v in values if '.' in v]) > 1:
739 if len([v for v in values if '.' in v]) > 1:
740 raise util.Abort(_('only one config item permitted'))
740 raise util.Abort(_('only one config item permitted'))
741 for section, name, value in ui.walkconfig(untrusted=untrusted):
741 for section, name, value in ui.walkconfig(untrusted=untrusted):
742 sectname = section + '.' + name
742 sectname = section + '.' + name
743 if values:
743 if values:
744 for v in values:
744 for v in values:
745 if v == section:
745 if v == section:
746 ui.write('%s=%s\n' % (sectname, value))
746 ui.write('%s=%s\n' % (sectname, value))
747 elif v == sectname:
747 elif v == sectname:
748 ui.write(value, '\n')
748 ui.write(value, '\n')
749 else:
749 else:
750 ui.write('%s=%s\n' % (sectname, value))
750 ui.write('%s=%s\n' % (sectname, value))
751
751
752 def debugsetparents(ui, repo, rev1, rev2=None):
752 def debugsetparents(ui, repo, rev1, rev2=None):
753 """manually set the parents of the current working directory
753 """manually set the parents of the current working directory
754
754
755 This is useful for writing repository conversion tools, but should
755 This is useful for writing repository conversion tools, but should
756 be used with care.
756 be used with care.
757 """
757 """
758
758
759 if not rev2:
759 if not rev2:
760 rev2 = hex(nullid)
760 rev2 = hex(nullid)
761
761
762 wlock = repo.wlock()
762 wlock = repo.wlock()
763 try:
763 try:
764 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
764 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
765 finally:
765 finally:
766 del wlock
766 del wlock
767
767
768 def debugstate(ui, repo):
768 def debugstate(ui, repo):
769 """show the contents of the current dirstate"""
769 """show the contents of the current dirstate"""
770 k = repo.dirstate._map.items()
770 k = repo.dirstate._map.items()
771 k.sort()
771 k.sort()
772 for file_, ent in k:
772 for file_, ent in k:
773 if ent[3] == -1:
773 if ent[3] == -1:
774 # Pad or slice to locale representation
774 # Pad or slice to locale representation
775 locale_len = len(time.strftime("%x %X", time.localtime(0)))
775 locale_len = len(time.strftime("%x %X", time.localtime(0)))
776 timestr = 'unset'
776 timestr = 'unset'
777 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
777 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
778 else:
778 else:
779 timestr = time.strftime("%x %X", time.localtime(ent[3]))
779 timestr = time.strftime("%x %X", time.localtime(ent[3]))
780 if ent[1] & 020000:
780 if ent[1] & 020000:
781 mode = 'lnk'
781 mode = 'lnk'
782 else:
782 else:
783 mode = '%3o' % (ent[1] & 0777)
783 mode = '%3o' % (ent[1] & 0777)
784 ui.write("%c %s %10d %s %s\n" % (ent[0], mode, ent[2], timestr, file_))
784 ui.write("%c %s %10d %s %s\n" % (ent[0], mode, ent[2], timestr, file_))
785 for f in repo.dirstate.copies():
785 for f in repo.dirstate.copies():
786 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
786 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
787
787
788 def debugdata(ui, file_, rev):
788 def debugdata(ui, file_, rev):
789 """dump the contents of a data file revision"""
789 """dump the contents of a data file revision"""
790 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
790 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
791 try:
791 try:
792 ui.write(r.revision(r.lookup(rev)))
792 ui.write(r.revision(r.lookup(rev)))
793 except KeyError:
793 except KeyError:
794 raise util.Abort(_('invalid revision identifier %s') % rev)
794 raise util.Abort(_('invalid revision identifier %s') % rev)
795
795
796 def debugdate(ui, date, range=None, **opts):
796 def debugdate(ui, date, range=None, **opts):
797 """parse and display a date"""
797 """parse and display a date"""
798 if opts["extended"]:
798 if opts["extended"]:
799 d = util.parsedate(date, util.extendeddateformats)
799 d = util.parsedate(date, util.extendeddateformats)
800 else:
800 else:
801 d = util.parsedate(date)
801 d = util.parsedate(date)
802 ui.write("internal: %s %s\n" % d)
802 ui.write("internal: %s %s\n" % d)
803 ui.write("standard: %s\n" % util.datestr(d))
803 ui.write("standard: %s\n" % util.datestr(d))
804 if range:
804 if range:
805 m = util.matchdate(range)
805 m = util.matchdate(range)
806 ui.write("match: %s\n" % m(d[0]))
806 ui.write("match: %s\n" % m(d[0]))
807
807
808 def debugindex(ui, file_):
808 def debugindex(ui, file_):
809 """dump the contents of an index file"""
809 """dump the contents of an index file"""
810 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
810 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
811 ui.write(" rev offset length base linkrev" +
811 ui.write(" rev offset length base linkrev" +
812 " nodeid p1 p2\n")
812 " nodeid p1 p2\n")
813 for i in xrange(r.count()):
813 for i in xrange(r.count()):
814 node = r.node(i)
814 node = r.node(i)
815 try:
815 try:
816 pp = r.parents(node)
816 pp = r.parents(node)
817 except:
817 except:
818 pp = [nullid, nullid]
818 pp = [nullid, nullid]
819 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
819 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
820 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
820 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
821 short(node), short(pp[0]), short(pp[1])))
821 short(node), short(pp[0]), short(pp[1])))
822
822
823 def debugindexdot(ui, file_):
823 def debugindexdot(ui, file_):
824 """dump an index DAG as a .dot file"""
824 """dump an index DAG as a .dot file"""
825 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
825 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
826 ui.write("digraph G {\n")
826 ui.write("digraph G {\n")
827 for i in xrange(r.count()):
827 for i in xrange(r.count()):
828 node = r.node(i)
828 node = r.node(i)
829 pp = r.parents(node)
829 pp = r.parents(node)
830 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
830 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
831 if pp[1] != nullid:
831 if pp[1] != nullid:
832 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
832 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
833 ui.write("}\n")
833 ui.write("}\n")
834
834
835 def debuginstall(ui):
835 def debuginstall(ui):
836 '''test Mercurial installation'''
836 '''test Mercurial installation'''
837
837
838 def writetemp(contents):
838 def writetemp(contents):
839 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
839 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
840 f = os.fdopen(fd, "wb")
840 f = os.fdopen(fd, "wb")
841 f.write(contents)
841 f.write(contents)
842 f.close()
842 f.close()
843 return name
843 return name
844
844
845 problems = 0
845 problems = 0
846
846
847 # encoding
847 # encoding
848 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
848 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
849 try:
849 try:
850 util.fromlocal("test")
850 util.fromlocal("test")
851 except util.Abort, inst:
851 except util.Abort, inst:
852 ui.write(" %s\n" % inst)
852 ui.write(" %s\n" % inst)
853 ui.write(_(" (check that your locale is properly set)\n"))
853 ui.write(_(" (check that your locale is properly set)\n"))
854 problems += 1
854 problems += 1
855
855
856 # compiled modules
856 # compiled modules
857 ui.status(_("Checking extensions...\n"))
857 ui.status(_("Checking extensions...\n"))
858 try:
858 try:
859 import bdiff, mpatch, base85
859 import bdiff, mpatch, base85
860 except Exception, inst:
860 except Exception, inst:
861 ui.write(" %s\n" % inst)
861 ui.write(" %s\n" % inst)
862 ui.write(_(" One or more extensions could not be found"))
862 ui.write(_(" One or more extensions could not be found"))
863 ui.write(_(" (check that you compiled the extensions)\n"))
863 ui.write(_(" (check that you compiled the extensions)\n"))
864 problems += 1
864 problems += 1
865
865
866 # templates
866 # templates
867 ui.status(_("Checking templates...\n"))
867 ui.status(_("Checking templates...\n"))
868 try:
868 try:
869 import templater
869 import templater
870 t = templater.templater(templater.templatepath("map-cmdline.default"))
870 t = templater.templater(templater.templatepath("map-cmdline.default"))
871 except Exception, inst:
871 except Exception, inst:
872 ui.write(" %s\n" % inst)
872 ui.write(" %s\n" % inst)
873 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
873 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
874 problems += 1
874 problems += 1
875
875
876 # patch
876 # patch
877 ui.status(_("Checking patch...\n"))
877 ui.status(_("Checking patch...\n"))
878 patchproblems = 0
878 patchproblems = 0
879 a = "1\n2\n3\n4\n"
879 a = "1\n2\n3\n4\n"
880 b = "1\n2\n3\ninsert\n4\n"
880 b = "1\n2\n3\ninsert\n4\n"
881 fa = writetemp(a)
881 fa = writetemp(a)
882 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
882 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
883 os.path.basename(fa))
883 os.path.basename(fa))
884 fd = writetemp(d)
884 fd = writetemp(d)
885
885
886 files = {}
886 files = {}
887 try:
887 try:
888 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
888 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
889 except util.Abort, e:
889 except util.Abort, e:
890 ui.write(_(" patch call failed:\n"))
890 ui.write(_(" patch call failed:\n"))
891 ui.write(" " + str(e) + "\n")
891 ui.write(" " + str(e) + "\n")
892 patchproblems += 1
892 patchproblems += 1
893 else:
893 else:
894 if list(files) != [os.path.basename(fa)]:
894 if list(files) != [os.path.basename(fa)]:
895 ui.write(_(" unexpected patch output!\n"))
895 ui.write(_(" unexpected patch output!\n"))
896 patchproblems += 1
896 patchproblems += 1
897 a = file(fa).read()
897 a = file(fa).read()
898 if a != b:
898 if a != b:
899 ui.write(_(" patch test failed!\n"))
899 ui.write(_(" patch test failed!\n"))
900 patchproblems += 1
900 patchproblems += 1
901
901
902 if patchproblems:
902 if patchproblems:
903 if ui.config('ui', 'patch'):
903 if ui.config('ui', 'patch'):
904 ui.write(_(" (Current patch tool may be incompatible with patch,"
904 ui.write(_(" (Current patch tool may be incompatible with patch,"
905 " or misconfigured. Please check your .hgrc file)\n"))
905 " or misconfigured. Please check your .hgrc file)\n"))
906 else:
906 else:
907 ui.write(_(" Internal patcher failure, please report this error"
907 ui.write(_(" Internal patcher failure, please report this error"
908 " to http://www.selenic.com/mercurial/bts\n"))
908 " to http://www.selenic.com/mercurial/bts\n"))
909 problems += patchproblems
909 problems += patchproblems
910
910
911 os.unlink(fa)
911 os.unlink(fa)
912 os.unlink(fd)
912 os.unlink(fd)
913
913
914 # merge helper
914 # merge helper
915 ui.status(_("Checking merge helper...\n"))
915 ui.status(_("Checking merge helper...\n"))
916 cmd = (os.environ.get("HGMERGE") or ui.config("ui", "merge")
916 cmd = (os.environ.get("HGMERGE") or ui.config("ui", "merge")
917 or "hgmerge")
917 or "hgmerge")
918 cmdpath = util.find_exe(cmd) or util.find_exe(cmd.split()[0])
918 cmdpath = util.find_exe(cmd) or util.find_exe(cmd.split()[0])
919 if not cmdpath:
919 if not cmdpath:
920 if cmd == 'hgmerge':
920 if cmd == 'hgmerge':
921 ui.write(_(" No merge helper set and can't find default"
921 ui.write(_(" No merge helper set and can't find default"
922 " hgmerge script in PATH\n"))
922 " hgmerge script in PATH\n"))
923 ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
923 ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
924 else:
924 else:
925 ui.write(_(" Can't find merge helper '%s' in PATH\n") % cmd)
925 ui.write(_(" Can't find merge helper '%s' in PATH\n") % cmd)
926 ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
926 ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
927 problems += 1
927 problems += 1
928 else:
928 else:
929 # actually attempt a patch here
929 # actually attempt a patch here
930 fa = writetemp("1\n2\n3\n4\n")
930 fa = writetemp("1\n2\n3\n4\n")
931 fl = writetemp("1\n2\n3\ninsert\n4\n")
931 fl = writetemp("1\n2\n3\ninsert\n4\n")
932 fr = writetemp("begin\n1\n2\n3\n4\n")
932 fr = writetemp("begin\n1\n2\n3\n4\n")
933 r = util.system('%s "%s" "%s" "%s"' % (cmd, fl, fa, fr))
933 r = util.system('%s "%s" "%s" "%s"' % (cmd, fl, fa, fr))
934 if r:
934 if r:
935 ui.write(_(" Got unexpected merge error %d!\n") % r)
935 ui.write(_(" Got unexpected merge error %d!\n") % r)
936 problems += 1
936 problems += 1
937 m = file(fl).read()
937 m = file(fl).read()
938 if m != "begin\n1\n2\n3\ninsert\n4\n":
938 if m != "begin\n1\n2\n3\ninsert\n4\n":
939 ui.write(_(" Got unexpected merge results!\n"))
939 ui.write(_(" Got unexpected merge results!\n"))
940 ui.write(_(" (your merge helper may have the"
940 ui.write(_(" (your merge helper may have the"
941 " wrong argument order)\n"))
941 " wrong argument order)\n"))
942 ui.write(_(" Result: %r\n") % m)
942 ui.write(_(" Result: %r\n") % m)
943 problems += 1
943 problems += 1
944 os.unlink(fa)
944 os.unlink(fa)
945 os.unlink(fl)
945 os.unlink(fl)
946 os.unlink(fr)
946 os.unlink(fr)
947
947
948 # editor
948 # editor
949 ui.status(_("Checking commit editor...\n"))
949 ui.status(_("Checking commit editor...\n"))
950 editor = (os.environ.get("HGEDITOR") or
950 editor = (os.environ.get("HGEDITOR") or
951 ui.config("ui", "editor") or
951 ui.config("ui", "editor") or
952 os.environ.get("EDITOR", "vi"))
952 os.environ.get("EDITOR", "vi"))
953 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
953 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
954 if not cmdpath:
954 if not cmdpath:
955 if editor == 'vi':
955 if editor == 'vi':
956 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
956 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
957 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
957 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
958 else:
958 else:
959 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
959 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
960 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
960 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
961 problems += 1
961 problems += 1
962
962
963 # check username
963 # check username
964 ui.status(_("Checking username...\n"))
964 ui.status(_("Checking username...\n"))
965 user = os.environ.get("HGUSER")
965 user = os.environ.get("HGUSER")
966 if user is None:
966 if user is None:
967 user = ui.config("ui", "username")
967 user = ui.config("ui", "username")
968 if user is None:
968 if user is None:
969 user = os.environ.get("EMAIL")
969 user = os.environ.get("EMAIL")
970 if not user:
970 if not user:
971 ui.warn(" ")
971 ui.warn(" ")
972 ui.username()
972 ui.username()
973 ui.write(_(" (specify a username in your .hgrc file)\n"))
973 ui.write(_(" (specify a username in your .hgrc file)\n"))
974
974
975 if not problems:
975 if not problems:
976 ui.status(_("No problems detected\n"))
976 ui.status(_("No problems detected\n"))
977 else:
977 else:
978 ui.write(_("%s problems detected,"
978 ui.write(_("%s problems detected,"
979 " please check your install!\n") % problems)
979 " please check your install!\n") % problems)
980
980
981 return problems
981 return problems
982
982
983 def debugrename(ui, repo, file1, *pats, **opts):
983 def debugrename(ui, repo, file1, *pats, **opts):
984 """dump rename information"""
984 """dump rename information"""
985
985
986 ctx = repo.changectx(opts.get('rev', 'tip'))
986 ctx = repo.changectx(opts.get('rev', 'tip'))
987 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
987 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
988 ctx.node()):
988 ctx.node()):
989 m = ctx.filectx(abs).renamed()
989 m = ctx.filectx(abs).renamed()
990 if m:
990 if m:
991 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
991 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
992 else:
992 else:
993 ui.write(_("%s not renamed\n") % rel)
993 ui.write(_("%s not renamed\n") % rel)
994
994
995 def debugwalk(ui, repo, *pats, **opts):
995 def debugwalk(ui, repo, *pats, **opts):
996 """show how files match on given patterns"""
996 """show how files match on given patterns"""
997 items = list(cmdutil.walk(repo, pats, opts))
997 items = list(cmdutil.walk(repo, pats, opts))
998 if not items:
998 if not items:
999 return
999 return
1000 fmt = '%%s %%-%ds %%-%ds %%s' % (
1000 fmt = '%%s %%-%ds %%-%ds %%s' % (
1001 max([len(abs) for (src, abs, rel, exact) in items]),
1001 max([len(abs) for (src, abs, rel, exact) in items]),
1002 max([len(rel) for (src, abs, rel, exact) in items]))
1002 max([len(rel) for (src, abs, rel, exact) in items]))
1003 for src, abs, rel, exact in items:
1003 for src, abs, rel, exact in items:
1004 line = fmt % (src, abs, rel, exact and 'exact' or '')
1004 line = fmt % (src, abs, rel, exact and 'exact' or '')
1005 ui.write("%s\n" % line.rstrip())
1005 ui.write("%s\n" % line.rstrip())
1006
1006
1007 def diff(ui, repo, *pats, **opts):
1007 def diff(ui, repo, *pats, **opts):
1008 """diff repository (or selected files)
1008 """diff repository (or selected files)
1009
1009
1010 Show differences between revisions for the specified files.
1010 Show differences between revisions for the specified files.
1011
1011
1012 Differences between files are shown using the unified diff format.
1012 Differences between files are shown using the unified diff format.
1013
1013
1014 NOTE: diff may generate unexpected results for merges, as it will
1014 NOTE: diff may generate unexpected results for merges, as it will
1015 default to comparing against the working directory's first parent
1015 default to comparing against the working directory's first parent
1016 changeset if no revisions are specified.
1016 changeset if no revisions are specified.
1017
1017
1018 When two revision arguments are given, then changes are shown
1018 When two revision arguments are given, then changes are shown
1019 between those revisions. If only one revision is specified then
1019 between those revisions. If only one revision is specified then
1020 that revision is compared to the working directory, and, when no
1020 that revision is compared to the working directory, and, when no
1021 revisions are specified, the working directory files are compared
1021 revisions are specified, the working directory files are compared
1022 to its parent.
1022 to its parent.
1023
1023
1024 Without the -a option, diff will avoid generating diffs of files
1024 Without the -a option, diff will avoid generating diffs of files
1025 it detects as binary. With -a, diff will generate a diff anyway,
1025 it detects as binary. With -a, diff will generate a diff anyway,
1026 probably with undesirable results.
1026 probably with undesirable results.
1027 """
1027 """
1028 node1, node2 = cmdutil.revpair(repo, opts['rev'])
1028 node1, node2 = cmdutil.revpair(repo, opts['rev'])
1029
1029
1030 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1030 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1031
1031
1032 patch.diff(repo, node1, node2, fns, match=matchfn,
1032 patch.diff(repo, node1, node2, fns, match=matchfn,
1033 opts=patch.diffopts(ui, opts))
1033 opts=patch.diffopts(ui, opts))
1034
1034
1035 def export(ui, repo, *changesets, **opts):
1035 def export(ui, repo, *changesets, **opts):
1036 """dump the header and diffs for one or more changesets
1036 """dump the header and diffs for one or more changesets
1037
1037
1038 Print the changeset header and diffs for one or more revisions.
1038 Print the changeset header and diffs for one or more revisions.
1039
1039
1040 The information shown in the changeset header is: author,
1040 The information shown in the changeset header is: author,
1041 changeset hash, parent(s) and commit comment.
1041 changeset hash, parent(s) and commit comment.
1042
1042
1043 NOTE: export may generate unexpected diff output for merge changesets,
1043 NOTE: export may generate unexpected diff output for merge changesets,
1044 as it will compare the merge changeset against its first parent only.
1044 as it will compare the merge changeset against its first parent only.
1045
1045
1046 Output may be to a file, in which case the name of the file is
1046 Output may be to a file, in which case the name of the file is
1047 given using a format string. The formatting rules are as follows:
1047 given using a format string. The formatting rules are as follows:
1048
1048
1049 %% literal "%" character
1049 %% literal "%" character
1050 %H changeset hash (40 bytes of hexadecimal)
1050 %H changeset hash (40 bytes of hexadecimal)
1051 %N number of patches being generated
1051 %N number of patches being generated
1052 %R changeset revision number
1052 %R changeset revision number
1053 %b basename of the exporting repository
1053 %b basename of the exporting repository
1054 %h short-form changeset hash (12 bytes of hexadecimal)
1054 %h short-form changeset hash (12 bytes of hexadecimal)
1055 %n zero-padded sequence number, starting at 1
1055 %n zero-padded sequence number, starting at 1
1056 %r zero-padded changeset revision number
1056 %r zero-padded changeset revision number
1057
1057
1058 Without the -a option, export will avoid generating diffs of files
1058 Without the -a option, export will avoid generating diffs of files
1059 it detects as binary. With -a, export will generate a diff anyway,
1059 it detects as binary. With -a, export will generate a diff anyway,
1060 probably with undesirable results.
1060 probably with undesirable results.
1061
1061
1062 With the --switch-parent option, the diff will be against the second
1062 With the --switch-parent option, the diff will be against the second
1063 parent. It can be useful to review a merge.
1063 parent. It can be useful to review a merge.
1064 """
1064 """
1065 if not changesets:
1065 if not changesets:
1066 raise util.Abort(_("export requires at least one changeset"))
1066 raise util.Abort(_("export requires at least one changeset"))
1067 revs = cmdutil.revrange(repo, changesets)
1067 revs = cmdutil.revrange(repo, changesets)
1068 if len(revs) > 1:
1068 if len(revs) > 1:
1069 ui.note(_('exporting patches:\n'))
1069 ui.note(_('exporting patches:\n'))
1070 else:
1070 else:
1071 ui.note(_('exporting patch:\n'))
1071 ui.note(_('exporting patch:\n'))
1072 patch.export(repo, revs, template=opts['output'],
1072 patch.export(repo, revs, template=opts['output'],
1073 switch_parent=opts['switch_parent'],
1073 switch_parent=opts['switch_parent'],
1074 opts=patch.diffopts(ui, opts))
1074 opts=patch.diffopts(ui, opts))
1075
1075
1076 def grep(ui, repo, pattern, *pats, **opts):
1076 def grep(ui, repo, pattern, *pats, **opts):
1077 """search for a pattern in specified files and revisions
1077 """search for a pattern in specified files and revisions
1078
1078
1079 Search revisions of files for a regular expression.
1079 Search revisions of files for a regular expression.
1080
1080
1081 This command behaves differently than Unix grep. It only accepts
1081 This command behaves differently than Unix grep. It only accepts
1082 Python/Perl regexps. It searches repository history, not the
1082 Python/Perl regexps. It searches repository history, not the
1083 working directory. It always prints the revision number in which
1083 working directory. It always prints the revision number in which
1084 a match appears.
1084 a match appears.
1085
1085
1086 By default, grep only prints output for the first revision of a
1086 By default, grep only prints output for the first revision of a
1087 file in which it finds a match. To get it to print every revision
1087 file in which it finds a match. To get it to print every revision
1088 that contains a change in match status ("-" for a match that
1088 that contains a change in match status ("-" for a match that
1089 becomes a non-match, or "+" for a non-match that becomes a match),
1089 becomes a non-match, or "+" for a non-match that becomes a match),
1090 use the --all flag.
1090 use the --all flag.
1091 """
1091 """
1092 reflags = 0
1092 reflags = 0
1093 if opts['ignore_case']:
1093 if opts['ignore_case']:
1094 reflags |= re.I
1094 reflags |= re.I
1095 try:
1095 try:
1096 regexp = re.compile(pattern, reflags)
1096 regexp = re.compile(pattern, reflags)
1097 except Exception, inst:
1097 except Exception, inst:
1098 ui.warn(_("grep: invalid match pattern: %s!\n") % inst)
1098 ui.warn(_("grep: invalid match pattern: %s!\n") % inst)
1099 return None
1099 return None
1100 sep, eol = ':', '\n'
1100 sep, eol = ':', '\n'
1101 if opts['print0']:
1101 if opts['print0']:
1102 sep = eol = '\0'
1102 sep = eol = '\0'
1103
1103
1104 fcache = {}
1104 fcache = {}
1105 def getfile(fn):
1105 def getfile(fn):
1106 if fn not in fcache:
1106 if fn not in fcache:
1107 fcache[fn] = repo.file(fn)
1107 fcache[fn] = repo.file(fn)
1108 return fcache[fn]
1108 return fcache[fn]
1109
1109
1110 def matchlines(body):
1110 def matchlines(body):
1111 begin = 0
1111 begin = 0
1112 linenum = 0
1112 linenum = 0
1113 while True:
1113 while True:
1114 match = regexp.search(body, begin)
1114 match = regexp.search(body, begin)
1115 if not match:
1115 if not match:
1116 break
1116 break
1117 mstart, mend = match.span()
1117 mstart, mend = match.span()
1118 linenum += body.count('\n', begin, mstart) + 1
1118 linenum += body.count('\n', begin, mstart) + 1
1119 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1119 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1120 lend = body.find('\n', mend)
1120 lend = body.find('\n', mend)
1121 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1121 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1122 begin = lend + 1
1122 begin = lend + 1
1123
1123
1124 class linestate(object):
1124 class linestate(object):
1125 def __init__(self, line, linenum, colstart, colend):
1125 def __init__(self, line, linenum, colstart, colend):
1126 self.line = line
1126 self.line = line
1127 self.linenum = linenum
1127 self.linenum = linenum
1128 self.colstart = colstart
1128 self.colstart = colstart
1129 self.colend = colend
1129 self.colend = colend
1130
1130
1131 def __eq__(self, other):
1131 def __eq__(self, other):
1132 return self.line == other.line
1132 return self.line == other.line
1133
1133
1134 matches = {}
1134 matches = {}
1135 copies = {}
1135 copies = {}
1136 def grepbody(fn, rev, body):
1136 def grepbody(fn, rev, body):
1137 matches[rev].setdefault(fn, [])
1137 matches[rev].setdefault(fn, [])
1138 m = matches[rev][fn]
1138 m = matches[rev][fn]
1139 for lnum, cstart, cend, line in matchlines(body):
1139 for lnum, cstart, cend, line in matchlines(body):
1140 s = linestate(line, lnum, cstart, cend)
1140 s = linestate(line, lnum, cstart, cend)
1141 m.append(s)
1141 m.append(s)
1142
1142
1143 def difflinestates(a, b):
1143 def difflinestates(a, b):
1144 sm = difflib.SequenceMatcher(None, a, b)
1144 sm = difflib.SequenceMatcher(None, a, b)
1145 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1145 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1146 if tag == 'insert':
1146 if tag == 'insert':
1147 for i in xrange(blo, bhi):
1147 for i in xrange(blo, bhi):
1148 yield ('+', b[i])
1148 yield ('+', b[i])
1149 elif tag == 'delete':
1149 elif tag == 'delete':
1150 for i in xrange(alo, ahi):
1150 for i in xrange(alo, ahi):
1151 yield ('-', a[i])
1151 yield ('-', a[i])
1152 elif tag == 'replace':
1152 elif tag == 'replace':
1153 for i in xrange(alo, ahi):
1153 for i in xrange(alo, ahi):
1154 yield ('-', a[i])
1154 yield ('-', a[i])
1155 for i in xrange(blo, bhi):
1155 for i in xrange(blo, bhi):
1156 yield ('+', b[i])
1156 yield ('+', b[i])
1157
1157
1158 prev = {}
1158 prev = {}
1159 def display(fn, rev, states, prevstates):
1159 def display(fn, rev, states, prevstates):
1160 found = False
1160 found = False
1161 filerevmatches = {}
1161 filerevmatches = {}
1162 r = prev.get(fn, -1)
1162 r = prev.get(fn, -1)
1163 if opts['all']:
1163 if opts['all']:
1164 iter = difflinestates(states, prevstates)
1164 iter = difflinestates(states, prevstates)
1165 else:
1165 else:
1166 iter = [('', l) for l in prevstates]
1166 iter = [('', l) for l in prevstates]
1167 for change, l in iter:
1167 for change, l in iter:
1168 cols = [fn, str(r)]
1168 cols = [fn, str(r)]
1169 if opts['line_number']:
1169 if opts['line_number']:
1170 cols.append(str(l.linenum))
1170 cols.append(str(l.linenum))
1171 if opts['all']:
1171 if opts['all']:
1172 cols.append(change)
1172 cols.append(change)
1173 if opts['user']:
1173 if opts['user']:
1174 cols.append(ui.shortuser(get(r)[1]))
1174 cols.append(ui.shortuser(get(r)[1]))
1175 if opts['files_with_matches']:
1175 if opts['files_with_matches']:
1176 c = (fn, r)
1176 c = (fn, r)
1177 if c in filerevmatches:
1177 if c in filerevmatches:
1178 continue
1178 continue
1179 filerevmatches[c] = 1
1179 filerevmatches[c] = 1
1180 else:
1180 else:
1181 cols.append(l.line)
1181 cols.append(l.line)
1182 ui.write(sep.join(cols), eol)
1182 ui.write(sep.join(cols), eol)
1183 found = True
1183 found = True
1184 return found
1184 return found
1185
1185
1186 fstate = {}
1186 fstate = {}
1187 skip = {}
1187 skip = {}
1188 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1188 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1189 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1189 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1190 found = False
1190 found = False
1191 follow = opts.get('follow')
1191 follow = opts.get('follow')
1192 for st, rev, fns in changeiter:
1192 for st, rev, fns in changeiter:
1193 if st == 'window':
1193 if st == 'window':
1194 matches.clear()
1194 matches.clear()
1195 elif st == 'add':
1195 elif st == 'add':
1196 mf = repo.changectx(rev).manifest()
1196 mf = repo.changectx(rev).manifest()
1197 matches[rev] = {}
1197 matches[rev] = {}
1198 for fn in fns:
1198 for fn in fns:
1199 if fn in skip:
1199 if fn in skip:
1200 continue
1200 continue
1201 try:
1201 try:
1202 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1202 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1203 fstate.setdefault(fn, [])
1203 fstate.setdefault(fn, [])
1204 if follow:
1204 if follow:
1205 copied = getfile(fn).renamed(mf[fn])
1205 copied = getfile(fn).renamed(mf[fn])
1206 if copied:
1206 if copied:
1207 copies.setdefault(rev, {})[fn] = copied[0]
1207 copies.setdefault(rev, {})[fn] = copied[0]
1208 except KeyError:
1208 except KeyError:
1209 pass
1209 pass
1210 elif st == 'iter':
1210 elif st == 'iter':
1211 states = matches[rev].items()
1211 states = matches[rev].items()
1212 states.sort()
1212 states.sort()
1213 for fn, m in states:
1213 for fn, m in states:
1214 copy = copies.get(rev, {}).get(fn)
1214 copy = copies.get(rev, {}).get(fn)
1215 if fn in skip:
1215 if fn in skip:
1216 if copy:
1216 if copy:
1217 skip[copy] = True
1217 skip[copy] = True
1218 continue
1218 continue
1219 if fn in prev or fstate[fn]:
1219 if fn in prev or fstate[fn]:
1220 r = display(fn, rev, m, fstate[fn])
1220 r = display(fn, rev, m, fstate[fn])
1221 found = found or r
1221 found = found or r
1222 if r and not opts['all']:
1222 if r and not opts['all']:
1223 skip[fn] = True
1223 skip[fn] = True
1224 if copy:
1224 if copy:
1225 skip[copy] = True
1225 skip[copy] = True
1226 fstate[fn] = m
1226 fstate[fn] = m
1227 if copy:
1227 if copy:
1228 fstate[copy] = m
1228 fstate[copy] = m
1229 prev[fn] = rev
1229 prev[fn] = rev
1230
1230
1231 fstate = fstate.items()
1231 fstate = fstate.items()
1232 fstate.sort()
1232 fstate.sort()
1233 for fn, state in fstate:
1233 for fn, state in fstate:
1234 if fn in skip:
1234 if fn in skip:
1235 continue
1235 continue
1236 if fn not in copies.get(prev[fn], {}):
1236 if fn not in copies.get(prev[fn], {}):
1237 found = display(fn, rev, {}, state) or found
1237 found = display(fn, rev, {}, state) or found
1238 return (not found and 1) or 0
1238 return (not found and 1) or 0
1239
1239
1240 def heads(ui, repo, *branchrevs, **opts):
1240 def heads(ui, repo, *branchrevs, **opts):
1241 """show current repository heads or show branch heads
1241 """show current repository heads or show branch heads
1242
1242
1243 With no arguments, show all repository head changesets.
1243 With no arguments, show all repository head changesets.
1244
1244
1245 If branch or revisions names are given this will show the heads of
1245 If branch or revisions names are given this will show the heads of
1246 the specified branches or the branches those revisions are tagged
1246 the specified branches or the branches those revisions are tagged
1247 with.
1247 with.
1248
1248
1249 Repository "heads" are changesets that don't have child
1249 Repository "heads" are changesets that don't have child
1250 changesets. They are where development generally takes place and
1250 changesets. They are where development generally takes place and
1251 are the usual targets for update and merge operations.
1251 are the usual targets for update and merge operations.
1252
1252
1253 Branch heads are changesets that have a given branch tag, but have
1253 Branch heads are changesets that have a given branch tag, but have
1254 no child changesets with that tag. They are usually where
1254 no child changesets with that tag. They are usually where
1255 development on the given branch takes place.
1255 development on the given branch takes place.
1256 """
1256 """
1257 if opts['rev']:
1257 if opts['rev']:
1258 start = repo.lookup(opts['rev'])
1258 start = repo.lookup(opts['rev'])
1259 else:
1259 else:
1260 start = None
1260 start = None
1261 if not branchrevs:
1261 if not branchrevs:
1262 # Assume we're looking repo-wide heads if no revs were specified.
1262 # Assume we're looking repo-wide heads if no revs were specified.
1263 heads = repo.heads(start)
1263 heads = repo.heads(start)
1264 else:
1264 else:
1265 heads = []
1265 heads = []
1266 visitedset = util.set()
1266 visitedset = util.set()
1267 for branchrev in branchrevs:
1267 for branchrev in branchrevs:
1268 branch = repo.changectx(branchrev).branch()
1268 branch = repo.changectx(branchrev).branch()
1269 if branch in visitedset:
1269 if branch in visitedset:
1270 continue
1270 continue
1271 visitedset.add(branch)
1271 visitedset.add(branch)
1272 bheads = repo.branchheads(branch, start)
1272 bheads = repo.branchheads(branch, start)
1273 if not bheads:
1273 if not bheads:
1274 if branch != branchrev:
1274 if branch != branchrev:
1275 ui.warn(_("no changes on branch %s containing %s are "
1275 ui.warn(_("no changes on branch %s containing %s are "
1276 "reachable from %s\n")
1276 "reachable from %s\n")
1277 % (branch, branchrev, opts['rev']))
1277 % (branch, branchrev, opts['rev']))
1278 else:
1278 else:
1279 ui.warn(_("no changes on branch %s are reachable from %s\n")
1279 ui.warn(_("no changes on branch %s are reachable from %s\n")
1280 % (branch, opts['rev']))
1280 % (branch, opts['rev']))
1281 heads.extend(bheads)
1281 heads.extend(bheads)
1282 if not heads:
1282 if not heads:
1283 return 1
1283 return 1
1284 displayer = cmdutil.show_changeset(ui, repo, opts)
1284 displayer = cmdutil.show_changeset(ui, repo, opts)
1285 for n in heads:
1285 for n in heads:
1286 displayer.show(changenode=n)
1286 displayer.show(changenode=n)
1287
1287
1288 def help_(ui, name=None, with_version=False):
1288 def help_(ui, name=None, with_version=False):
1289 """show help for a command, extension, or list of commands
1289 """show help for a command, extension, or list of commands
1290
1290
1291 With no arguments, print a list of commands and short help.
1291 With no arguments, print a list of commands and short help.
1292
1292
1293 Given a command name, print help for that command.
1293 Given a command name, print help for that command.
1294
1294
1295 Given an extension name, print help for that extension, and the
1295 Given an extension name, print help for that extension, and the
1296 commands it provides."""
1296 commands it provides."""
1297 option_lists = []
1297 option_lists = []
1298
1298
1299 def addglobalopts(aliases):
1299 def addglobalopts(aliases):
1300 if ui.verbose:
1300 if ui.verbose:
1301 option_lists.append((_("global options:"), globalopts))
1301 option_lists.append((_("global options:"), globalopts))
1302 if name == 'shortlist':
1302 if name == 'shortlist':
1303 option_lists.append((_('use "hg help" for the full list '
1303 option_lists.append((_('use "hg help" for the full list '
1304 'of commands'), ()))
1304 'of commands'), ()))
1305 else:
1305 else:
1306 if name == 'shortlist':
1306 if name == 'shortlist':
1307 msg = _('use "hg help" for the full list of commands '
1307 msg = _('use "hg help" for the full list of commands '
1308 'or "hg -v" for details')
1308 'or "hg -v" for details')
1309 elif aliases:
1309 elif aliases:
1310 msg = _('use "hg -v help%s" to show aliases and '
1310 msg = _('use "hg -v help%s" to show aliases and '
1311 'global options') % (name and " " + name or "")
1311 'global options') % (name and " " + name or "")
1312 else:
1312 else:
1313 msg = _('use "hg -v help %s" to show global options') % name
1313 msg = _('use "hg -v help %s" to show global options') % name
1314 option_lists.append((msg, ()))
1314 option_lists.append((msg, ()))
1315
1315
1316 def helpcmd(name):
1316 def helpcmd(name):
1317 if with_version:
1317 if with_version:
1318 version_(ui)
1318 version_(ui)
1319 ui.write('\n')
1319 ui.write('\n')
1320 aliases, i = cmdutil.findcmd(ui, name, table)
1320 aliases, i = cmdutil.findcmd(ui, name, table)
1321 # synopsis
1321 # synopsis
1322 ui.write("%s\n\n" % i[2])
1322 ui.write("%s\n\n" % i[2])
1323
1323
1324 # description
1324 # description
1325 doc = i[0].__doc__
1325 doc = i[0].__doc__
1326 if not doc:
1326 if not doc:
1327 doc = _("(No help text available)")
1327 doc = _("(No help text available)")
1328 if ui.quiet:
1328 if ui.quiet:
1329 doc = doc.splitlines(0)[0]
1329 doc = doc.splitlines(0)[0]
1330 ui.write("%s\n" % doc.rstrip())
1330 ui.write("%s\n" % doc.rstrip())
1331
1331
1332 if not ui.quiet:
1332 if not ui.quiet:
1333 # aliases
1333 # aliases
1334 if len(aliases) > 1:
1334 if len(aliases) > 1:
1335 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1335 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1336
1336
1337 # options
1337 # options
1338 if i[1]:
1338 if i[1]:
1339 option_lists.append((_("options:\n"), i[1]))
1339 option_lists.append((_("options:\n"), i[1]))
1340
1340
1341 addglobalopts(False)
1341 addglobalopts(False)
1342
1342
1343 def helplist(header, select=None):
1343 def helplist(header, select=None):
1344 h = {}
1344 h = {}
1345 cmds = {}
1345 cmds = {}
1346 for c, e in table.items():
1346 for c, e in table.items():
1347 f = c.split("|", 1)[0]
1347 f = c.split("|", 1)[0]
1348 if select and not select(f):
1348 if select and not select(f):
1349 continue
1349 continue
1350 if name == "shortlist" and not f.startswith("^"):
1350 if name == "shortlist" and not f.startswith("^"):
1351 continue
1351 continue
1352 f = f.lstrip("^")
1352 f = f.lstrip("^")
1353 if not ui.debugflag and f.startswith("debug"):
1353 if not ui.debugflag and f.startswith("debug"):
1354 continue
1354 continue
1355 doc = e[0].__doc__
1355 doc = e[0].__doc__
1356 if not doc:
1356 if not doc:
1357 doc = _("(No help text available)")
1357 doc = _("(No help text available)")
1358 h[f] = doc.splitlines(0)[0].rstrip()
1358 h[f] = doc.splitlines(0)[0].rstrip()
1359 cmds[f] = c.lstrip("^")
1359 cmds[f] = c.lstrip("^")
1360
1360
1361 if not h:
1361 if not h:
1362 ui.status(_('no commands defined\n'))
1362 ui.status(_('no commands defined\n'))
1363 return
1363 return
1364
1364
1365 ui.status(header)
1365 ui.status(header)
1366 fns = h.keys()
1366 fns = h.keys()
1367 fns.sort()
1367 fns.sort()
1368 m = max(map(len, fns))
1368 m = max(map(len, fns))
1369 for f in fns:
1369 for f in fns:
1370 if ui.verbose:
1370 if ui.verbose:
1371 commands = cmds[f].replace("|",", ")
1371 commands = cmds[f].replace("|",", ")
1372 ui.write(" %s:\n %s\n"%(commands, h[f]))
1372 ui.write(" %s:\n %s\n"%(commands, h[f]))
1373 else:
1373 else:
1374 ui.write(' %-*s %s\n' % (m, f, h[f]))
1374 ui.write(' %-*s %s\n' % (m, f, h[f]))
1375
1375
1376 if not ui.quiet:
1376 if not ui.quiet:
1377 addglobalopts(True)
1377 addglobalopts(True)
1378
1378
1379 def helptopic(name):
1379 def helptopic(name):
1380 v = None
1380 v = None
1381 for i in help.helptable:
1381 for i in help.helptable:
1382 l = i.split('|')
1382 l = i.split('|')
1383 if name in l:
1383 if name in l:
1384 v = i
1384 v = i
1385 header = l[-1]
1385 header = l[-1]
1386 if not v:
1386 if not v:
1387 raise cmdutil.UnknownCommand(name)
1387 raise cmdutil.UnknownCommand(name)
1388
1388
1389 # description
1389 # description
1390 doc = help.helptable[v]
1390 doc = help.helptable[v]
1391 if not doc:
1391 if not doc:
1392 doc = _("(No help text available)")
1392 doc = _("(No help text available)")
1393 if callable(doc):
1393 if callable(doc):
1394 doc = doc()
1394 doc = doc()
1395
1395
1396 ui.write("%s\n" % header)
1396 ui.write("%s\n" % header)
1397 ui.write("%s\n" % doc.rstrip())
1397 ui.write("%s\n" % doc.rstrip())
1398
1398
1399 def helpext(name):
1399 def helpext(name):
1400 try:
1400 try:
1401 mod = extensions.find(name)
1401 mod = extensions.find(name)
1402 except KeyError:
1402 except KeyError:
1403 raise cmdutil.UnknownCommand(name)
1403 raise cmdutil.UnknownCommand(name)
1404
1404
1405 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1405 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1406 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1406 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1407 for d in doc[1:]:
1407 for d in doc[1:]:
1408 ui.write(d, '\n')
1408 ui.write(d, '\n')
1409
1409
1410 ui.status('\n')
1410 ui.status('\n')
1411
1411
1412 try:
1412 try:
1413 ct = mod.cmdtable
1413 ct = mod.cmdtable
1414 except AttributeError:
1414 except AttributeError:
1415 ct = {}
1415 ct = {}
1416
1416
1417 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1417 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1418 helplist(_('list of commands:\n\n'), modcmds.has_key)
1418 helplist(_('list of commands:\n\n'), modcmds.has_key)
1419
1419
1420 if name and name != 'shortlist':
1420 if name and name != 'shortlist':
1421 i = None
1421 i = None
1422 for f in (helpcmd, helptopic, helpext):
1422 for f in (helpcmd, helptopic, helpext):
1423 try:
1423 try:
1424 f(name)
1424 f(name)
1425 i = None
1425 i = None
1426 break
1426 break
1427 except cmdutil.UnknownCommand, inst:
1427 except cmdutil.UnknownCommand, inst:
1428 i = inst
1428 i = inst
1429 if i:
1429 if i:
1430 raise i
1430 raise i
1431
1431
1432 else:
1432 else:
1433 # program name
1433 # program name
1434 if ui.verbose or with_version:
1434 if ui.verbose or with_version:
1435 version_(ui)
1435 version_(ui)
1436 else:
1436 else:
1437 ui.status(_("Mercurial Distributed SCM\n"))
1437 ui.status(_("Mercurial Distributed SCM\n"))
1438 ui.status('\n')
1438 ui.status('\n')
1439
1439
1440 # list of commands
1440 # list of commands
1441 if name == "shortlist":
1441 if name == "shortlist":
1442 header = _('basic commands:\n\n')
1442 header = _('basic commands:\n\n')
1443 else:
1443 else:
1444 header = _('list of commands:\n\n')
1444 header = _('list of commands:\n\n')
1445
1445
1446 helplist(header)
1446 helplist(header)
1447
1447
1448 # list all option lists
1448 # list all option lists
1449 opt_output = []
1449 opt_output = []
1450 for title, options in option_lists:
1450 for title, options in option_lists:
1451 opt_output.append(("\n%s" % title, None))
1451 opt_output.append(("\n%s" % title, None))
1452 for shortopt, longopt, default, desc in options:
1452 for shortopt, longopt, default, desc in options:
1453 if "DEPRECATED" in desc and not ui.verbose: continue
1453 if "DEPRECATED" in desc and not ui.verbose: continue
1454 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1454 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1455 longopt and " --%s" % longopt),
1455 longopt and " --%s" % longopt),
1456 "%s%s" % (desc,
1456 "%s%s" % (desc,
1457 default
1457 default
1458 and _(" (default: %s)") % default
1458 and _(" (default: %s)") % default
1459 or "")))
1459 or "")))
1460
1460
1461 if opt_output:
1461 if opt_output:
1462 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1462 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1463 for first, second in opt_output:
1463 for first, second in opt_output:
1464 if second:
1464 if second:
1465 ui.write(" %-*s %s\n" % (opts_len, first, second))
1465 ui.write(" %-*s %s\n" % (opts_len, first, second))
1466 else:
1466 else:
1467 ui.write("%s\n" % first)
1467 ui.write("%s\n" % first)
1468
1468
1469 def identify(ui, repo, source=None,
1469 def identify(ui, repo, source=None,
1470 rev=None, num=None, id=None, branch=None, tags=None):
1470 rev=None, num=None, id=None, branch=None, tags=None):
1471 """identify the working copy or specified revision
1471 """identify the working copy or specified revision
1472
1472
1473 With no revision, print a summary of the current state of the repo.
1473 With no revision, print a summary of the current state of the repo.
1474
1474
1475 With a path, do a lookup in another repository.
1475 With a path, do a lookup in another repository.
1476
1476
1477 This summary identifies the repository state using one or two parent
1477 This summary identifies the repository state using one or two parent
1478 hash identifiers, followed by a "+" if there are uncommitted changes
1478 hash identifiers, followed by a "+" if there are uncommitted changes
1479 in the working directory, a list of tags for this revision and a branch
1479 in the working directory, a list of tags for this revision and a branch
1480 name for non-default branches.
1480 name for non-default branches.
1481 """
1481 """
1482
1482
1483 if not repo and not source:
1483 if not repo and not source:
1484 raise util.Abort(_("There is no Mercurial repository here "
1484 raise util.Abort(_("There is no Mercurial repository here "
1485 "(.hg not found)"))
1485 "(.hg not found)"))
1486
1486
1487 hexfunc = ui.debugflag and hex or short
1487 hexfunc = ui.debugflag and hex or short
1488 default = not (num or id or branch or tags)
1488 default = not (num or id or branch or tags)
1489 output = []
1489 output = []
1490
1490
1491 if source:
1491 if source:
1492 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1492 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1493 srepo = hg.repository(ui, source)
1493 srepo = hg.repository(ui, source)
1494 if not rev and revs:
1494 if not rev and revs:
1495 rev = revs[0]
1495 rev = revs[0]
1496 if not rev:
1496 if not rev:
1497 rev = "tip"
1497 rev = "tip"
1498 if num or branch or tags:
1498 if num or branch or tags:
1499 raise util.Abort(
1499 raise util.Abort(
1500 "can't query remote revision number, branch, or tags")
1500 "can't query remote revision number, branch, or tags")
1501 output = [hexfunc(srepo.lookup(rev))]
1501 output = [hexfunc(srepo.lookup(rev))]
1502 elif not rev:
1502 elif not rev:
1503 ctx = repo.workingctx()
1503 ctx = repo.workingctx()
1504 parents = ctx.parents()
1504 parents = ctx.parents()
1505 changed = False
1505 changed = False
1506 if default or id or num:
1506 if default or id or num:
1507 changed = ctx.files() + ctx.deleted()
1507 changed = ctx.files() + ctx.deleted()
1508 if default or id:
1508 if default or id:
1509 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1509 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1510 (changed) and "+" or "")]
1510 (changed) and "+" or "")]
1511 if num:
1511 if num:
1512 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1512 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1513 (changed) and "+" or ""))
1513 (changed) and "+" or ""))
1514 else:
1514 else:
1515 ctx = repo.changectx(rev)
1515 ctx = repo.changectx(rev)
1516 if default or id:
1516 if default or id:
1517 output = [hexfunc(ctx.node())]
1517 output = [hexfunc(ctx.node())]
1518 if num:
1518 if num:
1519 output.append(str(ctx.rev()))
1519 output.append(str(ctx.rev()))
1520
1520
1521 if not source and default and not ui.quiet:
1521 if not source and default and not ui.quiet:
1522 b = util.tolocal(ctx.branch())
1522 b = util.tolocal(ctx.branch())
1523 if b != 'default':
1523 if b != 'default':
1524 output.append("(%s)" % b)
1524 output.append("(%s)" % b)
1525
1525
1526 # multiple tags for a single parent separated by '/'
1526 # multiple tags for a single parent separated by '/'
1527 t = "/".join(ctx.tags())
1527 t = "/".join(ctx.tags())
1528 if t:
1528 if t:
1529 output.append(t)
1529 output.append(t)
1530
1530
1531 if branch:
1531 if branch:
1532 output.append(util.tolocal(ctx.branch()))
1532 output.append(util.tolocal(ctx.branch()))
1533
1533
1534 if tags:
1534 if tags:
1535 output.extend(ctx.tags())
1535 output.extend(ctx.tags())
1536
1536
1537 ui.write("%s\n" % ' '.join(output))
1537 ui.write("%s\n" % ' '.join(output))
1538
1538
1539 def import_(ui, repo, patch1, *patches, **opts):
1539 def import_(ui, repo, patch1, *patches, **opts):
1540 """import an ordered set of patches
1540 """import an ordered set of patches
1541
1541
1542 Import a list of patches and commit them individually.
1542 Import a list of patches and commit them individually.
1543
1543
1544 If there are outstanding changes in the working directory, import
1544 If there are outstanding changes in the working directory, import
1545 will abort unless given the -f flag.
1545 will abort unless given the -f flag.
1546
1546
1547 You can import a patch straight from a mail message. Even patches
1547 You can import a patch straight from a mail message. Even patches
1548 as attachments work (body part must be type text/plain or
1548 as attachments work (body part must be type text/plain or
1549 text/x-patch to be used). From and Subject headers of email
1549 text/x-patch to be used). From and Subject headers of email
1550 message are used as default committer and commit message. All
1550 message are used as default committer and commit message. All
1551 text/plain body parts before first diff are added to commit
1551 text/plain body parts before first diff are added to commit
1552 message.
1552 message.
1553
1553
1554 If the imported patch was generated by hg export, user and description
1554 If the imported patch was generated by hg export, user and description
1555 from patch override values from message headers and body. Values
1555 from patch override values from message headers and body. Values
1556 given on command line with -m and -u override these.
1556 given on command line with -m and -u override these.
1557
1557
1558 If --exact is specified, import will set the working directory
1558 If --exact is specified, import will set the working directory
1559 to the parent of each patch before applying it, and will abort
1559 to the parent of each patch before applying it, and will abort
1560 if the resulting changeset has a different ID than the one
1560 if the resulting changeset has a different ID than the one
1561 recorded in the patch. This may happen due to character set
1561 recorded in the patch. This may happen due to character set
1562 problems or other deficiencies in the text patch format.
1562 problems or other deficiencies in the text patch format.
1563
1563
1564 To read a patch from standard input, use patch name "-".
1564 To read a patch from standard input, use patch name "-".
1565 """
1565 """
1566 patches = (patch1,) + patches
1566 patches = (patch1,) + patches
1567
1567
1568 if opts.get('exact') or not opts['force']:
1568 if opts.get('exact') or not opts['force']:
1569 cmdutil.bail_if_changed(repo)
1569 cmdutil.bail_if_changed(repo)
1570
1570
1571 d = opts["base"]
1571 d = opts["base"]
1572 strip = opts["strip"]
1572 strip = opts["strip"]
1573 wlock = lock = None
1573 wlock = lock = None
1574 try:
1574 try:
1575 wlock = repo.wlock()
1575 wlock = repo.wlock()
1576 lock = repo.lock()
1576 lock = repo.lock()
1577 for p in patches:
1577 for p in patches:
1578 pf = os.path.join(d, p)
1578 pf = os.path.join(d, p)
1579
1579
1580 if pf == '-':
1580 if pf == '-':
1581 ui.status(_("applying patch from stdin\n"))
1581 ui.status(_("applying patch from stdin\n"))
1582 data = patch.extract(ui, sys.stdin)
1582 data = patch.extract(ui, sys.stdin)
1583 else:
1583 else:
1584 ui.status(_("applying %s\n") % p)
1584 ui.status(_("applying %s\n") % p)
1585 if os.path.exists(pf):
1585 if os.path.exists(pf):
1586 data = patch.extract(ui, file(pf, 'rb'))
1586 data = patch.extract(ui, file(pf, 'rb'))
1587 else:
1587 else:
1588 data = patch.extract(ui, urllib.urlopen(pf))
1588 data = patch.extract(ui, urllib.urlopen(pf))
1589 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1589 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1590
1590
1591 if tmpname is None:
1591 if tmpname is None:
1592 raise util.Abort(_('no diffs found'))
1592 raise util.Abort(_('no diffs found'))
1593
1593
1594 try:
1594 try:
1595 cmdline_message = cmdutil.logmessage(opts)
1595 cmdline_message = cmdutil.logmessage(opts)
1596 if cmdline_message:
1596 if cmdline_message:
1597 # pickup the cmdline msg
1597 # pickup the cmdline msg
1598 message = cmdline_message
1598 message = cmdline_message
1599 elif message:
1599 elif message:
1600 # pickup the patch msg
1600 # pickup the patch msg
1601 message = message.strip()
1601 message = message.strip()
1602 else:
1602 else:
1603 # launch the editor
1603 # launch the editor
1604 message = None
1604 message = None
1605 ui.debug(_('message:\n%s\n') % message)
1605 ui.debug(_('message:\n%s\n') % message)
1606
1606
1607 wp = repo.workingctx().parents()
1607 wp = repo.workingctx().parents()
1608 if opts.get('exact'):
1608 if opts.get('exact'):
1609 if not nodeid or not p1:
1609 if not nodeid or not p1:
1610 raise util.Abort(_('not a mercurial patch'))
1610 raise util.Abort(_('not a mercurial patch'))
1611 p1 = repo.lookup(p1)
1611 p1 = repo.lookup(p1)
1612 p2 = repo.lookup(p2 or hex(nullid))
1612 p2 = repo.lookup(p2 or hex(nullid))
1613
1613
1614 if p1 != wp[0].node():
1614 if p1 != wp[0].node():
1615 hg.clean(repo, p1)
1615 hg.clean(repo, p1)
1616 repo.dirstate.setparents(p1, p2)
1616 repo.dirstate.setparents(p1, p2)
1617 elif p2:
1617 elif p2:
1618 try:
1618 try:
1619 p1 = repo.lookup(p1)
1619 p1 = repo.lookup(p1)
1620 p2 = repo.lookup(p2)
1620 p2 = repo.lookup(p2)
1621 if p1 == wp[0].node():
1621 if p1 == wp[0].node():
1622 repo.dirstate.setparents(p1, p2)
1622 repo.dirstate.setparents(p1, p2)
1623 except hg.RepoError:
1623 except hg.RepoError:
1624 pass
1624 pass
1625 if opts.get('exact') or opts.get('import_branch'):
1625 if opts.get('exact') or opts.get('import_branch'):
1626 repo.dirstate.setbranch(branch or 'default')
1626 repo.dirstate.setbranch(branch or 'default')
1627
1627
1628 files = {}
1628 files = {}
1629 try:
1629 try:
1630 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1630 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1631 files=files)
1631 files=files)
1632 finally:
1632 finally:
1633 files = patch.updatedir(ui, repo, files)
1633 files = patch.updatedir(ui, repo, files)
1634 n = repo.commit(files, message, user, date)
1634 n = repo.commit(files, message, user, date)
1635 if opts.get('exact'):
1635 if opts.get('exact'):
1636 if hex(n) != nodeid:
1636 if hex(n) != nodeid:
1637 repo.rollback()
1637 repo.rollback()
1638 raise util.Abort(_('patch is damaged'
1638 raise util.Abort(_('patch is damaged'
1639 ' or loses information'))
1639 ' or loses information'))
1640 finally:
1640 finally:
1641 os.unlink(tmpname)
1641 os.unlink(tmpname)
1642 finally:
1642 finally:
1643 del lock, wlock
1643 del lock, wlock
1644
1644
1645 def incoming(ui, repo, source="default", **opts):
1645 def incoming(ui, repo, source="default", **opts):
1646 """show new changesets found in source
1646 """show new changesets found in source
1647
1647
1648 Show new changesets found in the specified path/URL or the default
1648 Show new changesets found in the specified path/URL or the default
1649 pull location. These are the changesets that would be pulled if a pull
1649 pull location. These are the changesets that would be pulled if a pull
1650 was requested.
1650 was requested.
1651
1651
1652 For remote repository, using --bundle avoids downloading the changesets
1652 For remote repository, using --bundle avoids downloading the changesets
1653 twice if the incoming is followed by a pull.
1653 twice if the incoming is followed by a pull.
1654
1654
1655 See pull for valid source format details.
1655 See pull for valid source format details.
1656 """
1656 """
1657 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1657 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1658 cmdutil.setremoteconfig(ui, opts)
1658 cmdutil.setremoteconfig(ui, opts)
1659
1659
1660 other = hg.repository(ui, source)
1660 other = hg.repository(ui, source)
1661 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1661 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1662 if revs:
1662 if revs:
1663 revs = [other.lookup(rev) for rev in revs]
1663 revs = [other.lookup(rev) for rev in revs]
1664 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1664 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1665 if not incoming:
1665 if not incoming:
1666 try:
1666 try:
1667 os.unlink(opts["bundle"])
1667 os.unlink(opts["bundle"])
1668 except:
1668 except:
1669 pass
1669 pass
1670 ui.status(_("no changes found\n"))
1670 ui.status(_("no changes found\n"))
1671 return 1
1671 return 1
1672
1672
1673 cleanup = None
1673 cleanup = None
1674 try:
1674 try:
1675 fname = opts["bundle"]
1675 fname = opts["bundle"]
1676 if fname or not other.local():
1676 if fname or not other.local():
1677 # create a bundle (uncompressed if other repo is not local)
1677 # create a bundle (uncompressed if other repo is not local)
1678 if revs is None:
1678 if revs is None:
1679 cg = other.changegroup(incoming, "incoming")
1679 cg = other.changegroup(incoming, "incoming")
1680 else:
1680 else:
1681 cg = other.changegroupsubset(incoming, revs, 'incoming')
1681 cg = other.changegroupsubset(incoming, revs, 'incoming')
1682 bundletype = other.local() and "HG10BZ" or "HG10UN"
1682 bundletype = other.local() and "HG10BZ" or "HG10UN"
1683 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1683 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1684 # keep written bundle?
1684 # keep written bundle?
1685 if opts["bundle"]:
1685 if opts["bundle"]:
1686 cleanup = None
1686 cleanup = None
1687 if not other.local():
1687 if not other.local():
1688 # use the created uncompressed bundlerepo
1688 # use the created uncompressed bundlerepo
1689 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1689 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1690
1690
1691 o = other.changelog.nodesbetween(incoming, revs)[0]
1691 o = other.changelog.nodesbetween(incoming, revs)[0]
1692 if opts['newest_first']:
1692 if opts['newest_first']:
1693 o.reverse()
1693 o.reverse()
1694 displayer = cmdutil.show_changeset(ui, other, opts)
1694 displayer = cmdutil.show_changeset(ui, other, opts)
1695 for n in o:
1695 for n in o:
1696 parents = [p for p in other.changelog.parents(n) if p != nullid]
1696 parents = [p for p in other.changelog.parents(n) if p != nullid]
1697 if opts['no_merges'] and len(parents) == 2:
1697 if opts['no_merges'] and len(parents) == 2:
1698 continue
1698 continue
1699 displayer.show(changenode=n)
1699 displayer.show(changenode=n)
1700 finally:
1700 finally:
1701 if hasattr(other, 'close'):
1701 if hasattr(other, 'close'):
1702 other.close()
1702 other.close()
1703 if cleanup:
1703 if cleanup:
1704 os.unlink(cleanup)
1704 os.unlink(cleanup)
1705
1705
1706 def init(ui, dest=".", **opts):
1706 def init(ui, dest=".", **opts):
1707 """create a new repository in the given directory
1707 """create a new repository in the given directory
1708
1708
1709 Initialize a new repository in the given directory. If the given
1709 Initialize a new repository in the given directory. If the given
1710 directory does not exist, it is created.
1710 directory does not exist, it is created.
1711
1711
1712 If no directory is given, the current directory is used.
1712 If no directory is given, the current directory is used.
1713
1713
1714 It is possible to specify an ssh:// URL as the destination.
1714 It is possible to specify an ssh:// URL as the destination.
1715 Look at the help text for the pull command for important details
1715 Look at the help text for the pull command for important details
1716 about ssh:// URLs.
1716 about ssh:// URLs.
1717 """
1717 """
1718 cmdutil.setremoteconfig(ui, opts)
1718 cmdutil.setremoteconfig(ui, opts)
1719 hg.repository(ui, dest, create=1)
1719 hg.repository(ui, dest, create=1)
1720
1720
1721 def locate(ui, repo, *pats, **opts):
1721 def locate(ui, repo, *pats, **opts):
1722 """locate files matching specific patterns
1722 """locate files matching specific patterns
1723
1723
1724 Print all files under Mercurial control whose names match the
1724 Print all files under Mercurial control whose names match the
1725 given patterns.
1725 given patterns.
1726
1726
1727 This command searches the entire repository by default. To search
1727 This command searches the entire repository by default. To search
1728 just the current directory and its subdirectories, use
1728 just the current directory and its subdirectories, use
1729 "--include .".
1729 "--include .".
1730
1730
1731 If no patterns are given to match, this command prints all file
1731 If no patterns are given to match, this command prints all file
1732 names.
1732 names.
1733
1733
1734 If you want to feed the output of this command into the "xargs"
1734 If you want to feed the output of this command into the "xargs"
1735 command, use the "-0" option to both this command and "xargs".
1735 command, use the "-0" option to both this command and "xargs".
1736 This will avoid the problem of "xargs" treating single filenames
1736 This will avoid the problem of "xargs" treating single filenames
1737 that contain white space as multiple filenames.
1737 that contain white space as multiple filenames.
1738 """
1738 """
1739 end = opts['print0'] and '\0' or '\n'
1739 end = opts['print0'] and '\0' or '\n'
1740 rev = opts['rev']
1740 rev = opts['rev']
1741 if rev:
1741 if rev:
1742 node = repo.lookup(rev)
1742 node = repo.lookup(rev)
1743 else:
1743 else:
1744 node = None
1744 node = None
1745
1745
1746 ret = 1
1746 ret = 1
1747 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1747 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1748 badmatch=util.always,
1748 badmatch=util.always,
1749 default='relglob'):
1749 default='relglob'):
1750 if src == 'b':
1750 if src == 'b':
1751 continue
1751 continue
1752 if not node and abs not in repo.dirstate:
1752 if not node and abs not in repo.dirstate:
1753 continue
1753 continue
1754 if opts['fullpath']:
1754 if opts['fullpath']:
1755 ui.write(os.path.join(repo.root, abs), end)
1755 ui.write(os.path.join(repo.root, abs), end)
1756 else:
1756 else:
1757 ui.write(((pats and rel) or abs), end)
1757 ui.write(((pats and rel) or abs), end)
1758 ret = 0
1758 ret = 0
1759
1759
1760 return ret
1760 return ret
1761
1761
1762 def log(ui, repo, *pats, **opts):
1762 def log(ui, repo, *pats, **opts):
1763 """show revision history of entire repository or files
1763 """show revision history of entire repository or files
1764
1764
1765 Print the revision history of the specified files or the entire
1765 Print the revision history of the specified files or the entire
1766 project.
1766 project.
1767
1767
1768 File history is shown without following rename or copy history of
1768 File history is shown without following rename or copy history of
1769 files. Use -f/--follow with a file name to follow history across
1769 files. Use -f/--follow with a file name to follow history across
1770 renames and copies. --follow without a file name will only show
1770 renames and copies. --follow without a file name will only show
1771 ancestors or descendants of the starting revision. --follow-first
1771 ancestors or descendants of the starting revision. --follow-first
1772 only follows the first parent of merge revisions.
1772 only follows the first parent of merge revisions.
1773
1773
1774 If no revision range is specified, the default is tip:0 unless
1774 If no revision range is specified, the default is tip:0 unless
1775 --follow is set, in which case the working directory parent is
1775 --follow is set, in which case the working directory parent is
1776 used as the starting revision.
1776 used as the starting revision.
1777
1777
1778 By default this command outputs: changeset id and hash, tags,
1778 By default this command outputs: changeset id and hash, tags,
1779 non-trivial parents, user, date and time, and a summary for each
1779 non-trivial parents, user, date and time, and a summary for each
1780 commit. When the -v/--verbose switch is used, the list of changed
1780 commit. When the -v/--verbose switch is used, the list of changed
1781 files and full commit message is shown.
1781 files and full commit message is shown.
1782
1782
1783 NOTE: log -p may generate unexpected diff output for merge
1783 NOTE: log -p may generate unexpected diff output for merge
1784 changesets, as it will compare the merge changeset against its
1784 changesets, as it will compare the merge changeset against its
1785 first parent only. Also, the files: list will only reflect files
1785 first parent only. Also, the files: list will only reflect files
1786 that are different from BOTH parents.
1786 that are different from BOTH parents.
1787
1787
1788 """
1788 """
1789
1789
1790 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1790 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1791 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1791 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1792
1792
1793 if opts['limit']:
1793 if opts['limit']:
1794 try:
1794 try:
1795 limit = int(opts['limit'])
1795 limit = int(opts['limit'])
1796 except ValueError:
1796 except ValueError:
1797 raise util.Abort(_('limit must be a positive integer'))
1797 raise util.Abort(_('limit must be a positive integer'))
1798 if limit <= 0: raise util.Abort(_('limit must be positive'))
1798 if limit <= 0: raise util.Abort(_('limit must be positive'))
1799 else:
1799 else:
1800 limit = sys.maxint
1800 limit = sys.maxint
1801 count = 0
1801 count = 0
1802
1802
1803 if opts['copies'] and opts['rev']:
1803 if opts['copies'] and opts['rev']:
1804 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1804 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1805 else:
1805 else:
1806 endrev = repo.changelog.count()
1806 endrev = repo.changelog.count()
1807 rcache = {}
1807 rcache = {}
1808 ncache = {}
1808 ncache = {}
1809 dcache = []
1809 dcache = []
1810 def getrenamed(fn, rev, man):
1810 def getrenamed(fn, rev, man):
1811 '''looks up all renames for a file (up to endrev) the first
1811 '''looks up all renames for a file (up to endrev) the first
1812 time the file is given. It indexes on the changerev and only
1812 time the file is given. It indexes on the changerev and only
1813 parses the manifest if linkrev != changerev.
1813 parses the manifest if linkrev != changerev.
1814 Returns rename info for fn at changerev rev.'''
1814 Returns rename info for fn at changerev rev.'''
1815 if fn not in rcache:
1815 if fn not in rcache:
1816 rcache[fn] = {}
1816 rcache[fn] = {}
1817 ncache[fn] = {}
1817 ncache[fn] = {}
1818 fl = repo.file(fn)
1818 fl = repo.file(fn)
1819 for i in xrange(fl.count()):
1819 for i in xrange(fl.count()):
1820 node = fl.node(i)
1820 node = fl.node(i)
1821 lr = fl.linkrev(node)
1821 lr = fl.linkrev(node)
1822 renamed = fl.renamed(node)
1822 renamed = fl.renamed(node)
1823 rcache[fn][lr] = renamed
1823 rcache[fn][lr] = renamed
1824 if renamed:
1824 if renamed:
1825 ncache[fn][node] = renamed
1825 ncache[fn][node] = renamed
1826 if lr >= endrev:
1826 if lr >= endrev:
1827 break
1827 break
1828 if rev in rcache[fn]:
1828 if rev in rcache[fn]:
1829 return rcache[fn][rev]
1829 return rcache[fn][rev]
1830 mr = repo.manifest.rev(man)
1830 mr = repo.manifest.rev(man)
1831 if repo.manifest.parentrevs(mr) != (mr - 1, nullrev):
1831 if repo.manifest.parentrevs(mr) != (mr - 1, nullrev):
1832 return ncache[fn].get(repo.manifest.find(man, fn)[0])
1832 return ncache[fn].get(repo.manifest.find(man, fn)[0])
1833 if not dcache or dcache[0] != man:
1833 if not dcache or dcache[0] != man:
1834 dcache[:] = [man, repo.manifest.readdelta(man)]
1834 dcache[:] = [man, repo.manifest.readdelta(man)]
1835 if fn in dcache[1]:
1835 if fn in dcache[1]:
1836 return ncache[fn].get(dcache[1][fn])
1836 return ncache[fn].get(dcache[1][fn])
1837 return None
1837 return None
1838
1838
1839 df = False
1839 df = False
1840 if opts["date"]:
1840 if opts["date"]:
1841 df = util.matchdate(opts["date"])
1841 df = util.matchdate(opts["date"])
1842
1842
1843 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1843 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1844 for st, rev, fns in changeiter:
1844 for st, rev, fns in changeiter:
1845 if st == 'add':
1845 if st == 'add':
1846 changenode = repo.changelog.node(rev)
1846 changenode = repo.changelog.node(rev)
1847 parents = [p for p in repo.changelog.parentrevs(rev)
1847 parents = [p for p in repo.changelog.parentrevs(rev)
1848 if p != nullrev]
1848 if p != nullrev]
1849 if opts['no_merges'] and len(parents) == 2:
1849 if opts['no_merges'] and len(parents) == 2:
1850 continue
1850 continue
1851 if opts['only_merges'] and len(parents) != 2:
1851 if opts['only_merges'] and len(parents) != 2:
1852 continue
1852 continue
1853
1853
1854 if df:
1854 if df:
1855 changes = get(rev)
1855 changes = get(rev)
1856 if not df(changes[2][0]):
1856 if not df(changes[2][0]):
1857 continue
1857 continue
1858
1858
1859 if opts['keyword']:
1859 if opts['keyword']:
1860 changes = get(rev)
1860 changes = get(rev)
1861 miss = 0
1861 miss = 0
1862 for k in [kw.lower() for kw in opts['keyword']]:
1862 for k in [kw.lower() for kw in opts['keyword']]:
1863 if not (k in changes[1].lower() or
1863 if not (k in changes[1].lower() or
1864 k in changes[4].lower() or
1864 k in changes[4].lower() or
1865 k in " ".join(changes[3]).lower()):
1865 k in " ".join(changes[3]).lower()):
1866 miss = 1
1866 miss = 1
1867 break
1867 break
1868 if miss:
1868 if miss:
1869 continue
1869 continue
1870
1870
1871 copies = []
1871 copies = []
1872 if opts.get('copies') and rev:
1872 if opts.get('copies') and rev:
1873 mf = get(rev)[0]
1873 mf = get(rev)[0]
1874 for fn in get(rev)[3]:
1874 for fn in get(rev)[3]:
1875 rename = getrenamed(fn, rev, mf)
1875 rename = getrenamed(fn, rev, mf)
1876 if rename:
1876 if rename:
1877 copies.append((fn, rename[0]))
1877 copies.append((fn, rename[0]))
1878 displayer.show(rev, changenode, copies=copies)
1878 displayer.show(rev, changenode, copies=copies)
1879 elif st == 'iter':
1879 elif st == 'iter':
1880 if count == limit: break
1880 if count == limit: break
1881 if displayer.flush(rev):
1881 if displayer.flush(rev):
1882 count += 1
1882 count += 1
1883
1883
1884 def manifest(ui, repo, node=None, rev=None):
1884 def manifest(ui, repo, node=None, rev=None):
1885 """output the current or given revision of the project manifest
1885 """output the current or given revision of the project manifest
1886
1886
1887 Print a list of version controlled files for the given revision.
1887 Print a list of version controlled files for the given revision.
1888 If no revision is given, the parent of the working directory is used,
1888 If no revision is given, the parent of the working directory is used,
1889 or tip if no revision is checked out.
1889 or tip if no revision is checked out.
1890
1890
1891 The manifest is the list of files being version controlled. If no revision
1891 The manifest is the list of files being version controlled. If no revision
1892 is given then the first parent of the working directory is used.
1892 is given then the first parent of the working directory is used.
1893
1893
1894 With -v flag, print file permissions, symlink and executable bits. With
1894 With -v flag, print file permissions, symlink and executable bits. With
1895 --debug flag, print file revision hashes.
1895 --debug flag, print file revision hashes.
1896 """
1896 """
1897
1897
1898 if rev and node:
1898 if rev and node:
1899 raise util.Abort(_("please specify just one revision"))
1899 raise util.Abort(_("please specify just one revision"))
1900
1900
1901 if not node:
1901 if not node:
1902 node = rev
1902 node = rev
1903
1903
1904 m = repo.changectx(node).manifest()
1904 m = repo.changectx(node).manifest()
1905 files = m.keys()
1905 files = m.keys()
1906 files.sort()
1906 files.sort()
1907
1907
1908 for f in files:
1908 for f in files:
1909 if ui.debugflag:
1909 if ui.debugflag:
1910 ui.write("%40s " % hex(m[f]))
1910 ui.write("%40s " % hex(m[f]))
1911 if ui.verbose:
1911 if ui.verbose:
1912 type = m.execf(f) and "*" or m.linkf(f) and "@" or " "
1912 type = m.execf(f) and "*" or m.linkf(f) and "@" or " "
1913 perm = m.execf(f) and "755" or "644"
1913 perm = m.execf(f) and "755" or "644"
1914 ui.write("%3s %1s " % (perm, type))
1914 ui.write("%3s %1s " % (perm, type))
1915 ui.write("%s\n" % f)
1915 ui.write("%s\n" % f)
1916
1916
1917 def merge(ui, repo, node=None, force=None, rev=None):
1917 def merge(ui, repo, node=None, force=None, rev=None):
1918 """merge working directory with another revision
1918 """merge working directory with another revision
1919
1919
1920 Merge the contents of the current working directory and the
1920 Merge the contents of the current working directory and the
1921 requested revision. Files that changed between either parent are
1921 requested revision. Files that changed between either parent are
1922 marked as changed for the next commit and a commit must be
1922 marked as changed for the next commit and a commit must be
1923 performed before any further updates are allowed.
1923 performed before any further updates are allowed.
1924
1924
1925 If no revision is specified, the working directory's parent is a
1925 If no revision is specified, the working directory's parent is a
1926 head revision, and the repository contains exactly one other head,
1926 head revision, and the repository contains exactly one other head,
1927 the other head is merged with by default. Otherwise, an explicit
1927 the other head is merged with by default. Otherwise, an explicit
1928 revision to merge with must be provided.
1928 revision to merge with must be provided.
1929 """
1929 """
1930
1930
1931 if rev and node:
1931 if rev and node:
1932 raise util.Abort(_("please specify just one revision"))
1932 raise util.Abort(_("please specify just one revision"))
1933 if not node:
1933 if not node:
1934 node = rev
1934 node = rev
1935
1935
1936 if not node:
1936 if not node:
1937 heads = repo.heads()
1937 heads = repo.heads()
1938 if len(heads) > 2:
1938 if len(heads) > 2:
1939 raise util.Abort(_('repo has %d heads - '
1939 raise util.Abort(_('repo has %d heads - '
1940 'please merge with an explicit rev') %
1940 'please merge with an explicit rev') %
1941 len(heads))
1941 len(heads))
1942 parent = repo.dirstate.parents()[0]
1942 parent = repo.dirstate.parents()[0]
1943 if len(heads) == 1:
1943 if len(heads) == 1:
1944 msg = _('there is nothing to merge')
1944 msg = _('there is nothing to merge')
1945 if parent != repo.lookup(repo.workingctx().branch()):
1945 if parent != repo.lookup(repo.workingctx().branch()):
1946 msg = _('%s - use "hg update" instead') % msg
1946 msg = _('%s - use "hg update" instead') % msg
1947 raise util.Abort(msg)
1947 raise util.Abort(msg)
1948
1948
1949 if parent not in heads:
1949 if parent not in heads:
1950 raise util.Abort(_('working dir not at a head rev - '
1950 raise util.Abort(_('working dir not at a head rev - '
1951 'use "hg update" or merge with an explicit rev'))
1951 'use "hg update" or merge with an explicit rev'))
1952 node = parent == heads[0] and heads[-1] or heads[0]
1952 node = parent == heads[0] and heads[-1] or heads[0]
1953 return hg.merge(repo, node, force=force)
1953 return hg.merge(repo, node, force=force)
1954
1954
1955 def outgoing(ui, repo, dest=None, **opts):
1955 def outgoing(ui, repo, dest=None, **opts):
1956 """show changesets not found in destination
1956 """show changesets not found in destination
1957
1957
1958 Show changesets not found in the specified destination repository or
1958 Show changesets not found in the specified destination repository or
1959 the default push location. These are the changesets that would be pushed
1959 the default push location. These are the changesets that would be pushed
1960 if a push was requested.
1960 if a push was requested.
1961
1961
1962 See pull for valid destination format details.
1962 See pull for valid destination format details.
1963 """
1963 """
1964 dest, revs, checkout = hg.parseurl(
1964 dest, revs, checkout = hg.parseurl(
1965 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1965 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1966 cmdutil.setremoteconfig(ui, opts)
1966 cmdutil.setremoteconfig(ui, opts)
1967 if revs:
1967 if revs:
1968 revs = [repo.lookup(rev) for rev in revs]
1968 revs = [repo.lookup(rev) for rev in revs]
1969
1969
1970 other = hg.repository(ui, dest)
1970 other = hg.repository(ui, dest)
1971 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1971 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1972 o = repo.findoutgoing(other, force=opts['force'])
1972 o = repo.findoutgoing(other, force=opts['force'])
1973 if not o:
1973 if not o:
1974 ui.status(_("no changes found\n"))
1974 ui.status(_("no changes found\n"))
1975 return 1
1975 return 1
1976 o = repo.changelog.nodesbetween(o, revs)[0]
1976 o = repo.changelog.nodesbetween(o, revs)[0]
1977 if opts['newest_first']:
1977 if opts['newest_first']:
1978 o.reverse()
1978 o.reverse()
1979 displayer = cmdutil.show_changeset(ui, repo, opts)
1979 displayer = cmdutil.show_changeset(ui, repo, opts)
1980 for n in o:
1980 for n in o:
1981 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1981 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1982 if opts['no_merges'] and len(parents) == 2:
1982 if opts['no_merges'] and len(parents) == 2:
1983 continue
1983 continue
1984 displayer.show(changenode=n)
1984 displayer.show(changenode=n)
1985
1985
1986 def parents(ui, repo, file_=None, **opts):
1986 def parents(ui, repo, file_=None, **opts):
1987 """show the parents of the working dir or revision
1987 """show the parents of the working dir or revision
1988
1988
1989 Print the working directory's parent revisions. If a
1989 Print the working directory's parent revisions. If a
1990 revision is given via --rev, the parent of that revision
1990 revision is given via --rev, the parent of that revision
1991 will be printed. If a file argument is given, revision in
1991 will be printed. If a file argument is given, revision in
1992 which the file was last changed (before the working directory
1992 which the file was last changed (before the working directory
1993 revision or the argument to --rev if given) is printed.
1993 revision or the argument to --rev if given) is printed.
1994 """
1994 """
1995 rev = opts.get('rev')
1995 rev = opts.get('rev')
1996 if rev:
1996 if rev:
1997 ctx = repo.changectx(rev)
1997 ctx = repo.changectx(rev)
1998 else:
1998 else:
1999 ctx = repo.workingctx()
1999 ctx = repo.workingctx()
2000
2000
2001 if file_:
2001 if file_:
2002 files, match, anypats = cmdutil.matchpats(repo, (file_,), opts)
2002 files, match, anypats = cmdutil.matchpats(repo, (file_,), opts)
2003 if anypats or len(files) != 1:
2003 if anypats or len(files) != 1:
2004 raise util.Abort(_('can only specify an explicit file name'))
2004 raise util.Abort(_('can only specify an explicit file name'))
2005 file_ = files[0]
2005 file_ = files[0]
2006 filenodes = []
2006 filenodes = []
2007 for cp in ctx.parents():
2007 for cp in ctx.parents():
2008 if not cp:
2008 if not cp:
2009 continue
2009 continue
2010 try:
2010 try:
2011 filenodes.append(cp.filenode(file_))
2011 filenodes.append(cp.filenode(file_))
2012 except revlog.LookupError:
2012 except revlog.LookupError:
2013 pass
2013 pass
2014 if not filenodes:
2014 if not filenodes:
2015 raise util.Abort(_("'%s' not found in manifest!") % file_)
2015 raise util.Abort(_("'%s' not found in manifest!") % file_)
2016 fl = repo.file(file_)
2016 fl = repo.file(file_)
2017 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
2017 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
2018 else:
2018 else:
2019 p = [cp.node() for cp in ctx.parents()]
2019 p = [cp.node() for cp in ctx.parents()]
2020
2020
2021 displayer = cmdutil.show_changeset(ui, repo, opts)
2021 displayer = cmdutil.show_changeset(ui, repo, opts)
2022 for n in p:
2022 for n in p:
2023 if n != nullid:
2023 if n != nullid:
2024 displayer.show(changenode=n)
2024 displayer.show(changenode=n)
2025
2025
2026 def paths(ui, repo, search=None):
2026 def paths(ui, repo, search=None):
2027 """show definition of symbolic path names
2027 """show definition of symbolic path names
2028
2028
2029 Show definition of symbolic path name NAME. If no name is given, show
2029 Show definition of symbolic path name NAME. If no name is given, show
2030 definition of available names.
2030 definition of available names.
2031
2031
2032 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2032 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2033 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2033 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2034 """
2034 """
2035 if search:
2035 if search:
2036 for name, path in ui.configitems("paths"):
2036 for name, path in ui.configitems("paths"):
2037 if name == search:
2037 if name == search:
2038 ui.write("%s\n" % path)
2038 ui.write("%s\n" % path)
2039 return
2039 return
2040 ui.warn(_("not found!\n"))
2040 ui.warn(_("not found!\n"))
2041 return 1
2041 return 1
2042 else:
2042 else:
2043 for name, path in ui.configitems("paths"):
2043 for name, path in ui.configitems("paths"):
2044 ui.write("%s = %s\n" % (name, path))
2044 ui.write("%s = %s\n" % (name, path))
2045
2045
2046 def postincoming(ui, repo, modheads, optupdate, checkout):
2046 def postincoming(ui, repo, modheads, optupdate, checkout):
2047 if modheads == 0:
2047 if modheads == 0:
2048 return
2048 return
2049 if optupdate:
2049 if optupdate:
2050 if modheads <= 1 or checkout:
2050 if modheads <= 1 or checkout:
2051 return hg.update(repo, checkout)
2051 return hg.update(repo, checkout)
2052 else:
2052 else:
2053 ui.status(_("not updating, since new heads added\n"))
2053 ui.status(_("not updating, since new heads added\n"))
2054 if modheads > 1:
2054 if modheads > 1:
2055 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2055 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2056 else:
2056 else:
2057 ui.status(_("(run 'hg update' to get a working copy)\n"))
2057 ui.status(_("(run 'hg update' to get a working copy)\n"))
2058
2058
2059 def pull(ui, repo, source="default", **opts):
2059 def pull(ui, repo, source="default", **opts):
2060 """pull changes from the specified source
2060 """pull changes from the specified source
2061
2061
2062 Pull changes from a remote repository to a local one.
2062 Pull changes from a remote repository to a local one.
2063
2063
2064 This finds all changes from the repository at the specified path
2064 This finds all changes from the repository at the specified path
2065 or URL and adds them to the local repository. By default, this
2065 or URL and adds them to the local repository. By default, this
2066 does not update the copy of the project in the working directory.
2066 does not update the copy of the project in the working directory.
2067
2067
2068 Valid URLs are of the form:
2068 Valid URLs are of the form:
2069
2069
2070 local/filesystem/path (or file://local/filesystem/path)
2070 local/filesystem/path (or file://local/filesystem/path)
2071 http://[user@]host[:port]/[path]
2071 http://[user@]host[:port]/[path]
2072 https://[user@]host[:port]/[path]
2072 https://[user@]host[:port]/[path]
2073 ssh://[user@]host[:port]/[path]
2073 ssh://[user@]host[:port]/[path]
2074 static-http://host[:port]/[path]
2074 static-http://host[:port]/[path]
2075
2075
2076 Paths in the local filesystem can either point to Mercurial
2076 Paths in the local filesystem can either point to Mercurial
2077 repositories or to bundle files (as created by 'hg bundle' or
2077 repositories or to bundle files (as created by 'hg bundle' or
2078 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
2078 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
2079 allows access to a Mercurial repository where you simply use a web
2079 allows access to a Mercurial repository where you simply use a web
2080 server to publish the .hg directory as static content.
2080 server to publish the .hg directory as static content.
2081
2081
2082 An optional identifier after # indicates a particular branch, tag,
2082 An optional identifier after # indicates a particular branch, tag,
2083 or changeset to pull.
2083 or changeset to pull.
2084
2084
2085 Some notes about using SSH with Mercurial:
2085 Some notes about using SSH with Mercurial:
2086 - SSH requires an accessible shell account on the destination machine
2086 - SSH requires an accessible shell account on the destination machine
2087 and a copy of hg in the remote path or specified with as remotecmd.
2087 and a copy of hg in the remote path or specified with as remotecmd.
2088 - path is relative to the remote user's home directory by default.
2088 - path is relative to the remote user's home directory by default.
2089 Use an extra slash at the start of a path to specify an absolute path:
2089 Use an extra slash at the start of a path to specify an absolute path:
2090 ssh://example.com//tmp/repository
2090 ssh://example.com//tmp/repository
2091 - Mercurial doesn't use its own compression via SSH; the right thing
2091 - Mercurial doesn't use its own compression via SSH; the right thing
2092 to do is to configure it in your ~/.ssh/config, e.g.:
2092 to do is to configure it in your ~/.ssh/config, e.g.:
2093 Host *.mylocalnetwork.example.com
2093 Host *.mylocalnetwork.example.com
2094 Compression no
2094 Compression no
2095 Host *
2095 Host *
2096 Compression yes
2096 Compression yes
2097 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2097 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2098 with the --ssh command line option.
2098 with the --ssh command line option.
2099 """
2099 """
2100 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2100 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2101 cmdutil.setremoteconfig(ui, opts)
2101 cmdutil.setremoteconfig(ui, opts)
2102
2102
2103 other = hg.repository(ui, source)
2103 other = hg.repository(ui, source)
2104 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2104 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2105 if revs:
2105 if revs:
2106 try:
2106 try:
2107 revs = [other.lookup(rev) for rev in revs]
2107 revs = [other.lookup(rev) for rev in revs]
2108 except repo.NoCapability:
2108 except repo.NoCapability:
2109 error = _("Other repository doesn't support revision lookup, "
2109 error = _("Other repository doesn't support revision lookup, "
2110 "so a rev cannot be specified.")
2110 "so a rev cannot be specified.")
2111 raise util.Abort(error)
2111 raise util.Abort(error)
2112
2112
2113 modheads = repo.pull(other, heads=revs, force=opts['force'])
2113 modheads = repo.pull(other, heads=revs, force=opts['force'])
2114 return postincoming(ui, repo, modheads, opts['update'], checkout)
2114 return postincoming(ui, repo, modheads, opts['update'], checkout)
2115
2115
2116 def push(ui, repo, dest=None, **opts):
2116 def push(ui, repo, dest=None, **opts):
2117 """push changes to the specified destination
2117 """push changes to the specified destination
2118
2118
2119 Push changes from the local repository to the given destination.
2119 Push changes from the local repository to the given destination.
2120
2120
2121 This is the symmetrical operation for pull. It helps to move
2121 This is the symmetrical operation for pull. It helps to move
2122 changes from the current repository to a different one. If the
2122 changes from the current repository to a different one. If the
2123 destination is local this is identical to a pull in that directory
2123 destination is local this is identical to a pull in that directory
2124 from the current one.
2124 from the current one.
2125
2125
2126 By default, push will refuse to run if it detects the result would
2126 By default, push will refuse to run if it detects the result would
2127 increase the number of remote heads. This generally indicates the
2127 increase the number of remote heads. This generally indicates the
2128 the client has forgotten to sync and merge before pushing.
2128 the client has forgotten to sync and merge before pushing.
2129
2129
2130 Valid URLs are of the form:
2130 Valid URLs are of the form:
2131
2131
2132 local/filesystem/path (or file://local/filesystem/path)
2132 local/filesystem/path (or file://local/filesystem/path)
2133 ssh://[user@]host[:port]/[path]
2133 ssh://[user@]host[:port]/[path]
2134 http://[user@]host[:port]/[path]
2134 http://[user@]host[:port]/[path]
2135 https://[user@]host[:port]/[path]
2135 https://[user@]host[:port]/[path]
2136
2136
2137 An optional identifier after # indicates a particular branch, tag,
2137 An optional identifier after # indicates a particular branch, tag,
2138 or changeset to push.
2138 or changeset to push.
2139
2139
2140 Look at the help text for the pull command for important details
2140 Look at the help text for the pull command for important details
2141 about ssh:// URLs.
2141 about ssh:// URLs.
2142
2142
2143 Pushing to http:// and https:// URLs is only possible, if this
2143 Pushing to http:// and https:// URLs is only possible, if this
2144 feature is explicitly enabled on the remote Mercurial server.
2144 feature is explicitly enabled on the remote Mercurial server.
2145 """
2145 """
2146 dest, revs, checkout = hg.parseurl(
2146 dest, revs, checkout = hg.parseurl(
2147 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2147 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2148 cmdutil.setremoteconfig(ui, opts)
2148 cmdutil.setremoteconfig(ui, opts)
2149
2149
2150 other = hg.repository(ui, dest)
2150 other = hg.repository(ui, dest)
2151 ui.status('pushing to %s\n' % util.hidepassword(dest))
2151 ui.status('pushing to %s\n' % util.hidepassword(dest))
2152 if revs:
2152 if revs:
2153 revs = [repo.lookup(rev) for rev in revs]
2153 revs = [repo.lookup(rev) for rev in revs]
2154 r = repo.push(other, opts['force'], revs=revs)
2154 r = repo.push(other, opts['force'], revs=revs)
2155 return r == 0
2155 return r == 0
2156
2156
2157 def rawcommit(ui, repo, *pats, **opts):
2157 def rawcommit(ui, repo, *pats, **opts):
2158 """raw commit interface (DEPRECATED)
2158 """raw commit interface (DEPRECATED)
2159
2159
2160 (DEPRECATED)
2160 (DEPRECATED)
2161 Lowlevel commit, for use in helper scripts.
2161 Lowlevel commit, for use in helper scripts.
2162
2162
2163 This command is not intended to be used by normal users, as it is
2163 This command is not intended to be used by normal users, as it is
2164 primarily useful for importing from other SCMs.
2164 primarily useful for importing from other SCMs.
2165
2165
2166 This command is now deprecated and will be removed in a future
2166 This command is now deprecated and will be removed in a future
2167 release, please use debugsetparents and commit instead.
2167 release, please use debugsetparents and commit instead.
2168 """
2168 """
2169
2169
2170 ui.warn(_("(the rawcommit command is deprecated)\n"))
2170 ui.warn(_("(the rawcommit command is deprecated)\n"))
2171
2171
2172 message = cmdutil.logmessage(opts)
2172 message = cmdutil.logmessage(opts)
2173
2173
2174 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
2174 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
2175 if opts['files']:
2175 if opts['files']:
2176 files += open(opts['files']).read().splitlines()
2176 files += open(opts['files']).read().splitlines()
2177
2177
2178 parents = [repo.lookup(p) for p in opts['parent']]
2178 parents = [repo.lookup(p) for p in opts['parent']]
2179
2179
2180 try:
2180 try:
2181 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2181 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2182 except ValueError, inst:
2182 except ValueError, inst:
2183 raise util.Abort(str(inst))
2183 raise util.Abort(str(inst))
2184
2184
2185 def recover(ui, repo):
2185 def recover(ui, repo):
2186 """roll back an interrupted transaction
2186 """roll back an interrupted transaction
2187
2187
2188 Recover from an interrupted commit or pull.
2188 Recover from an interrupted commit or pull.
2189
2189
2190 This command tries to fix the repository status after an interrupted
2190 This command tries to fix the repository status after an interrupted
2191 operation. It should only be necessary when Mercurial suggests it.
2191 operation. It should only be necessary when Mercurial suggests it.
2192 """
2192 """
2193 if repo.recover():
2193 if repo.recover():
2194 return hg.verify(repo)
2194 return hg.verify(repo)
2195 return 1
2195 return 1
2196
2196
2197 def remove(ui, repo, *pats, **opts):
2197 def remove(ui, repo, *pats, **opts):
2198 """remove the specified files on the next commit
2198 """remove the specified files on the next commit
2199
2199
2200 Schedule the indicated files for removal from the repository.
2200 Schedule the indicated files for removal from the repository.
2201
2201
2202 This only removes files from the current branch, not from the
2202 This only removes files from the current branch, not from the
2203 entire project history. If the files still exist in the working
2203 entire project history. If the files still exist in the working
2204 directory, they will be deleted from it. If invoked with --after,
2204 directory, they will be deleted from it. If invoked with --after,
2205 files are marked as removed, but not actually unlinked unless --force
2205 files are marked as removed, but not actually unlinked unless --force
2206 is also given. Without exact file names, --after will only mark
2206 is also given. Without exact file names, --after will only mark
2207 files as removed if they are no longer in the working directory.
2207 files as removed if they are no longer in the working directory.
2208
2208
2209 This command schedules the files to be removed at the next commit.
2209 This command schedules the files to be removed at the next commit.
2210 To undo a remove before that, see hg revert.
2210 To undo a remove before that, see hg revert.
2211
2211
2212 Modified files and added files are not removed by default. To
2212 Modified files and added files are not removed by default. To
2213 remove them, use the -f/--force option.
2213 remove them, use the -f/--force option.
2214 """
2214 """
2215 if not opts['after'] and not pats:
2215 if not opts['after'] and not pats:
2216 raise util.Abort(_('no files specified'))
2216 raise util.Abort(_('no files specified'))
2217 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2217 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2218 exact = dict.fromkeys(files)
2218 exact = dict.fromkeys(files)
2219 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
2219 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
2220 modified, added, removed, deleted, unknown = mardu
2220 modified, added, removed, deleted, unknown = mardu
2221 remove, forget = [], []
2221 remove, forget = [], []
2222 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
2222 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
2223 reason = None
2223 reason = None
2224 if abs in modified and not opts['force']:
2224 if abs in modified and not opts['force']:
2225 reason = _('is modified (use -f to force removal)')
2225 reason = _('is modified (use -f to force removal)')
2226 elif abs in added:
2226 elif abs in added:
2227 if opts['force']:
2227 if opts['force']:
2228 forget.append(abs)
2228 forget.append(abs)
2229 continue
2229 continue
2230 reason = _('has been marked for add (use -f to force removal)')
2230 reason = _('has been marked for add (use -f to force removal)')
2231 elif abs not in repo.dirstate:
2231 elif abs not in repo.dirstate:
2232 reason = _('is not managed')
2232 reason = _('is not managed')
2233 elif opts['after'] and not exact and abs not in deleted:
2233 elif opts['after'] and not exact and abs not in deleted:
2234 continue
2234 continue
2235 elif abs in removed:
2235 elif abs in removed:
2236 continue
2236 continue
2237 if reason:
2237 if reason:
2238 if exact:
2238 if exact:
2239 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2239 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2240 else:
2240 else:
2241 if ui.verbose or not exact:
2241 if ui.verbose or not exact:
2242 ui.status(_('removing %s\n') % rel)
2242 ui.status(_('removing %s\n') % rel)
2243 remove.append(abs)
2243 remove.append(abs)
2244 repo.forget(forget)
2244 repo.forget(forget)
2245 repo.remove(remove, unlink=opts['force'] or not opts['after'])
2245 repo.remove(remove, unlink=opts['force'] or not opts['after'])
2246
2246
2247 def rename(ui, repo, *pats, **opts):
2247 def rename(ui, repo, *pats, **opts):
2248 """rename files; equivalent of copy + remove
2248 """rename files; equivalent of copy + remove
2249
2249
2250 Mark dest as copies of sources; mark sources for deletion. If
2250 Mark dest as copies of sources; mark sources for deletion. If
2251 dest is a directory, copies are put in that directory. If dest is
2251 dest is a directory, copies are put in that directory. If dest is
2252 a file, there can only be one source.
2252 a file, there can only be one source.
2253
2253
2254 By default, this command copies the contents of files as they
2254 By default, this command copies the contents of files as they
2255 stand in the working directory. If invoked with --after, the
2255 stand in the working directory. If invoked with --after, the
2256 operation is recorded, but no copying is performed.
2256 operation is recorded, but no copying is performed.
2257
2257
2258 This command takes effect in the next commit. To undo a rename
2258 This command takes effect in the next commit. To undo a rename
2259 before that, see hg revert.
2259 before that, see hg revert.
2260 """
2260 """
2261 wlock = repo.wlock(False)
2261 wlock = repo.wlock(False)
2262 try:
2262 try:
2263 errs, copied = docopy(ui, repo, pats, opts)
2263 errs, copied = docopy(ui, repo, pats, opts)
2264 names = []
2264 names = []
2265 for abs, rel, exact in copied:
2265 for abs, rel, exact in copied:
2266 if ui.verbose or not exact:
2266 if ui.verbose or not exact:
2267 ui.status(_('removing %s\n') % rel)
2267 ui.status(_('removing %s\n') % rel)
2268 names.append(abs)
2268 names.append(abs)
2269 if not opts.get('dry_run'):
2269 if not opts.get('dry_run'):
2270 repo.remove(names, True)
2270 repo.remove(names, True)
2271 return errs
2271 return errs
2272 finally:
2272 finally:
2273 del wlock
2273 del wlock
2274
2274
2275 def revert(ui, repo, *pats, **opts):
2275 def revert(ui, repo, *pats, **opts):
2276 """restore individual files or dirs to an earlier state
2276 """restore individual files or dirs to an earlier state
2277
2277
2278 (use update -r to check out earlier revisions, revert does not
2278 (use update -r to check out earlier revisions, revert does not
2279 change the working dir parents)
2279 change the working dir parents)
2280
2280
2281 With no revision specified, revert the named files or directories
2281 With no revision specified, revert the named files or directories
2282 to the contents they had in the parent of the working directory.
2282 to the contents they had in the parent of the working directory.
2283 This restores the contents of the affected files to an unmodified
2283 This restores the contents of the affected files to an unmodified
2284 state and unschedules adds, removes, copies, and renames. If the
2284 state and unschedules adds, removes, copies, and renames. If the
2285 working directory has two parents, you must explicitly specify the
2285 working directory has two parents, you must explicitly specify the
2286 revision to revert to.
2286 revision to revert to.
2287
2287
2288 Using the -r option, revert the given files or directories to their
2288 Using the -r option, revert the given files or directories to their
2289 contents as of a specific revision. This can be helpful to "roll
2289 contents as of a specific revision. This can be helpful to "roll
2290 back" some or all of an earlier change.
2290 back" some or all of an earlier change.
2291
2291
2292 Revert modifies the working directory. It does not commit any
2292 Revert modifies the working directory. It does not commit any
2293 changes, or change the parent of the working directory. If you
2293 changes, or change the parent of the working directory. If you
2294 revert to a revision other than the parent of the working
2294 revert to a revision other than the parent of the working
2295 directory, the reverted files will thus appear modified
2295 directory, the reverted files will thus appear modified
2296 afterwards.
2296 afterwards.
2297
2297
2298 If a file has been deleted, it is restored. If the executable
2298 If a file has been deleted, it is restored. If the executable
2299 mode of a file was changed, it is reset.
2299 mode of a file was changed, it is reset.
2300
2300
2301 If names are given, all files matching the names are reverted.
2301 If names are given, all files matching the names are reverted.
2302
2302
2303 If no arguments are given, no files are reverted.
2303 If no arguments are given, no files are reverted.
2304
2304
2305 Modified files are saved with a .orig suffix before reverting.
2305 Modified files are saved with a .orig suffix before reverting.
2306 To disable these backups, use --no-backup.
2306 To disable these backups, use --no-backup.
2307 """
2307 """
2308
2308
2309 if opts["date"]:
2309 if opts["date"]:
2310 if opts["rev"]:
2310 if opts["rev"]:
2311 raise util.Abort(_("you can't specify a revision and a date"))
2311 raise util.Abort(_("you can't specify a revision and a date"))
2312 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2312 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2313
2313
2314 if not pats and not opts['all']:
2314 if not pats and not opts['all']:
2315 raise util.Abort(_('no files or directories specified; '
2315 raise util.Abort(_('no files or directories specified; '
2316 'use --all to revert the whole repo'))
2316 'use --all to revert the whole repo'))
2317
2317
2318 parent, p2 = repo.dirstate.parents()
2318 parent, p2 = repo.dirstate.parents()
2319 if not opts['rev'] and p2 != nullid:
2319 if not opts['rev'] and p2 != nullid:
2320 raise util.Abort(_('uncommitted merge - please provide a '
2320 raise util.Abort(_('uncommitted merge - please provide a '
2321 'specific revision'))
2321 'specific revision'))
2322 ctx = repo.changectx(opts['rev'])
2322 ctx = repo.changectx(opts['rev'])
2323 node = ctx.node()
2323 node = ctx.node()
2324 mf = ctx.manifest()
2324 mf = ctx.manifest()
2325 if node == parent:
2325 if node == parent:
2326 pmf = mf
2326 pmf = mf
2327 else:
2327 else:
2328 pmf = None
2328 pmf = None
2329
2329
2330 # need all matching names in dirstate and manifest of target rev,
2330 # need all matching names in dirstate and manifest of target rev,
2331 # so have to walk both. do not print errors if files exist in one
2331 # so have to walk both. do not print errors if files exist in one
2332 # but not other.
2332 # but not other.
2333
2333
2334 names = {}
2334 names = {}
2335 target_only = {}
2335 target_only = {}
2336
2336
2337 wlock = repo.wlock()
2337 wlock = repo.wlock()
2338 try:
2338 try:
2339 # walk dirstate.
2339 # walk dirstate.
2340 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
2340 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
2341 badmatch=mf.has_key):
2341 badmatch=mf.has_key):
2342 names[abs] = (rel, exact)
2342 names[abs] = (rel, exact)
2343 if src == 'b':
2343 if src == 'b':
2344 target_only[abs] = True
2344 target_only[abs] = True
2345
2345
2346 # walk target manifest.
2346 # walk target manifest.
2347
2347
2348 def badmatch(path):
2348 def badmatch(path):
2349 if path in names:
2349 if path in names:
2350 return True
2350 return True
2351 path_ = path + '/'
2351 path_ = path + '/'
2352 for f in names:
2352 for f in names:
2353 if f.startswith(path_):
2353 if f.startswith(path_):
2354 return True
2354 return True
2355 return False
2355 return False
2356
2356
2357 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
2357 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
2358 badmatch=badmatch):
2358 badmatch=badmatch):
2359 if abs in names or src == 'b':
2359 if abs in names or src == 'b':
2360 continue
2360 continue
2361 names[abs] = (rel, exact)
2361 names[abs] = (rel, exact)
2362 target_only[abs] = True
2362 target_only[abs] = True
2363
2363
2364 changes = repo.status(match=names.has_key)[:5]
2364 changes = repo.status(match=names.has_key)[:5]
2365 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
2365 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
2366
2366
2367 # if f is a rename, also revert the source
2367 # if f is a rename, also revert the source
2368 cwd = repo.getcwd()
2368 cwd = repo.getcwd()
2369 for f in added:
2369 for f in added:
2370 src = repo.dirstate.copied(f)
2370 src = repo.dirstate.copied(f)
2371 if src and src not in names and repo.dirstate[src] == 'r':
2371 if src and src not in names and repo.dirstate[src] == 'r':
2372 removed[src] = None
2372 removed[src] = None
2373 names[src] = (repo.pathto(src, cwd), True)
2373 names[src] = (repo.pathto(src, cwd), True)
2374
2374
2375 revert = ([], _('reverting %s\n'))
2375 revert = ([], _('reverting %s\n'))
2376 add = ([], _('adding %s\n'))
2376 add = ([], _('adding %s\n'))
2377 remove = ([], _('removing %s\n'))
2377 remove = ([], _('removing %s\n'))
2378 forget = ([], _('forgetting %s\n'))
2378 forget = ([], _('forgetting %s\n'))
2379 undelete = ([], _('undeleting %s\n'))
2379 undelete = ([], _('undeleting %s\n'))
2380 update = {}
2380 update = {}
2381
2381
2382 disptable = (
2382 disptable = (
2383 # dispatch table:
2383 # dispatch table:
2384 # file state
2384 # file state
2385 # action if in target manifest
2385 # action if in target manifest
2386 # action if not in target manifest
2386 # action if not in target manifest
2387 # make backup if in target manifest
2387 # make backup if in target manifest
2388 # make backup if not in target manifest
2388 # make backup if not in target manifest
2389 (modified, revert, remove, True, True),
2389 (modified, revert, remove, True, True),
2390 (added, revert, forget, True, False),
2390 (added, revert, forget, True, False),
2391 (removed, undelete, None, False, False),
2391 (removed, undelete, None, False, False),
2392 (deleted, revert, remove, False, False),
2392 (deleted, revert, remove, False, False),
2393 (unknown, add, None, True, False),
2393 (unknown, add, None, True, False),
2394 (target_only, add, None, False, False),
2394 (target_only, add, None, False, False),
2395 )
2395 )
2396
2396
2397 entries = names.items()
2397 entries = names.items()
2398 entries.sort()
2398 entries.sort()
2399
2399
2400 for abs, (rel, exact) in entries:
2400 for abs, (rel, exact) in entries:
2401 mfentry = mf.get(abs)
2401 mfentry = mf.get(abs)
2402 target = repo.wjoin(abs)
2402 target = repo.wjoin(abs)
2403 def handle(xlist, dobackup):
2403 def handle(xlist, dobackup):
2404 xlist[0].append(abs)
2404 xlist[0].append(abs)
2405 update[abs] = 1
2405 update[abs] = 1
2406 if dobackup and not opts['no_backup'] and util.lexists(target):
2406 if dobackup and not opts['no_backup'] and util.lexists(target):
2407 bakname = "%s.orig" % rel
2407 bakname = "%s.orig" % rel
2408 ui.note(_('saving current version of %s as %s\n') %
2408 ui.note(_('saving current version of %s as %s\n') %
2409 (rel, bakname))
2409 (rel, bakname))
2410 if not opts.get('dry_run'):
2410 if not opts.get('dry_run'):
2411 util.copyfile(target, bakname)
2411 util.copyfile(target, bakname)
2412 if ui.verbose or not exact:
2412 if ui.verbose or not exact:
2413 ui.status(xlist[1] % rel)
2413 ui.status(xlist[1] % rel)
2414 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2414 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2415 if abs not in table: continue
2415 if abs not in table: continue
2416 # file has changed in dirstate
2416 # file has changed in dirstate
2417 if mfentry:
2417 if mfentry:
2418 handle(hitlist, backuphit)
2418 handle(hitlist, backuphit)
2419 elif misslist is not None:
2419 elif misslist is not None:
2420 handle(misslist, backupmiss)
2420 handle(misslist, backupmiss)
2421 else:
2421 else:
2422 if exact: ui.warn(_('file not managed: %s\n') % rel)
2422 if exact: ui.warn(_('file not managed: %s\n') % rel)
2423 break
2423 break
2424 else:
2424 else:
2425 # file has not changed in dirstate
2425 # file has not changed in dirstate
2426 if node == parent:
2426 if node == parent:
2427 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2427 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2428 continue
2428 continue
2429 if pmf is None:
2429 if pmf is None:
2430 # only need parent manifest in this unlikely case,
2430 # only need parent manifest in this unlikely case,
2431 # so do not read by default
2431 # so do not read by default
2432 pmf = repo.changectx(parent).manifest()
2432 pmf = repo.changectx(parent).manifest()
2433 if abs in pmf:
2433 if abs in pmf:
2434 if mfentry:
2434 if mfentry:
2435 # if version of file is same in parent and target
2435 # if version of file is same in parent and target
2436 # manifests, do nothing
2436 # manifests, do nothing
2437 if pmf[abs] != mfentry:
2437 if pmf[abs] != mfentry:
2438 handle(revert, False)
2438 handle(revert, False)
2439 else:
2439 else:
2440 handle(remove, False)
2440 handle(remove, False)
2441
2441
2442 if not opts.get('dry_run'):
2442 if not opts.get('dry_run'):
2443 for f in forget[0]:
2443 for f in forget[0]:
2444 repo.dirstate.forget(f)
2444 repo.dirstate.forget(f)
2445 r = hg.revert(repo, node, update.has_key)
2445 r = hg.revert(repo, node, update.has_key)
2446 for f in add[0]:
2446 for f in add[0]:
2447 repo.dirstate.add(f)
2447 repo.dirstate.add(f)
2448 for f in undelete[0]:
2448 for f in undelete[0]:
2449 repo.dirstate.normal(f)
2449 repo.dirstate.normal(f)
2450 for f in remove[0]:
2450 for f in remove[0]:
2451 repo.dirstate.remove(f)
2451 repo.dirstate.remove(f)
2452 return r
2452 return r
2453 finally:
2453 finally:
2454 del wlock
2454 del wlock
2455
2455
2456 def rollback(ui, repo):
2456 def rollback(ui, repo):
2457 """roll back the last transaction in this repository
2457 """roll back the last transaction
2458
2458
2459 Roll back the last transaction in this repository, restoring the
2459 This command should be used with care. There is only one level of
2460 project to its state prior to the transaction.
2460 rollback, and there is no way to undo a rollback. It will also
2461 restore the dirstate at the time of the last transaction, losing
2462 any dirstate changes since that time.
2461
2463
2462 Transactions are used to encapsulate the effects of all commands
2464 Transactions are used to encapsulate the effects of all commands
2463 that create new changesets or propagate existing changesets into a
2465 that create new changesets or propagate existing changesets into a
2464 repository. For example, the following commands are transactional,
2466 repository. For example, the following commands are transactional,
2465 and their effects can be rolled back:
2467 and their effects can be rolled back:
2466
2468
2467 commit
2469 commit
2468 import
2470 import
2469 pull
2471 pull
2470 push (with this repository as destination)
2472 push (with this repository as destination)
2471 unbundle
2473 unbundle
2472
2474
2473 This command should be used with care. There is only one level of
2474 rollback, and there is no way to undo a rollback. It will also
2475 restore the dirstate at the time of the last transaction, which
2476 may lose subsequent dirstate changes.
2477
2478 This command is not intended for use on public repositories. Once
2475 This command is not intended for use on public repositories. Once
2479 changes are visible for pull by other users, rolling a transaction
2476 changes are visible for pull by other users, rolling a transaction
2480 back locally is ineffective (someone else may already have pulled
2477 back locally is ineffective (someone else may already have pulled
2481 the changes). Furthermore, a race is possible with readers of the
2478 the changes). Furthermore, a race is possible with readers of the
2482 repository; for example an in-progress pull from the repository
2479 repository; for example an in-progress pull from the repository
2483 may fail if a rollback is performed.
2480 may fail if a rollback is performed.
2484 """
2481 """
2485 repo.rollback()
2482 repo.rollback()
2486
2483
2487 def root(ui, repo):
2484 def root(ui, repo):
2488 """print the root (top) of the current working dir
2485 """print the root (top) of the current working dir
2489
2486
2490 Print the root directory of the current repository.
2487 Print the root directory of the current repository.
2491 """
2488 """
2492 ui.write(repo.root + "\n")
2489 ui.write(repo.root + "\n")
2493
2490
2494 def serve(ui, repo, **opts):
2491 def serve(ui, repo, **opts):
2495 """export the repository via HTTP
2492 """export the repository via HTTP
2496
2493
2497 Start a local HTTP repository browser and pull server.
2494 Start a local HTTP repository browser and pull server.
2498
2495
2499 By default, the server logs accesses to stdout and errors to
2496 By default, the server logs accesses to stdout and errors to
2500 stderr. Use the "-A" and "-E" options to log to files.
2497 stderr. Use the "-A" and "-E" options to log to files.
2501 """
2498 """
2502
2499
2503 if opts["stdio"]:
2500 if opts["stdio"]:
2504 if repo is None:
2501 if repo is None:
2505 raise hg.RepoError(_("There is no Mercurial repository here"
2502 raise hg.RepoError(_("There is no Mercurial repository here"
2506 " (.hg not found)"))
2503 " (.hg not found)"))
2507 s = sshserver.sshserver(ui, repo)
2504 s = sshserver.sshserver(ui, repo)
2508 s.serve_forever()
2505 s.serve_forever()
2509
2506
2510 parentui = ui.parentui or ui
2507 parentui = ui.parentui or ui
2511 optlist = ("name templates style address port ipv6"
2508 optlist = ("name templates style address port ipv6"
2512 " accesslog errorlog webdir_conf certificate")
2509 " accesslog errorlog webdir_conf certificate")
2513 for o in optlist.split():
2510 for o in optlist.split():
2514 if opts[o]:
2511 if opts[o]:
2515 parentui.setconfig("web", o, str(opts[o]))
2512 parentui.setconfig("web", o, str(opts[o]))
2516 if (repo is not None) and (repo.ui != parentui):
2513 if (repo is not None) and (repo.ui != parentui):
2517 repo.ui.setconfig("web", o, str(opts[o]))
2514 repo.ui.setconfig("web", o, str(opts[o]))
2518
2515
2519 if repo is None and not ui.config("web", "webdir_conf"):
2516 if repo is None and not ui.config("web", "webdir_conf"):
2520 raise hg.RepoError(_("There is no Mercurial repository here"
2517 raise hg.RepoError(_("There is no Mercurial repository here"
2521 " (.hg not found)"))
2518 " (.hg not found)"))
2522
2519
2523 class service:
2520 class service:
2524 def init(self):
2521 def init(self):
2525 util.set_signal_handler()
2522 util.set_signal_handler()
2526 try:
2523 try:
2527 self.httpd = hgweb.server.create_server(parentui, repo)
2524 self.httpd = hgweb.server.create_server(parentui, repo)
2528 except socket.error, inst:
2525 except socket.error, inst:
2529 raise util.Abort(_('cannot start server: ') + inst.args[1])
2526 raise util.Abort(_('cannot start server: ') + inst.args[1])
2530
2527
2531 if not ui.verbose: return
2528 if not ui.verbose: return
2532
2529
2533 if self.httpd.port != 80:
2530 if self.httpd.port != 80:
2534 ui.status(_('listening at http://%s:%d/\n') %
2531 ui.status(_('listening at http://%s:%d/\n') %
2535 (self.httpd.addr, self.httpd.port))
2532 (self.httpd.addr, self.httpd.port))
2536 else:
2533 else:
2537 ui.status(_('listening at http://%s/\n') % self.httpd.addr)
2534 ui.status(_('listening at http://%s/\n') % self.httpd.addr)
2538
2535
2539 def run(self):
2536 def run(self):
2540 self.httpd.serve_forever()
2537 self.httpd.serve_forever()
2541
2538
2542 service = service()
2539 service = service()
2543
2540
2544 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2541 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2545
2542
2546 def status(ui, repo, *pats, **opts):
2543 def status(ui, repo, *pats, **opts):
2547 """show changed files in the working directory
2544 """show changed files in the working directory
2548
2545
2549 Show status of files in the repository. If names are given, only
2546 Show status of files in the repository. If names are given, only
2550 files that match are shown. Files that are clean or ignored, are
2547 files that match are shown. Files that are clean or ignored, are
2551 not listed unless -c (clean), -i (ignored) or -A is given.
2548 not listed unless -c (clean), -i (ignored) or -A is given.
2552
2549
2553 NOTE: status may appear to disagree with diff if permissions have
2550 NOTE: status may appear to disagree with diff if permissions have
2554 changed or a merge has occurred. The standard diff format does not
2551 changed or a merge has occurred. The standard diff format does not
2555 report permission changes and diff only reports changes relative
2552 report permission changes and diff only reports changes relative
2556 to one merge parent.
2553 to one merge parent.
2557
2554
2558 If one revision is given, it is used as the base revision.
2555 If one revision is given, it is used as the base revision.
2559 If two revisions are given, the difference between them is shown.
2556 If two revisions are given, the difference between them is shown.
2560
2557
2561 The codes used to show the status of files are:
2558 The codes used to show the status of files are:
2562 M = modified
2559 M = modified
2563 A = added
2560 A = added
2564 R = removed
2561 R = removed
2565 C = clean
2562 C = clean
2566 ! = deleted, but still tracked
2563 ! = deleted, but still tracked
2567 ? = not tracked
2564 ? = not tracked
2568 I = ignored (not shown by default)
2565 I = ignored (not shown by default)
2569 = the previous added file was copied from here
2566 = the previous added file was copied from here
2570 """
2567 """
2571
2568
2572 all = opts['all']
2569 all = opts['all']
2573 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2570 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2574
2571
2575 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2572 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2576 cwd = (pats and repo.getcwd()) or ''
2573 cwd = (pats and repo.getcwd()) or ''
2577 modified, added, removed, deleted, unknown, ignored, clean = [
2574 modified, added, removed, deleted, unknown, ignored, clean = [
2578 n for n in repo.status(node1=node1, node2=node2, files=files,
2575 n for n in repo.status(node1=node1, node2=node2, files=files,
2579 match=matchfn,
2576 match=matchfn,
2580 list_ignored=all or opts['ignored'],
2577 list_ignored=all or opts['ignored'],
2581 list_clean=all or opts['clean'])]
2578 list_clean=all or opts['clean'])]
2582
2579
2583 changetypes = (('modified', 'M', modified),
2580 changetypes = (('modified', 'M', modified),
2584 ('added', 'A', added),
2581 ('added', 'A', added),
2585 ('removed', 'R', removed),
2582 ('removed', 'R', removed),
2586 ('deleted', '!', deleted),
2583 ('deleted', '!', deleted),
2587 ('unknown', '?', unknown),
2584 ('unknown', '?', unknown),
2588 ('ignored', 'I', ignored))
2585 ('ignored', 'I', ignored))
2589
2586
2590 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2587 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2591
2588
2592 end = opts['print0'] and '\0' or '\n'
2589 end = opts['print0'] and '\0' or '\n'
2593
2590
2594 for opt, char, changes in ([ct for ct in explicit_changetypes
2591 for opt, char, changes in ([ct for ct in explicit_changetypes
2595 if all or opts[ct[0]]]
2592 if all or opts[ct[0]]]
2596 or changetypes):
2593 or changetypes):
2597 if opts['no_status']:
2594 if opts['no_status']:
2598 format = "%%s%s" % end
2595 format = "%%s%s" % end
2599 else:
2596 else:
2600 format = "%s %%s%s" % (char, end)
2597 format = "%s %%s%s" % (char, end)
2601
2598
2602 for f in changes:
2599 for f in changes:
2603 ui.write(format % repo.pathto(f, cwd))
2600 ui.write(format % repo.pathto(f, cwd))
2604 if ((all or opts.get('copies')) and not opts.get('no_status')):
2601 if ((all or opts.get('copies')) and not opts.get('no_status')):
2605 copied = repo.dirstate.copied(f)
2602 copied = repo.dirstate.copied(f)
2606 if copied:
2603 if copied:
2607 ui.write(' %s%s' % (repo.pathto(copied, cwd), end))
2604 ui.write(' %s%s' % (repo.pathto(copied, cwd), end))
2608
2605
2609 def tag(ui, repo, name, rev_=None, **opts):
2606 def tag(ui, repo, name, rev_=None, **opts):
2610 """add a tag for the current or given revision
2607 """add a tag for the current or given revision
2611
2608
2612 Name a particular revision using <name>.
2609 Name a particular revision using <name>.
2613
2610
2614 Tags are used to name particular revisions of the repository and are
2611 Tags are used to name particular revisions of the repository and are
2615 very useful to compare different revision, to go back to significant
2612 very useful to compare different revision, to go back to significant
2616 earlier versions or to mark branch points as releases, etc.
2613 earlier versions or to mark branch points as releases, etc.
2617
2614
2618 If no revision is given, the parent of the working directory is used,
2615 If no revision is given, the parent of the working directory is used,
2619 or tip if no revision is checked out.
2616 or tip if no revision is checked out.
2620
2617
2621 To facilitate version control, distribution, and merging of tags,
2618 To facilitate version control, distribution, and merging of tags,
2622 they are stored as a file named ".hgtags" which is managed
2619 they are stored as a file named ".hgtags" which is managed
2623 similarly to other project files and can be hand-edited if
2620 similarly to other project files and can be hand-edited if
2624 necessary. The file '.hg/localtags' is used for local tags (not
2621 necessary. The file '.hg/localtags' is used for local tags (not
2625 shared among repositories).
2622 shared among repositories).
2626 """
2623 """
2627 if name in ['tip', '.', 'null']:
2624 if name in ['tip', '.', 'null']:
2628 raise util.Abort(_("the name '%s' is reserved") % name)
2625 raise util.Abort(_("the name '%s' is reserved") % name)
2629 if rev_ is not None:
2626 if rev_ is not None:
2630 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2627 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2631 "please use 'hg tag [-r REV] NAME' instead\n"))
2628 "please use 'hg tag [-r REV] NAME' instead\n"))
2632 if opts['rev']:
2629 if opts['rev']:
2633 raise util.Abort(_("use only one form to specify the revision"))
2630 raise util.Abort(_("use only one form to specify the revision"))
2634 if opts['rev'] and opts['remove']:
2631 if opts['rev'] and opts['remove']:
2635 raise util.Abort(_("--rev and --remove are incompatible"))
2632 raise util.Abort(_("--rev and --remove are incompatible"))
2636 if opts['rev']:
2633 if opts['rev']:
2637 rev_ = opts['rev']
2634 rev_ = opts['rev']
2638 message = opts['message']
2635 message = opts['message']
2639 if opts['remove']:
2636 if opts['remove']:
2640 if not name in repo.tags():
2637 if not name in repo.tags():
2641 raise util.Abort(_('tag %s does not exist') % name)
2638 raise util.Abort(_('tag %s does not exist') % name)
2642 rev_ = nullid
2639 rev_ = nullid
2643 if not message:
2640 if not message:
2644 message = _('Removed tag %s') % name
2641 message = _('Removed tag %s') % name
2645 elif name in repo.tags() and not opts['force']:
2642 elif name in repo.tags() and not opts['force']:
2646 raise util.Abort(_('a tag named %s already exists (use -f to force)')
2643 raise util.Abort(_('a tag named %s already exists (use -f to force)')
2647 % name)
2644 % name)
2648 if not rev_ and repo.dirstate.parents()[1] != nullid:
2645 if not rev_ and repo.dirstate.parents()[1] != nullid:
2649 raise util.Abort(_('uncommitted merge - please provide a '
2646 raise util.Abort(_('uncommitted merge - please provide a '
2650 'specific revision'))
2647 'specific revision'))
2651 r = repo.changectx(rev_).node()
2648 r = repo.changectx(rev_).node()
2652
2649
2653 if not message:
2650 if not message:
2654 message = _('Added tag %s for changeset %s') % (name, short(r))
2651 message = _('Added tag %s for changeset %s') % (name, short(r))
2655
2652
2656 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2653 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2657
2654
2658 def tags(ui, repo):
2655 def tags(ui, repo):
2659 """list repository tags
2656 """list repository tags
2660
2657
2661 List the repository tags.
2658 List the repository tags.
2662
2659
2663 This lists both regular and local tags.
2660 This lists both regular and local tags.
2664 """
2661 """
2665
2662
2666 l = repo.tagslist()
2663 l = repo.tagslist()
2667 l.reverse()
2664 l.reverse()
2668 hexfunc = ui.debugflag and hex or short
2665 hexfunc = ui.debugflag and hex or short
2669 for t, n in l:
2666 for t, n in l:
2670 try:
2667 try:
2671 hn = hexfunc(n)
2668 hn = hexfunc(n)
2672 r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n))
2669 r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n))
2673 except revlog.LookupError:
2670 except revlog.LookupError:
2674 r = " ?:%s" % hn
2671 r = " ?:%s" % hn
2675 if ui.quiet:
2672 if ui.quiet:
2676 ui.write("%s\n" % t)
2673 ui.write("%s\n" % t)
2677 else:
2674 else:
2678 spaces = " " * (30 - util.locallen(t))
2675 spaces = " " * (30 - util.locallen(t))
2679 ui.write("%s%s %s\n" % (t, spaces, r))
2676 ui.write("%s%s %s\n" % (t, spaces, r))
2680
2677
2681 def tip(ui, repo, **opts):
2678 def tip(ui, repo, **opts):
2682 """show the tip revision
2679 """show the tip revision
2683
2680
2684 Show the tip revision.
2681 Show the tip revision.
2685 """
2682 """
2686 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2683 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2687
2684
2688 def unbundle(ui, repo, fname1, *fnames, **opts):
2685 def unbundle(ui, repo, fname1, *fnames, **opts):
2689 """apply one or more changegroup files
2686 """apply one or more changegroup files
2690
2687
2691 Apply one or more compressed changegroup files generated by the
2688 Apply one or more compressed changegroup files generated by the
2692 bundle command.
2689 bundle command.
2693 """
2690 """
2694 fnames = (fname1,) + fnames
2691 fnames = (fname1,) + fnames
2695 for fname in fnames:
2692 for fname in fnames:
2696 if os.path.exists(fname):
2693 if os.path.exists(fname):
2697 f = open(fname, "rb")
2694 f = open(fname, "rb")
2698 else:
2695 else:
2699 f = urllib.urlopen(fname)
2696 f = urllib.urlopen(fname)
2700 gen = changegroup.readbundle(f, fname)
2697 gen = changegroup.readbundle(f, fname)
2701 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2698 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2702
2699
2703 return postincoming(ui, repo, modheads, opts['update'], None)
2700 return postincoming(ui, repo, modheads, opts['update'], None)
2704
2701
2705 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2702 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2706 """update working directory
2703 """update working directory
2707
2704
2708 Update the working directory to the specified revision, or the
2705 Update the working directory to the specified revision, or the
2709 tip of the current branch if none is specified.
2706 tip of the current branch if none is specified.
2710
2707
2711 If there are no outstanding changes in the working directory and
2708 If there are no outstanding changes in the working directory and
2712 there is a linear relationship between the current version and the
2709 there is a linear relationship between the current version and the
2713 requested version, the result is the requested version.
2710 requested version, the result is the requested version.
2714
2711
2715 To merge the working directory with another revision, use the
2712 To merge the working directory with another revision, use the
2716 merge command.
2713 merge command.
2717
2714
2718 By default, update will refuse to run if doing so would require
2715 By default, update will refuse to run if doing so would require
2719 discarding local changes.
2716 discarding local changes.
2720 """
2717 """
2721 if rev and node:
2718 if rev and node:
2722 raise util.Abort(_("please specify just one revision"))
2719 raise util.Abort(_("please specify just one revision"))
2723
2720
2724 if not rev:
2721 if not rev:
2725 rev = node
2722 rev = node
2726
2723
2727 if date:
2724 if date:
2728 if rev:
2725 if rev:
2729 raise util.Abort(_("you can't specify a revision and a date"))
2726 raise util.Abort(_("you can't specify a revision and a date"))
2730 rev = cmdutil.finddate(ui, repo, date)
2727 rev = cmdutil.finddate(ui, repo, date)
2731
2728
2732 if clean:
2729 if clean:
2733 return hg.clean(repo, rev)
2730 return hg.clean(repo, rev)
2734 else:
2731 else:
2735 return hg.update(repo, rev)
2732 return hg.update(repo, rev)
2736
2733
2737 def verify(ui, repo):
2734 def verify(ui, repo):
2738 """verify the integrity of the repository
2735 """verify the integrity of the repository
2739
2736
2740 Verify the integrity of the current repository.
2737 Verify the integrity of the current repository.
2741
2738
2742 This will perform an extensive check of the repository's
2739 This will perform an extensive check of the repository's
2743 integrity, validating the hashes and checksums of each entry in
2740 integrity, validating the hashes and checksums of each entry in
2744 the changelog, manifest, and tracked files, as well as the
2741 the changelog, manifest, and tracked files, as well as the
2745 integrity of their crosslinks and indices.
2742 integrity of their crosslinks and indices.
2746 """
2743 """
2747 return hg.verify(repo)
2744 return hg.verify(repo)
2748
2745
2749 def version_(ui):
2746 def version_(ui):
2750 """output version and copyright information"""
2747 """output version and copyright information"""
2751 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2748 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2752 % version.get_version())
2749 % version.get_version())
2753 ui.status(_(
2750 ui.status(_(
2754 "\nCopyright (C) 2005-2007 Matt Mackall <mpm@selenic.com> and others\n"
2751 "\nCopyright (C) 2005-2007 Matt Mackall <mpm@selenic.com> and others\n"
2755 "This is free software; see the source for copying conditions. "
2752 "This is free software; see the source for copying conditions. "
2756 "There is NO\nwarranty; "
2753 "There is NO\nwarranty; "
2757 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2754 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2758 ))
2755 ))
2759
2756
2760 # Command options and aliases are listed here, alphabetically
2757 # Command options and aliases are listed here, alphabetically
2761
2758
2762 globalopts = [
2759 globalopts = [
2763 ('R', 'repository', '',
2760 ('R', 'repository', '',
2764 _('repository root directory or symbolic path name')),
2761 _('repository root directory or symbolic path name')),
2765 ('', 'cwd', '', _('change working directory')),
2762 ('', 'cwd', '', _('change working directory')),
2766 ('y', 'noninteractive', None,
2763 ('y', 'noninteractive', None,
2767 _('do not prompt, assume \'yes\' for any required answers')),
2764 _('do not prompt, assume \'yes\' for any required answers')),
2768 ('q', 'quiet', None, _('suppress output')),
2765 ('q', 'quiet', None, _('suppress output')),
2769 ('v', 'verbose', None, _('enable additional output')),
2766 ('v', 'verbose', None, _('enable additional output')),
2770 ('', 'config', [], _('set/override config option')),
2767 ('', 'config', [], _('set/override config option')),
2771 ('', 'debug', None, _('enable debugging output')),
2768 ('', 'debug', None, _('enable debugging output')),
2772 ('', 'debugger', None, _('start debugger')),
2769 ('', 'debugger', None, _('start debugger')),
2773 ('', 'encoding', util._encoding, _('set the charset encoding')),
2770 ('', 'encoding', util._encoding, _('set the charset encoding')),
2774 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2771 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2775 ('', 'lsprof', None, _('print improved command execution profile')),
2772 ('', 'lsprof', None, _('print improved command execution profile')),
2776 ('', 'traceback', None, _('print traceback on exception')),
2773 ('', 'traceback', None, _('print traceback on exception')),
2777 ('', 'time', None, _('time how long the command takes')),
2774 ('', 'time', None, _('time how long the command takes')),
2778 ('', 'profile', None, _('print command execution profile')),
2775 ('', 'profile', None, _('print command execution profile')),
2779 ('', 'version', None, _('output version information and exit')),
2776 ('', 'version', None, _('output version information and exit')),
2780 ('h', 'help', None, _('display help and exit')),
2777 ('h', 'help', None, _('display help and exit')),
2781 ]
2778 ]
2782
2779
2783 dryrunopts = [('n', 'dry-run', None,
2780 dryrunopts = [('n', 'dry-run', None,
2784 _('do not perform actions, just print output'))]
2781 _('do not perform actions, just print output'))]
2785
2782
2786 remoteopts = [
2783 remoteopts = [
2787 ('e', 'ssh', '', _('specify ssh command to use')),
2784 ('e', 'ssh', '', _('specify ssh command to use')),
2788 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2785 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2789 ]
2786 ]
2790
2787
2791 walkopts = [
2788 walkopts = [
2792 ('I', 'include', [], _('include names matching the given patterns')),
2789 ('I', 'include', [], _('include names matching the given patterns')),
2793 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2790 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2794 ]
2791 ]
2795
2792
2796 commitopts = [
2793 commitopts = [
2797 ('m', 'message', '', _('use <text> as commit message')),
2794 ('m', 'message', '', _('use <text> as commit message')),
2798 ('l', 'logfile', '', _('read commit message from <file>')),
2795 ('l', 'logfile', '', _('read commit message from <file>')),
2799 ]
2796 ]
2800
2797
2801 commitopts2 = [
2798 commitopts2 = [
2802 ('d', 'date', '', _('record datecode as commit date')),
2799 ('d', 'date', '', _('record datecode as commit date')),
2803 ('u', 'user', '', _('record user as committer')),
2800 ('u', 'user', '', _('record user as committer')),
2804 ]
2801 ]
2805
2802
2806 table = {
2803 table = {
2807 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2804 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2808 "addremove":
2805 "addremove":
2809 (addremove,
2806 (addremove,
2810 [('s', 'similarity', '',
2807 [('s', 'similarity', '',
2811 _('guess renamed files by similarity (0<=s<=100)')),
2808 _('guess renamed files by similarity (0<=s<=100)')),
2812 ] + walkopts + dryrunopts,
2809 ] + walkopts + dryrunopts,
2813 _('hg addremove [OPTION]... [FILE]...')),
2810 _('hg addremove [OPTION]... [FILE]...')),
2814 "^annotate":
2811 "^annotate":
2815 (annotate,
2812 (annotate,
2816 [('r', 'rev', '', _('annotate the specified revision')),
2813 [('r', 'rev', '', _('annotate the specified revision')),
2817 ('f', 'follow', None, _('follow file copies and renames')),
2814 ('f', 'follow', None, _('follow file copies and renames')),
2818 ('a', 'text', None, _('treat all files as text')),
2815 ('a', 'text', None, _('treat all files as text')),
2819 ('u', 'user', None, _('list the author')),
2816 ('u', 'user', None, _('list the author')),
2820 ('d', 'date', None, _('list the date')),
2817 ('d', 'date', None, _('list the date')),
2821 ('n', 'number', None, _('list the revision number (default)')),
2818 ('n', 'number', None, _('list the revision number (default)')),
2822 ('c', 'changeset', None, _('list the changeset')),
2819 ('c', 'changeset', None, _('list the changeset')),
2823 ('l', 'line-number', None,
2820 ('l', 'line-number', None,
2824 _('show line number at the first appearance'))
2821 _('show line number at the first appearance'))
2825 ] + walkopts,
2822 ] + walkopts,
2826 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2823 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2827 "archive":
2824 "archive":
2828 (archive,
2825 (archive,
2829 [('', 'no-decode', None, _('do not pass files through decoders')),
2826 [('', 'no-decode', None, _('do not pass files through decoders')),
2830 ('p', 'prefix', '', _('directory prefix for files in archive')),
2827 ('p', 'prefix', '', _('directory prefix for files in archive')),
2831 ('r', 'rev', '', _('revision to distribute')),
2828 ('r', 'rev', '', _('revision to distribute')),
2832 ('t', 'type', '', _('type of distribution to create')),
2829 ('t', 'type', '', _('type of distribution to create')),
2833 ] + walkopts,
2830 ] + walkopts,
2834 _('hg archive [OPTION]... DEST')),
2831 _('hg archive [OPTION]... DEST')),
2835 "backout":
2832 "backout":
2836 (backout,
2833 (backout,
2837 [('', 'merge', None,
2834 [('', 'merge', None,
2838 _('merge with old dirstate parent after backout')),
2835 _('merge with old dirstate parent after backout')),
2839 ('', 'parent', '', _('parent to choose when backing out merge')),
2836 ('', 'parent', '', _('parent to choose when backing out merge')),
2840 ('r', 'rev', '', _('revision to backout')),
2837 ('r', 'rev', '', _('revision to backout')),
2841 ] + walkopts + commitopts + commitopts2,
2838 ] + walkopts + commitopts + commitopts2,
2842 _('hg backout [OPTION]... [-r] REV')),
2839 _('hg backout [OPTION]... [-r] REV')),
2843 "branch":
2840 "branch":
2844 (branch,
2841 (branch,
2845 [('f', 'force', None,
2842 [('f', 'force', None,
2846 _('set branch name even if it shadows an existing branch'))],
2843 _('set branch name even if it shadows an existing branch'))],
2847 _('hg branch [NAME]')),
2844 _('hg branch [NAME]')),
2848 "branches":
2845 "branches":
2849 (branches,
2846 (branches,
2850 [('a', 'active', False,
2847 [('a', 'active', False,
2851 _('show only branches that have unmerged heads'))],
2848 _('show only branches that have unmerged heads'))],
2852 _('hg branches [-a]')),
2849 _('hg branches [-a]')),
2853 "bundle":
2850 "bundle":
2854 (bundle,
2851 (bundle,
2855 [('f', 'force', None,
2852 [('f', 'force', None,
2856 _('run even when remote repository is unrelated')),
2853 _('run even when remote repository is unrelated')),
2857 ('r', 'rev', [],
2854 ('r', 'rev', [],
2858 _('a changeset you would like to bundle')),
2855 _('a changeset you would like to bundle')),
2859 ('', 'base', [],
2856 ('', 'base', [],
2860 _('a base changeset to specify instead of a destination')),
2857 _('a base changeset to specify instead of a destination')),
2861 ] + remoteopts,
2858 ] + remoteopts,
2862 _('hg bundle [-f] [-r REV]... [--base REV]... FILE [DEST]')),
2859 _('hg bundle [-f] [-r REV]... [--base REV]... FILE [DEST]')),
2863 "cat":
2860 "cat":
2864 (cat,
2861 (cat,
2865 [('o', 'output', '', _('print output to file with formatted name')),
2862 [('o', 'output', '', _('print output to file with formatted name')),
2866 ('r', 'rev', '', _('print the given revision')),
2863 ('r', 'rev', '', _('print the given revision')),
2867 ] + walkopts,
2864 ] + walkopts,
2868 _('hg cat [OPTION]... FILE...')),
2865 _('hg cat [OPTION]... FILE...')),
2869 "^clone":
2866 "^clone":
2870 (clone,
2867 (clone,
2871 [('U', 'noupdate', None, _('do not update the new working directory')),
2868 [('U', 'noupdate', None, _('do not update the new working directory')),
2872 ('r', 'rev', [],
2869 ('r', 'rev', [],
2873 _('a changeset you would like to have after cloning')),
2870 _('a changeset you would like to have after cloning')),
2874 ('', 'pull', None, _('use pull protocol to copy metadata')),
2871 ('', 'pull', None, _('use pull protocol to copy metadata')),
2875 ('', 'uncompressed', None,
2872 ('', 'uncompressed', None,
2876 _('use uncompressed transfer (fast over LAN)')),
2873 _('use uncompressed transfer (fast over LAN)')),
2877 ] + remoteopts,
2874 ] + remoteopts,
2878 _('hg clone [OPTION]... SOURCE [DEST]')),
2875 _('hg clone [OPTION]... SOURCE [DEST]')),
2879 "^commit|ci":
2876 "^commit|ci":
2880 (commit,
2877 (commit,
2881 [('A', 'addremove', None,
2878 [('A', 'addremove', None,
2882 _('mark new/missing files as added/removed before committing')),
2879 _('mark new/missing files as added/removed before committing')),
2883 ] + walkopts + commitopts + commitopts2,
2880 ] + walkopts + commitopts + commitopts2,
2884 _('hg commit [OPTION]... [FILE]...')),
2881 _('hg commit [OPTION]... [FILE]...')),
2885 "copy|cp":
2882 "copy|cp":
2886 (copy,
2883 (copy,
2887 [('A', 'after', None, _('record a copy that has already occurred')),
2884 [('A', 'after', None, _('record a copy that has already occurred')),
2888 ('f', 'force', None,
2885 ('f', 'force', None,
2889 _('forcibly copy over an existing managed file')),
2886 _('forcibly copy over an existing managed file')),
2890 ] + walkopts + dryrunopts,
2887 ] + walkopts + dryrunopts,
2891 _('hg copy [OPTION]... [SOURCE]... DEST')),
2888 _('hg copy [OPTION]... [SOURCE]... DEST')),
2892 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2889 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2893 "debugcomplete":
2890 "debugcomplete":
2894 (debugcomplete,
2891 (debugcomplete,
2895 [('o', 'options', None, _('show the command options'))],
2892 [('o', 'options', None, _('show the command options'))],
2896 _('debugcomplete [-o] CMD')),
2893 _('debugcomplete [-o] CMD')),
2897 "debuginstall": (debuginstall, [], _('debuginstall')),
2894 "debuginstall": (debuginstall, [], _('debuginstall')),
2898 "debugrebuildstate":
2895 "debugrebuildstate":
2899 (debugrebuildstate,
2896 (debugrebuildstate,
2900 [('r', 'rev', '', _('revision to rebuild to'))],
2897 [('r', 'rev', '', _('revision to rebuild to'))],
2901 _('debugrebuildstate [-r REV] [REV]')),
2898 _('debugrebuildstate [-r REV] [REV]')),
2902 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2899 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2903 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2900 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2904 "debugstate": (debugstate, [], _('debugstate')),
2901 "debugstate": (debugstate, [], _('debugstate')),
2905 "debugdate":
2902 "debugdate":
2906 (debugdate,
2903 (debugdate,
2907 [('e', 'extended', None, _('try extended date formats'))],
2904 [('e', 'extended', None, _('try extended date formats'))],
2908 _('debugdate [-e] DATE [RANGE]')),
2905 _('debugdate [-e] DATE [RANGE]')),
2909 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2906 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2910 "debugindex": (debugindex, [], _('debugindex FILE')),
2907 "debugindex": (debugindex, [], _('debugindex FILE')),
2911 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2908 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2912 "debugrename":
2909 "debugrename":
2913 (debugrename,
2910 (debugrename,
2914 [('r', 'rev', '', _('revision to debug'))],
2911 [('r', 'rev', '', _('revision to debug'))],
2915 _('debugrename [-r REV] FILE')),
2912 _('debugrename [-r REV] FILE')),
2916 "debugwalk": (debugwalk, walkopts, _('debugwalk [OPTION]... [FILE]...')),
2913 "debugwalk": (debugwalk, walkopts, _('debugwalk [OPTION]... [FILE]...')),
2917 "^diff":
2914 "^diff":
2918 (diff,
2915 (diff,
2919 [('r', 'rev', [], _('revision')),
2916 [('r', 'rev', [], _('revision')),
2920 ('a', 'text', None, _('treat all files as text')),
2917 ('a', 'text', None, _('treat all files as text')),
2921 ('p', 'show-function', None,
2918 ('p', 'show-function', None,
2922 _('show which function each change is in')),
2919 _('show which function each change is in')),
2923 ('g', 'git', None, _('use git extended diff format')),
2920 ('g', 'git', None, _('use git extended diff format')),
2924 ('', 'nodates', None, _("don't include dates in diff headers")),
2921 ('', 'nodates', None, _("don't include dates in diff headers")),
2925 ('w', 'ignore-all-space', None,
2922 ('w', 'ignore-all-space', None,
2926 _('ignore white space when comparing lines')),
2923 _('ignore white space when comparing lines')),
2927 ('b', 'ignore-space-change', None,
2924 ('b', 'ignore-space-change', None,
2928 _('ignore changes in the amount of white space')),
2925 _('ignore changes in the amount of white space')),
2929 ('B', 'ignore-blank-lines', None,
2926 ('B', 'ignore-blank-lines', None,
2930 _('ignore changes whose lines are all blank')),
2927 _('ignore changes whose lines are all blank')),
2931 ] + walkopts,
2928 ] + walkopts,
2932 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
2929 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
2933 "^export":
2930 "^export":
2934 (export,
2931 (export,
2935 [('o', 'output', '', _('print output to file with formatted name')),
2932 [('o', 'output', '', _('print output to file with formatted name')),
2936 ('a', 'text', None, _('treat all files as text')),
2933 ('a', 'text', None, _('treat all files as text')),
2937 ('g', 'git', None, _('use git extended diff format')),
2934 ('g', 'git', None, _('use git extended diff format')),
2938 ('', 'nodates', None, _("don't include dates in diff headers")),
2935 ('', 'nodates', None, _("don't include dates in diff headers")),
2939 ('', 'switch-parent', None, _('diff against the second parent'))],
2936 ('', 'switch-parent', None, _('diff against the second parent'))],
2940 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
2937 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
2941 "grep":
2938 "grep":
2942 (grep,
2939 (grep,
2943 [('0', 'print0', None, _('end fields with NUL')),
2940 [('0', 'print0', None, _('end fields with NUL')),
2944 ('', 'all', None, _('print all revisions that match')),
2941 ('', 'all', None, _('print all revisions that match')),
2945 ('f', 'follow', None,
2942 ('f', 'follow', None,
2946 _('follow changeset history, or file history across copies and renames')),
2943 _('follow changeset history, or file history across copies and renames')),
2947 ('i', 'ignore-case', None, _('ignore case when matching')),
2944 ('i', 'ignore-case', None, _('ignore case when matching')),
2948 ('l', 'files-with-matches', None,
2945 ('l', 'files-with-matches', None,
2949 _('print only filenames and revs that match')),
2946 _('print only filenames and revs that match')),
2950 ('n', 'line-number', None, _('print matching line numbers')),
2947 ('n', 'line-number', None, _('print matching line numbers')),
2951 ('r', 'rev', [], _('search in given revision range')),
2948 ('r', 'rev', [], _('search in given revision range')),
2952 ('u', 'user', None, _('print user who committed change')),
2949 ('u', 'user', None, _('print user who committed change')),
2953 ] + walkopts,
2950 ] + walkopts,
2954 _('hg grep [OPTION]... PATTERN [FILE]...')),
2951 _('hg grep [OPTION]... PATTERN [FILE]...')),
2955 "heads":
2952 "heads":
2956 (heads,
2953 (heads,
2957 [('', 'style', '', _('display using template map file')),
2954 [('', 'style', '', _('display using template map file')),
2958 ('r', 'rev', '', _('show only heads which are descendants of rev')),
2955 ('r', 'rev', '', _('show only heads which are descendants of rev')),
2959 ('', 'template', '', _('display with template'))],
2956 ('', 'template', '', _('display with template'))],
2960 _('hg heads [-r REV] [REV]...')),
2957 _('hg heads [-r REV] [REV]...')),
2961 "help": (help_, [], _('hg help [COMMAND]')),
2958 "help": (help_, [], _('hg help [COMMAND]')),
2962 "identify|id":
2959 "identify|id":
2963 (identify,
2960 (identify,
2964 [('r', 'rev', '', _('identify the specified rev')),
2961 [('r', 'rev', '', _('identify the specified rev')),
2965 ('n', 'num', None, _('show local revision number')),
2962 ('n', 'num', None, _('show local revision number')),
2966 ('i', 'id', None, _('show global revision id')),
2963 ('i', 'id', None, _('show global revision id')),
2967 ('b', 'branch', None, _('show branch')),
2964 ('b', 'branch', None, _('show branch')),
2968 ('t', 'tags', None, _('show tags'))],
2965 ('t', 'tags', None, _('show tags'))],
2969 _('hg identify [-nibt] [-r REV] [SOURCE]')),
2966 _('hg identify [-nibt] [-r REV] [SOURCE]')),
2970 "import|patch":
2967 "import|patch":
2971 (import_,
2968 (import_,
2972 [('p', 'strip', 1,
2969 [('p', 'strip', 1,
2973 _('directory strip option for patch. This has the same\n'
2970 _('directory strip option for patch. This has the same\n'
2974 'meaning as the corresponding patch option')),
2971 'meaning as the corresponding patch option')),
2975 ('b', 'base', '', _('base path')),
2972 ('b', 'base', '', _('base path')),
2976 ('f', 'force', None,
2973 ('f', 'force', None,
2977 _('skip check for outstanding uncommitted changes')),
2974 _('skip check for outstanding uncommitted changes')),
2978 ('', 'exact', None,
2975 ('', 'exact', None,
2979 _('apply patch to the nodes from which it was generated')),
2976 _('apply patch to the nodes from which it was generated')),
2980 ('', 'import-branch', None,
2977 ('', 'import-branch', None,
2981 _('Use any branch information in patch (implied by --exact)'))] + commitopts,
2978 _('Use any branch information in patch (implied by --exact)'))] + commitopts,
2982 _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')),
2979 _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')),
2983 "incoming|in": (incoming,
2980 "incoming|in": (incoming,
2984 [('M', 'no-merges', None, _('do not show merges')),
2981 [('M', 'no-merges', None, _('do not show merges')),
2985 ('f', 'force', None,
2982 ('f', 'force', None,
2986 _('run even when remote repository is unrelated')),
2983 _('run even when remote repository is unrelated')),
2987 ('', 'style', '', _('display using template map file')),
2984 ('', 'style', '', _('display using template map file')),
2988 ('n', 'newest-first', None, _('show newest record first')),
2985 ('n', 'newest-first', None, _('show newest record first')),
2989 ('', 'bundle', '', _('file to store the bundles into')),
2986 ('', 'bundle', '', _('file to store the bundles into')),
2990 ('p', 'patch', None, _('show patch')),
2987 ('p', 'patch', None, _('show patch')),
2991 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2988 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2992 ('', 'template', '', _('display with template')),
2989 ('', 'template', '', _('display with template')),
2993 ] + remoteopts,
2990 ] + remoteopts,
2994 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
2991 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
2995 ' [--bundle FILENAME] [SOURCE]')),
2992 ' [--bundle FILENAME] [SOURCE]')),
2996 "^init":
2993 "^init":
2997 (init,
2994 (init,
2998 remoteopts,
2995 remoteopts,
2999 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
2996 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
3000 "locate":
2997 "locate":
3001 (locate,
2998 (locate,
3002 [('r', 'rev', '', _('search the repository as it stood at rev')),
2999 [('r', 'rev', '', _('search the repository as it stood at rev')),
3003 ('0', 'print0', None,
3000 ('0', 'print0', None,
3004 _('end filenames with NUL, for use with xargs')),
3001 _('end filenames with NUL, for use with xargs')),
3005 ('f', 'fullpath', None,
3002 ('f', 'fullpath', None,
3006 _('print complete paths from the filesystem root')),
3003 _('print complete paths from the filesystem root')),
3007 ] + walkopts,
3004 ] + walkopts,
3008 _('hg locate [OPTION]... [PATTERN]...')),
3005 _('hg locate [OPTION]... [PATTERN]...')),
3009 "^log|history":
3006 "^log|history":
3010 (log,
3007 (log,
3011 [('f', 'follow', None,
3008 [('f', 'follow', None,
3012 _('follow changeset history, or file history across copies and renames')),
3009 _('follow changeset history, or file history across copies and renames')),
3013 ('', 'follow-first', None,
3010 ('', 'follow-first', None,
3014 _('only follow the first parent of merge changesets')),
3011 _('only follow the first parent of merge changesets')),
3015 ('d', 'date', '', _('show revs matching date spec')),
3012 ('d', 'date', '', _('show revs matching date spec')),
3016 ('C', 'copies', None, _('show copied files')),
3013 ('C', 'copies', None, _('show copied files')),
3017 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3014 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3018 ('l', 'limit', '', _('limit number of changes displayed')),
3015 ('l', 'limit', '', _('limit number of changes displayed')),
3019 ('r', 'rev', [], _('show the specified revision or range')),
3016 ('r', 'rev', [], _('show the specified revision or range')),
3020 ('', 'removed', None, _('include revs where files were removed')),
3017 ('', 'removed', None, _('include revs where files were removed')),
3021 ('M', 'no-merges', None, _('do not show merges')),
3018 ('M', 'no-merges', None, _('do not show merges')),
3022 ('', 'style', '', _('display using template map file')),
3019 ('', 'style', '', _('display using template map file')),
3023 ('m', 'only-merges', None, _('show only merges')),
3020 ('m', 'only-merges', None, _('show only merges')),
3024 ('p', 'patch', None, _('show patch')),
3021 ('p', 'patch', None, _('show patch')),
3025 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3022 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3026 ('', 'template', '', _('display with template')),
3023 ('', 'template', '', _('display with template')),
3027 ] + walkopts,
3024 ] + walkopts,
3028 _('hg log [OPTION]... [FILE]')),
3025 _('hg log [OPTION]... [FILE]')),
3029 "manifest": (manifest, [('r', 'rev', '', _('revision to display'))],
3026 "manifest": (manifest, [('r', 'rev', '', _('revision to display'))],
3030 _('hg manifest [-r REV]')),
3027 _('hg manifest [-r REV]')),
3031 "^merge":
3028 "^merge":
3032 (merge,
3029 (merge,
3033 [('f', 'force', None, _('force a merge with outstanding changes')),
3030 [('f', 'force', None, _('force a merge with outstanding changes')),
3034 ('r', 'rev', '', _('revision to merge')),
3031 ('r', 'rev', '', _('revision to merge')),
3035 ],
3032 ],
3036 _('hg merge [-f] [[-r] REV]')),
3033 _('hg merge [-f] [[-r] REV]')),
3037 "outgoing|out": (outgoing,
3034 "outgoing|out": (outgoing,
3038 [('M', 'no-merges', None, _('do not show merges')),
3035 [('M', 'no-merges', None, _('do not show merges')),
3039 ('f', 'force', None,
3036 ('f', 'force', None,
3040 _('run even when remote repository is unrelated')),
3037 _('run even when remote repository is unrelated')),
3041 ('p', 'patch', None, _('show patch')),
3038 ('p', 'patch', None, _('show patch')),
3042 ('', 'style', '', _('display using template map file')),
3039 ('', 'style', '', _('display using template map file')),
3043 ('r', 'rev', [], _('a specific revision you would like to push')),
3040 ('r', 'rev', [], _('a specific revision you would like to push')),
3044 ('n', 'newest-first', None, _('show newest record first')),
3041 ('n', 'newest-first', None, _('show newest record first')),
3045 ('', 'template', '', _('display with template')),
3042 ('', 'template', '', _('display with template')),
3046 ] + remoteopts,
3043 ] + remoteopts,
3047 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3044 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3048 "^parents":
3045 "^parents":
3049 (parents,
3046 (parents,
3050 [('r', 'rev', '', _('show parents from the specified rev')),
3047 [('r', 'rev', '', _('show parents from the specified rev')),
3051 ('', 'style', '', _('display using template map file')),
3048 ('', 'style', '', _('display using template map file')),
3052 ('', 'template', '', _('display with template'))],
3049 ('', 'template', '', _('display with template'))],
3053 _('hg parents [-r REV] [FILE]')),
3050 _('hg parents [-r REV] [FILE]')),
3054 "paths": (paths, [], _('hg paths [NAME]')),
3051 "paths": (paths, [], _('hg paths [NAME]')),
3055 "^pull":
3052 "^pull":
3056 (pull,
3053 (pull,
3057 [('u', 'update', None,
3054 [('u', 'update', None,
3058 _('update to new tip if changesets were pulled')),
3055 _('update to new tip if changesets were pulled')),
3059 ('f', 'force', None,
3056 ('f', 'force', None,
3060 _('run even when remote repository is unrelated')),
3057 _('run even when remote repository is unrelated')),
3061 ('r', 'rev', [],
3058 ('r', 'rev', [],
3062 _('a specific revision up to which you would like to pull')),
3059 _('a specific revision up to which you would like to pull')),
3063 ] + remoteopts,
3060 ] + remoteopts,
3064 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3061 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3065 "^push":
3062 "^push":
3066 (push,
3063 (push,
3067 [('f', 'force', None, _('force push')),
3064 [('f', 'force', None, _('force push')),
3068 ('r', 'rev', [], _('a specific revision you would like to push')),
3065 ('r', 'rev', [], _('a specific revision you would like to push')),
3069 ] + remoteopts,
3066 ] + remoteopts,
3070 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3067 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3071 "debugrawcommit|rawcommit":
3068 "debugrawcommit|rawcommit":
3072 (rawcommit,
3069 (rawcommit,
3073 [('p', 'parent', [], _('parent')),
3070 [('p', 'parent', [], _('parent')),
3074 ('F', 'files', '', _('file list'))
3071 ('F', 'files', '', _('file list'))
3075 ] + commitopts + commitopts2,
3072 ] + commitopts + commitopts2,
3076 _('hg debugrawcommit [OPTION]... [FILE]...')),
3073 _('hg debugrawcommit [OPTION]... [FILE]...')),
3077 "recover": (recover, [], _('hg recover')),
3074 "recover": (recover, [], _('hg recover')),
3078 "^remove|rm":
3075 "^remove|rm":
3079 (remove,
3076 (remove,
3080 [('A', 'after', None, _('record remove without deleting')),
3077 [('A', 'after', None, _('record remove without deleting')),
3081 ('f', 'force', None, _('remove file even if modified')),
3078 ('f', 'force', None, _('remove file even if modified')),
3082 ] + walkopts,
3079 ] + walkopts,
3083 _('hg remove [OPTION]... FILE...')),
3080 _('hg remove [OPTION]... FILE...')),
3084 "rename|mv":
3081 "rename|mv":
3085 (rename,
3082 (rename,
3086 [('A', 'after', None, _('record a rename that has already occurred')),
3083 [('A', 'after', None, _('record a rename that has already occurred')),
3087 ('f', 'force', None,
3084 ('f', 'force', None,
3088 _('forcibly copy over an existing managed file')),
3085 _('forcibly copy over an existing managed file')),
3089 ] + walkopts + dryrunopts,
3086 ] + walkopts + dryrunopts,
3090 _('hg rename [OPTION]... SOURCE... DEST')),
3087 _('hg rename [OPTION]... SOURCE... DEST')),
3091 "revert":
3088 "revert":
3092 (revert,
3089 (revert,
3093 [('a', 'all', None, _('revert all changes when no arguments given')),
3090 [('a', 'all', None, _('revert all changes when no arguments given')),
3094 ('d', 'date', '', _('tipmost revision matching date')),
3091 ('d', 'date', '', _('tipmost revision matching date')),
3095 ('r', 'rev', '', _('revision to revert to')),
3092 ('r', 'rev', '', _('revision to revert to')),
3096 ('', 'no-backup', None, _('do not save backup copies of files')),
3093 ('', 'no-backup', None, _('do not save backup copies of files')),
3097 ] + walkopts + dryrunopts,
3094 ] + walkopts + dryrunopts,
3098 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3095 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3099 "rollback": (rollback, [], _('hg rollback')),
3096 "rollback": (rollback, [], _('hg rollback')),
3100 "root": (root, [], _('hg root')),
3097 "root": (root, [], _('hg root')),
3101 "showconfig|debugconfig":
3098 "showconfig|debugconfig":
3102 (showconfig,
3099 (showconfig,
3103 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3100 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3104 _('showconfig [-u] [NAME]...')),
3101 _('showconfig [-u] [NAME]...')),
3105 "^serve":
3102 "^serve":
3106 (serve,
3103 (serve,
3107 [('A', 'accesslog', '', _('name of access log file to write to')),
3104 [('A', 'accesslog', '', _('name of access log file to write to')),
3108 ('d', 'daemon', None, _('run server in background')),
3105 ('d', 'daemon', None, _('run server in background')),
3109 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3106 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3110 ('E', 'errorlog', '', _('name of error log file to write to')),
3107 ('E', 'errorlog', '', _('name of error log file to write to')),
3111 ('p', 'port', 0, _('port to use (default: 8000)')),
3108 ('p', 'port', 0, _('port to use (default: 8000)')),
3112 ('a', 'address', '', _('address to use')),
3109 ('a', 'address', '', _('address to use')),
3113 ('n', 'name', '',
3110 ('n', 'name', '',
3114 _('name to show in web pages (default: working dir)')),
3111 _('name to show in web pages (default: working dir)')),
3115 ('', 'webdir-conf', '', _('name of the webdir config file'
3112 ('', 'webdir-conf', '', _('name of the webdir config file'
3116 ' (serve more than one repo)')),
3113 ' (serve more than one repo)')),
3117 ('', 'pid-file', '', _('name of file to write process ID to')),
3114 ('', 'pid-file', '', _('name of file to write process ID to')),
3118 ('', 'stdio', None, _('for remote clients')),
3115 ('', 'stdio', None, _('for remote clients')),
3119 ('t', 'templates', '', _('web templates to use')),
3116 ('t', 'templates', '', _('web templates to use')),
3120 ('', 'style', '', _('template style to use')),
3117 ('', 'style', '', _('template style to use')),
3121 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3118 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3122 ('', 'certificate', '', _('SSL certificate file'))],
3119 ('', 'certificate', '', _('SSL certificate file'))],
3123 _('hg serve [OPTION]...')),
3120 _('hg serve [OPTION]...')),
3124 "^status|st":
3121 "^status|st":
3125 (status,
3122 (status,
3126 [('A', 'all', None, _('show status of all files')),
3123 [('A', 'all', None, _('show status of all files')),
3127 ('m', 'modified', None, _('show only modified files')),
3124 ('m', 'modified', None, _('show only modified files')),
3128 ('a', 'added', None, _('show only added files')),
3125 ('a', 'added', None, _('show only added files')),
3129 ('r', 'removed', None, _('show only removed files')),
3126 ('r', 'removed', None, _('show only removed files')),
3130 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3127 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3131 ('c', 'clean', None, _('show only files without changes')),
3128 ('c', 'clean', None, _('show only files without changes')),
3132 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3129 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3133 ('i', 'ignored', None, _('show only ignored files')),
3130 ('i', 'ignored', None, _('show only ignored files')),
3134 ('n', 'no-status', None, _('hide status prefix')),
3131 ('n', 'no-status', None, _('hide status prefix')),
3135 ('C', 'copies', None, _('show source of copied files')),
3132 ('C', 'copies', None, _('show source of copied files')),
3136 ('0', 'print0', None,
3133 ('0', 'print0', None,
3137 _('end filenames with NUL, for use with xargs')),
3134 _('end filenames with NUL, for use with xargs')),
3138 ('', 'rev', [], _('show difference from revision')),
3135 ('', 'rev', [], _('show difference from revision')),
3139 ] + walkopts,
3136 ] + walkopts,
3140 _('hg status [OPTION]... [FILE]...')),
3137 _('hg status [OPTION]... [FILE]...')),
3141 "tag":
3138 "tag":
3142 (tag,
3139 (tag,
3143 [('f', 'force', None, _('replace existing tag')),
3140 [('f', 'force', None, _('replace existing tag')),
3144 ('l', 'local', None, _('make the tag local')),
3141 ('l', 'local', None, _('make the tag local')),
3145 ('r', 'rev', '', _('revision to tag')),
3142 ('r', 'rev', '', _('revision to tag')),
3146 ('', 'remove', None, _('remove a tag')),
3143 ('', 'remove', None, _('remove a tag')),
3147 # -l/--local is already there, commitopts cannot be used
3144 # -l/--local is already there, commitopts cannot be used
3148 ('m', 'message', '', _('use <text> as commit message')),
3145 ('m', 'message', '', _('use <text> as commit message')),
3149 ] + commitopts2,
3146 ] + commitopts2,
3150 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3147 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3151 "tags": (tags, [], _('hg tags')),
3148 "tags": (tags, [], _('hg tags')),
3152 "tip":
3149 "tip":
3153 (tip,
3150 (tip,
3154 [('', 'style', '', _('display using template map file')),
3151 [('', 'style', '', _('display using template map file')),
3155 ('p', 'patch', None, _('show patch')),
3152 ('p', 'patch', None, _('show patch')),
3156 ('', 'template', '', _('display with template'))],
3153 ('', 'template', '', _('display with template'))],
3157 _('hg tip [-p]')),
3154 _('hg tip [-p]')),
3158 "unbundle":
3155 "unbundle":
3159 (unbundle,
3156 (unbundle,
3160 [('u', 'update', None,
3157 [('u', 'update', None,
3161 _('update to new tip if changesets were unbundled'))],
3158 _('update to new tip if changesets were unbundled'))],
3162 _('hg unbundle [-u] FILE...')),
3159 _('hg unbundle [-u] FILE...')),
3163 "^update|up|checkout|co":
3160 "^update|up|checkout|co":
3164 (update,
3161 (update,
3165 [('C', 'clean', None, _('overwrite locally modified files')),
3162 [('C', 'clean', None, _('overwrite locally modified files')),
3166 ('d', 'date', '', _('tipmost revision matching date')),
3163 ('d', 'date', '', _('tipmost revision matching date')),
3167 ('r', 'rev', '', _('revision'))],
3164 ('r', 'rev', '', _('revision'))],
3168 _('hg update [-C] [-d DATE] [[-r] REV]')),
3165 _('hg update [-C] [-d DATE] [[-r] REV]')),
3169 "verify": (verify, [], _('hg verify')),
3166 "verify": (verify, [], _('hg verify')),
3170 "version": (version_, [], _('hg version')),
3167 "version": (version_, [], _('hg version')),
3171 }
3168 }
3172
3169
3173 norepo = ("clone init version help debugancestor debugcomplete debugdata"
3170 norepo = ("clone init version help debugancestor debugcomplete debugdata"
3174 " debugindex debugindexdot debugdate debuginstall")
3171 " debugindex debugindexdot debugdate debuginstall")
3175 optionalrepo = ("identify paths serve showconfig")
3172 optionalrepo = ("identify paths serve showconfig")
General Comments 0
You need to be logged in to leave comments. Login now