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