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