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