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