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