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