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