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