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