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