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