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