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