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