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