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