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