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