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