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