##// END OF EJS Templates
Actually implement the -f switch for push
mpm@selenic.com -
r818:eef75215 default
parent child Browse files
Show More
@@ -1,1427 +1,1430
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 demandload(globals(), "os re sys signal shutil")
9 demandload(globals(), "os re sys signal shutil")
10 demandload(globals(), "fancyopts ui hg util")
10 demandload(globals(), "fancyopts ui hg util")
11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
12 demandload(globals(), "errno socket version struct atexit")
12 demandload(globals(), "errno socket version struct atexit")
13
13
14 class UnknownCommand(Exception):
14 class UnknownCommand(Exception):
15 """Exception raised if command is not in the command table."""
15 """Exception raised if command is not in the command table."""
16
16
17 class Abort(Exception):
17 class Abort(Exception):
18 """Raised if a command needs to print an error and exit."""
18 """Raised if a command needs to print an error and exit."""
19
19
20 def filterfiles(filters, files):
20 def filterfiles(filters, files):
21 l = [x for x in files if x in filters]
21 l = [x for x in files if x in filters]
22
22
23 for t in filters:
23 for t in filters:
24 if t and t[-1] != "/":
24 if t and t[-1] != "/":
25 t += "/"
25 t += "/"
26 l += [x for x in files if x.startswith(t)]
26 l += [x for x in files if x.startswith(t)]
27 return l
27 return l
28
28
29 def relfilter(repo, files):
29 def relfilter(repo, files):
30 cwd = repo.getcwd()
30 cwd = repo.getcwd()
31 if cwd:
31 if cwd:
32 return filterfiles([util.pconvert(cwd)], files)
32 return filterfiles([util.pconvert(cwd)], files)
33 return files
33 return files
34
34
35 def relpath(repo, args):
35 def relpath(repo, args):
36 cwd = repo.getcwd()
36 cwd = repo.getcwd()
37 if cwd:
37 if cwd:
38 return [util.pconvert(os.path.normpath(os.path.join(cwd, x)))
38 return [util.pconvert(os.path.normpath(os.path.join(cwd, x)))
39 for x in args]
39 for x in args]
40 return args
40 return args
41
41
42 def matchpats(cwd, pats = [], opts = {}, head = ''):
42 def matchpats(cwd, pats = [], opts = {}, head = ''):
43 return util.matcher(cwd, pats, opts.get('include'),
43 return util.matcher(cwd, pats, opts.get('include'),
44 opts.get('exclude'), head)
44 opts.get('exclude'), head)
45
45
46 def walk(repo, pats, opts, head = ''):
46 def walk(repo, pats, opts, head = ''):
47 cwd = repo.getcwd()
47 cwd = repo.getcwd()
48 c = 0
48 c = 0
49 if cwd: c = len(cwd) + 1
49 if cwd: c = len(cwd) + 1
50 files, matchfn = matchpats(cwd, pats, opts, head)
50 files, matchfn = matchpats(cwd, pats, opts, head)
51 for src, fn in repo.walk(files = files, match = matchfn):
51 for src, fn in repo.walk(files = files, match = matchfn):
52 yield src, fn, fn[c:]
52 yield src, fn, fn[c:]
53
53
54 revrangesep = ':'
54 revrangesep = ':'
55
55
56 def revrange(ui, repo, revs, revlog=None):
56 def revrange(ui, repo, revs, revlog=None):
57 if revlog is None:
57 if revlog is None:
58 revlog = repo.changelog
58 revlog = repo.changelog
59 revcount = revlog.count()
59 revcount = revlog.count()
60 def fix(val, defval):
60 def fix(val, defval):
61 if not val:
61 if not val:
62 return defval
62 return defval
63 try:
63 try:
64 num = int(val)
64 num = int(val)
65 if str(num) != val:
65 if str(num) != val:
66 raise ValueError
66 raise ValueError
67 if num < 0:
67 if num < 0:
68 num += revcount
68 num += revcount
69 if not (0 <= num < revcount):
69 if not (0 <= num < revcount):
70 raise ValueError
70 raise ValueError
71 except ValueError:
71 except ValueError:
72 try:
72 try:
73 num = repo.changelog.rev(repo.lookup(val))
73 num = repo.changelog.rev(repo.lookup(val))
74 except KeyError:
74 except KeyError:
75 try:
75 try:
76 num = revlog.rev(revlog.lookup(val))
76 num = revlog.rev(revlog.lookup(val))
77 except KeyError:
77 except KeyError:
78 raise Abort('invalid revision identifier %s', val)
78 raise Abort('invalid revision identifier %s', val)
79 return num
79 return num
80 for spec in revs:
80 for spec in revs:
81 if spec.find(revrangesep) >= 0:
81 if spec.find(revrangesep) >= 0:
82 start, end = spec.split(revrangesep, 1)
82 start, end = spec.split(revrangesep, 1)
83 start = fix(start, 0)
83 start = fix(start, 0)
84 end = fix(end, revcount - 1)
84 end = fix(end, revcount - 1)
85 if end > start:
85 if end > start:
86 end += 1
86 end += 1
87 step = 1
87 step = 1
88 else:
88 else:
89 end -= 1
89 end -= 1
90 step = -1
90 step = -1
91 for rev in xrange(start, end, step):
91 for rev in xrange(start, end, step):
92 yield str(rev)
92 yield str(rev)
93 else:
93 else:
94 yield spec
94 yield spec
95
95
96 def make_filename(repo, r, pat, node=None,
96 def make_filename(repo, r, pat, node=None,
97 total=None, seqno=None, revwidth=None):
97 total=None, seqno=None, revwidth=None):
98 node_expander = {
98 node_expander = {
99 'H': lambda: hg.hex(node),
99 'H': lambda: hg.hex(node),
100 'R': lambda: str(r.rev(node)),
100 'R': lambda: str(r.rev(node)),
101 'h': lambda: hg.short(node),
101 'h': lambda: hg.short(node),
102 }
102 }
103 expander = {
103 expander = {
104 '%': lambda: '%',
104 '%': lambda: '%',
105 'b': lambda: os.path.basename(repo.root),
105 'b': lambda: os.path.basename(repo.root),
106 }
106 }
107
107
108 try:
108 try:
109 if node:
109 if node:
110 expander.update(node_expander)
110 expander.update(node_expander)
111 if node and revwidth is not None:
111 if node and revwidth is not None:
112 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
112 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
113 if total is not None:
113 if total is not None:
114 expander['N'] = lambda: str(total)
114 expander['N'] = lambda: str(total)
115 if seqno is not None:
115 if seqno is not None:
116 expander['n'] = lambda: str(seqno)
116 expander['n'] = lambda: str(seqno)
117 if total is not None and seqno is not None:
117 if total is not None and seqno is not None:
118 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
118 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
119
119
120 newname = []
120 newname = []
121 patlen = len(pat)
121 patlen = len(pat)
122 i = 0
122 i = 0
123 while i < patlen:
123 while i < patlen:
124 c = pat[i]
124 c = pat[i]
125 if c == '%':
125 if c == '%':
126 i += 1
126 i += 1
127 c = pat[i]
127 c = pat[i]
128 c = expander[c]()
128 c = expander[c]()
129 newname.append(c)
129 newname.append(c)
130 i += 1
130 i += 1
131 return ''.join(newname)
131 return ''.join(newname)
132 except KeyError, inst:
132 except KeyError, inst:
133 raise Abort("invalid format spec '%%%s' in output file name",
133 raise Abort("invalid format spec '%%%s' in output file name",
134 inst.args[0])
134 inst.args[0])
135
135
136 def make_file(repo, r, pat, node=None,
136 def make_file(repo, r, pat, node=None,
137 total=None, seqno=None, revwidth=None, mode='wb'):
137 total=None, seqno=None, revwidth=None, mode='wb'):
138 if not pat or pat == '-':
138 if not pat or pat == '-':
139 if 'w' in mode: return sys.stdout
139 if 'w' in mode: return sys.stdout
140 else: return sys.stdin
140 else: return sys.stdin
141 if hasattr(pat, 'write') and 'w' in mode:
141 if hasattr(pat, 'write') and 'w' in mode:
142 return pat
142 return pat
143 if hasattr(pat, 'read') and 'r' in mode:
143 if hasattr(pat, 'read') and 'r' in mode:
144 return pat
144 return pat
145 return open(make_filename(repo, r, pat, node, total, seqno, revwidth),
145 return open(make_filename(repo, r, pat, node, total, seqno, revwidth),
146 mode)
146 mode)
147
147
148 def dodiff(fp, ui, repo, files=None, node1=None, node2=None):
148 def dodiff(fp, ui, repo, files=None, node1=None, node2=None):
149 def date(c):
149 def date(c):
150 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
150 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
151
151
152 (c, a, d, u) = repo.changes(node1, node2, files)
152 (c, a, d, u) = repo.changes(node1, node2, files)
153 if files:
153 if files:
154 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
154 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
155
155
156 if not c and not a and not d:
156 if not c and not a and not d:
157 return
157 return
158
158
159 if node2:
159 if node2:
160 change = repo.changelog.read(node2)
160 change = repo.changelog.read(node2)
161 mmap2 = repo.manifest.read(change[0])
161 mmap2 = repo.manifest.read(change[0])
162 date2 = date(change)
162 date2 = date(change)
163 def read(f):
163 def read(f):
164 return repo.file(f).read(mmap2[f])
164 return repo.file(f).read(mmap2[f])
165 else:
165 else:
166 date2 = time.asctime()
166 date2 = time.asctime()
167 if not node1:
167 if not node1:
168 node1 = repo.dirstate.parents()[0]
168 node1 = repo.dirstate.parents()[0]
169 def read(f):
169 def read(f):
170 return repo.wfile(f).read()
170 return repo.wfile(f).read()
171
171
172 if ui.quiet:
172 if ui.quiet:
173 r = None
173 r = None
174 else:
174 else:
175 hexfunc = ui.verbose and hg.hex or hg.short
175 hexfunc = ui.verbose and hg.hex or hg.short
176 r = [hexfunc(node) for node in [node1, node2] if node]
176 r = [hexfunc(node) for node in [node1, node2] if node]
177
177
178 change = repo.changelog.read(node1)
178 change = repo.changelog.read(node1)
179 mmap = repo.manifest.read(change[0])
179 mmap = repo.manifest.read(change[0])
180 date1 = date(change)
180 date1 = date(change)
181
181
182 for f in c:
182 for f in c:
183 to = None
183 to = None
184 if f in mmap:
184 if f in mmap:
185 to = repo.file(f).read(mmap[f])
185 to = repo.file(f).read(mmap[f])
186 tn = read(f)
186 tn = read(f)
187 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
187 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
188 for f in a:
188 for f in a:
189 to = None
189 to = None
190 tn = read(f)
190 tn = read(f)
191 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
191 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
192 for f in d:
192 for f in d:
193 to = repo.file(f).read(mmap[f])
193 to = repo.file(f).read(mmap[f])
194 tn = None
194 tn = None
195 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
195 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
196
196
197 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
197 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
198 """show a single changeset or file revision"""
198 """show a single changeset or file revision"""
199 changelog = repo.changelog
199 changelog = repo.changelog
200 if filelog:
200 if filelog:
201 log = filelog
201 log = filelog
202 filerev = rev
202 filerev = rev
203 node = filenode = filelog.node(filerev)
203 node = filenode = filelog.node(filerev)
204 changerev = filelog.linkrev(filenode)
204 changerev = filelog.linkrev(filenode)
205 changenode = changenode or changelog.node(changerev)
205 changenode = changenode or changelog.node(changerev)
206 else:
206 else:
207 log = changelog
207 log = changelog
208 changerev = rev
208 changerev = rev
209 if changenode is None:
209 if changenode is None:
210 changenode = changelog.node(changerev)
210 changenode = changelog.node(changerev)
211 elif not changerev:
211 elif not changerev:
212 rev = changerev = changelog.rev(changenode)
212 rev = changerev = changelog.rev(changenode)
213 node = changenode
213 node = changenode
214
214
215 if ui.quiet:
215 if ui.quiet:
216 ui.write("%d:%s\n" % (rev, hg.hex(node)))
216 ui.write("%d:%s\n" % (rev, hg.hex(node)))
217 return
217 return
218
218
219 changes = changelog.read(changenode)
219 changes = changelog.read(changenode)
220
220
221 parents = [(log.rev(p), ui.verbose and hg.hex(p) or hg.short(p))
221 parents = [(log.rev(p), ui.verbose and hg.hex(p) or hg.short(p))
222 for p in log.parents(node)
222 for p in log.parents(node)
223 if ui.debugflag or p != hg.nullid]
223 if ui.debugflag or p != hg.nullid]
224 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
224 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
225 parents = []
225 parents = []
226
226
227 if ui.verbose:
227 if ui.verbose:
228 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
228 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
229 else:
229 else:
230 ui.write("changeset: %d:%s\n" % (changerev, hg.short(changenode)))
230 ui.write("changeset: %d:%s\n" % (changerev, hg.short(changenode)))
231
231
232 for tag in repo.nodetags(changenode):
232 for tag in repo.nodetags(changenode):
233 ui.status("tag: %s\n" % tag)
233 ui.status("tag: %s\n" % tag)
234 for parent in parents:
234 for parent in parents:
235 ui.write("parent: %d:%s\n" % parent)
235 ui.write("parent: %d:%s\n" % parent)
236 if filelog:
236 if filelog:
237 ui.debug("file rev: %d:%s\n" % (filerev, hg.hex(filenode)))
237 ui.debug("file rev: %d:%s\n" % (filerev, hg.hex(filenode)))
238
238
239 ui.debug("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
239 ui.debug("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
240 hg.hex(changes[0])))
240 hg.hex(changes[0])))
241 ui.status("user: %s\n" % changes[1])
241 ui.status("user: %s\n" % changes[1])
242 ui.status("date: %s\n" % time.asctime(
242 ui.status("date: %s\n" % time.asctime(
243 time.localtime(float(changes[2].split(' ')[0]))))
243 time.localtime(float(changes[2].split(' ')[0]))))
244
244
245 if ui.debugflag:
245 if ui.debugflag:
246 files = repo.changes(changelog.parents(changenode)[0], changenode)
246 files = repo.changes(changelog.parents(changenode)[0], changenode)
247 for key, value in zip(["files:", "files+:", "files-:"], files):
247 for key, value in zip(["files:", "files+:", "files-:"], files):
248 if value:
248 if value:
249 ui.note("%-12s %s\n" % (key, " ".join(value)))
249 ui.note("%-12s %s\n" % (key, " ".join(value)))
250 else:
250 else:
251 ui.note("files: %s\n" % " ".join(changes[3]))
251 ui.note("files: %s\n" % " ".join(changes[3]))
252
252
253 description = changes[4].strip()
253 description = changes[4].strip()
254 if description:
254 if description:
255 if ui.verbose:
255 if ui.verbose:
256 ui.status("description:\n")
256 ui.status("description:\n")
257 ui.status(description)
257 ui.status(description)
258 ui.status("\n\n")
258 ui.status("\n\n")
259 else:
259 else:
260 ui.status("summary: %s\n" % description.splitlines()[0])
260 ui.status("summary: %s\n" % description.splitlines()[0])
261 ui.status("\n")
261 ui.status("\n")
262
262
263 def show_version(ui):
263 def show_version(ui):
264 """output version and copyright information"""
264 """output version and copyright information"""
265 ui.write("Mercurial version %s\n" % version.get_version())
265 ui.write("Mercurial version %s\n" % version.get_version())
266 ui.status(
266 ui.status(
267 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
267 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
268 "This is free software; see the source for copying conditions. "
268 "This is free software; see the source for copying conditions. "
269 "There is NO\nwarranty; "
269 "There is NO\nwarranty; "
270 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
270 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
271 )
271 )
272
272
273 def help_(ui, cmd=None):
273 def help_(ui, cmd=None):
274 """show help for a given command or all commands"""
274 """show help for a given command or all commands"""
275 if cmd:
275 if cmd:
276 try:
276 try:
277 i = find(cmd)
277 i = find(cmd)
278 ui.write("%s\n\n" % i[2])
278 ui.write("%s\n\n" % i[2])
279
279
280 if i[1]:
280 if i[1]:
281 for s, l, d, c in i[1]:
281 for s, l, d, c in i[1]:
282 opt = ' '
282 opt = ' '
283 if s:
283 if s:
284 opt = opt + '-' + s + ' '
284 opt = opt + '-' + s + ' '
285 if l:
285 if l:
286 opt = opt + '--' + l + ' '
286 opt = opt + '--' + l + ' '
287 if d:
287 if d:
288 opt = opt + '(' + str(d) + ')'
288 opt = opt + '(' + str(d) + ')'
289 ui.write(opt, "\n")
289 ui.write(opt, "\n")
290 if c:
290 if c:
291 ui.write(' %s\n' % c)
291 ui.write(' %s\n' % c)
292 ui.write("\n")
292 ui.write("\n")
293
293
294 ui.write(i[0].__doc__, "\n")
294 ui.write(i[0].__doc__, "\n")
295 except UnknownCommand:
295 except UnknownCommand:
296 ui.warn("hg: unknown command %s\n" % cmd)
296 ui.warn("hg: unknown command %s\n" % cmd)
297 sys.exit(0)
297 sys.exit(0)
298 else:
298 else:
299 if ui.verbose:
299 if ui.verbose:
300 show_version(ui)
300 show_version(ui)
301 ui.write('\n')
301 ui.write('\n')
302 if ui.verbose:
302 if ui.verbose:
303 ui.write('hg commands:\n\n')
303 ui.write('hg commands:\n\n')
304 else:
304 else:
305 ui.write('basic hg commands (use "hg help -v" for more):\n\n')
305 ui.write('basic hg commands (use "hg help -v" for more):\n\n')
306
306
307 h = {}
307 h = {}
308 for c, e in table.items():
308 for c, e in table.items():
309 f = c.split("|")[0]
309 f = c.split("|")[0]
310 if not ui.verbose and not f.startswith("^"):
310 if not ui.verbose and not f.startswith("^"):
311 continue
311 continue
312 if not ui.debugflag and f.startswith("debug"):
312 if not ui.debugflag and f.startswith("debug"):
313 continue
313 continue
314 f = f.lstrip("^")
314 f = f.lstrip("^")
315 d = ""
315 d = ""
316 if e[0].__doc__:
316 if e[0].__doc__:
317 d = e[0].__doc__.splitlines(0)[0].rstrip()
317 d = e[0].__doc__.splitlines(0)[0].rstrip()
318 h[f] = d
318 h[f] = d
319
319
320 fns = h.keys()
320 fns = h.keys()
321 fns.sort()
321 fns.sort()
322 m = max(map(len, fns))
322 m = max(map(len, fns))
323 for f in fns:
323 for f in fns:
324 ui.write(' %-*s %s\n' % (m, f, h[f]))
324 ui.write(' %-*s %s\n' % (m, f, h[f]))
325
325
326 # Commands start here, listed alphabetically
326 # Commands start here, listed alphabetically
327
327
328 def add(ui, repo, *pats, **opts):
328 def add(ui, repo, *pats, **opts):
329 '''add the specified files on the next commit'''
329 '''add the specified files on the next commit'''
330 names = []
330 names = []
331 q = dict(zip(pats, pats))
331 q = dict(zip(pats, pats))
332 for src, abs, rel in walk(repo, pats, opts):
332 for src, abs, rel in walk(repo, pats, opts):
333 if rel in q or abs in q:
333 if rel in q or abs in q:
334 names.append(abs)
334 names.append(abs)
335 elif repo.dirstate.state(abs) == '?':
335 elif repo.dirstate.state(abs) == '?':
336 ui.status('adding %s\n' % rel)
336 ui.status('adding %s\n' % rel)
337 names.append(abs)
337 names.append(abs)
338 repo.add(names)
338 repo.add(names)
339
339
340 def addremove(ui, repo, *pats, **opts):
340 def addremove(ui, repo, *pats, **opts):
341 """add all new files, delete all missing files"""
341 """add all new files, delete all missing files"""
342 q = dict(zip(pats, pats))
342 q = dict(zip(pats, pats))
343 add, remove = [], []
343 add, remove = [], []
344 for src, abs, rel in walk(repo, pats, opts):
344 for src, abs, rel in walk(repo, pats, opts):
345 if src == 'f':
345 if src == 'f':
346 if repo.dirstate.state(abs) == '?':
346 if repo.dirstate.state(abs) == '?':
347 add.append(abs)
347 add.append(abs)
348 if rel not in q: ui.status('adding ', rel, '\n')
348 if rel not in q: ui.status('adding ', rel, '\n')
349 elif repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
349 elif repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
350 remove.append(abs)
350 remove.append(abs)
351 if rel not in q: ui.status('removing ', rel, '\n')
351 if rel not in q: ui.status('removing ', rel, '\n')
352 repo.add(add)
352 repo.add(add)
353 repo.remove(remove)
353 repo.remove(remove)
354
354
355 def annotate(ui, repo, *pats, **opts):
355 def annotate(ui, repo, *pats, **opts):
356 """show changeset information per file line"""
356 """show changeset information per file line"""
357 def getnode(rev):
357 def getnode(rev):
358 return hg.short(repo.changelog.node(rev))
358 return hg.short(repo.changelog.node(rev))
359
359
360 def getname(rev):
360 def getname(rev):
361 try:
361 try:
362 return bcache[rev]
362 return bcache[rev]
363 except KeyError:
363 except KeyError:
364 cl = repo.changelog.read(repo.changelog.node(rev))
364 cl = repo.changelog.read(repo.changelog.node(rev))
365 name = cl[1]
365 name = cl[1]
366 f = name.find('@')
366 f = name.find('@')
367 if f >= 0:
367 if f >= 0:
368 name = name[:f]
368 name = name[:f]
369 f = name.find('<')
369 f = name.find('<')
370 if f >= 0:
370 if f >= 0:
371 name = name[f+1:]
371 name = name[f+1:]
372 bcache[rev] = name
372 bcache[rev] = name
373 return name
373 return name
374
374
375 if not pats:
375 if not pats:
376 raise Abort('at least one file name or pattern required')
376 raise Abort('at least one file name or pattern required')
377
377
378 bcache = {}
378 bcache = {}
379 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
379 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
380 if not opts['user'] and not opts['changeset']:
380 if not opts['user'] and not opts['changeset']:
381 opts['number'] = 1
381 opts['number'] = 1
382
382
383 if opts['rev']:
383 if opts['rev']:
384 node = repo.changelog.lookup(opts['rev'])
384 node = repo.changelog.lookup(opts['rev'])
385 else:
385 else:
386 node = repo.dirstate.parents()[0]
386 node = repo.dirstate.parents()[0]
387 change = repo.changelog.read(node)
387 change = repo.changelog.read(node)
388 mmap = repo.manifest.read(change[0])
388 mmap = repo.manifest.read(change[0])
389 for src, abs, rel in walk(repo, pats, opts):
389 for src, abs, rel in walk(repo, pats, opts):
390 if abs not in mmap:
390 if abs not in mmap:
391 ui.warn("warning: %s is not in the repository!\n" % rel)
391 ui.warn("warning: %s is not in the repository!\n" % rel)
392 continue
392 continue
393
393
394 lines = repo.file(abs).annotate(mmap[abs])
394 lines = repo.file(abs).annotate(mmap[abs])
395 pieces = []
395 pieces = []
396
396
397 for o, f in opmap:
397 for o, f in opmap:
398 if opts[o]:
398 if opts[o]:
399 l = [f(n) for n, dummy in lines]
399 l = [f(n) for n, dummy in lines]
400 if l:
400 if l:
401 m = max(map(len, l))
401 m = max(map(len, l))
402 pieces.append(["%*s" % (m, x) for x in l])
402 pieces.append(["%*s" % (m, x) for x in l])
403
403
404 if pieces:
404 if pieces:
405 for p, l in zip(zip(*pieces), lines):
405 for p, l in zip(zip(*pieces), lines):
406 ui.write("%s: %s" % (" ".join(p), l[1]))
406 ui.write("%s: %s" % (" ".join(p), l[1]))
407
407
408 def cat(ui, repo, file1, rev=None, **opts):
408 def cat(ui, repo, file1, rev=None, **opts):
409 """output the latest or given revision of a file"""
409 """output the latest or given revision of a file"""
410 r = repo.file(relpath(repo, [file1])[0])
410 r = repo.file(relpath(repo, [file1])[0])
411 if rev:
411 if rev:
412 n = r.lookup(rev)
412 n = r.lookup(rev)
413 else:
413 else:
414 n = r.tip()
414 n = r.tip()
415 fp = make_file(repo, r, opts['output'], node=n)
415 fp = make_file(repo, r, opts['output'], node=n)
416 fp.write(r.read(n))
416 fp.write(r.read(n))
417
417
418 def clone(ui, source, dest=None, **opts):
418 def clone(ui, source, dest=None, **opts):
419 """make a copy of an existing repository"""
419 """make a copy of an existing repository"""
420 if dest is None:
420 if dest is None:
421 dest = os.path.basename(os.path.normpath(source))
421 dest = os.path.basename(os.path.normpath(source))
422
422
423 if os.path.exists(dest):
423 if os.path.exists(dest):
424 ui.warn("abort: destination '%s' already exists\n" % dest)
424 ui.warn("abort: destination '%s' already exists\n" % dest)
425 return 1
425 return 1
426
426
427 class Dircleanup:
427 class Dircleanup:
428 def __init__(self, dir_):
428 def __init__(self, dir_):
429 self.rmtree = shutil.rmtree
429 self.rmtree = shutil.rmtree
430 self.dir_ = dir_
430 self.dir_ = dir_
431 os.mkdir(dir_)
431 os.mkdir(dir_)
432 def close(self):
432 def close(self):
433 self.dir_ = None
433 self.dir_ = None
434 def __del__(self):
434 def __del__(self):
435 if self.dir_:
435 if self.dir_:
436 self.rmtree(self.dir_, True)
436 self.rmtree(self.dir_, True)
437
437
438 d = Dircleanup(dest)
438 d = Dircleanup(dest)
439 abspath = source
439 abspath = source
440 source = ui.expandpath(source)
440 source = ui.expandpath(source)
441 other = hg.repository(ui, source)
441 other = hg.repository(ui, source)
442
442
443 if other.dev() != -1:
443 if other.dev() != -1:
444 abspath = os.path.abspath(source)
444 abspath = os.path.abspath(source)
445 copyfile = (os.stat(dest).st_dev == other.dev()
445 copyfile = (os.stat(dest).st_dev == other.dev()
446 and getattr(os, 'link', None) or shutil.copy2)
446 and getattr(os, 'link', None) or shutil.copy2)
447 if copyfile is not shutil.copy2:
447 if copyfile is not shutil.copy2:
448 ui.note("cloning by hardlink\n")
448 ui.note("cloning by hardlink\n")
449 util.copytree(os.path.join(source, ".hg"), os.path.join(dest, ".hg"),
449 util.copytree(os.path.join(source, ".hg"), os.path.join(dest, ".hg"),
450 copyfile)
450 copyfile)
451 try:
451 try:
452 os.unlink(os.path.join(dest, ".hg", "dirstate"))
452 os.unlink(os.path.join(dest, ".hg", "dirstate"))
453 except OSError:
453 except OSError:
454 pass
454 pass
455
455
456 repo = hg.repository(ui, dest)
456 repo = hg.repository(ui, dest)
457
457
458 else:
458 else:
459 repo = hg.repository(ui, dest, create=1)
459 repo = hg.repository(ui, dest, create=1)
460 repo.pull(other)
460 repo.pull(other)
461
461
462 f = repo.opener("hgrc", "w")
462 f = repo.opener("hgrc", "w")
463 f.write("[paths]\n")
463 f.write("[paths]\n")
464 f.write("default = %s\n" % abspath)
464 f.write("default = %s\n" % abspath)
465
465
466 if not opts['noupdate']:
466 if not opts['noupdate']:
467 update(ui, repo)
467 update(ui, repo)
468
468
469 d.close()
469 d.close()
470
470
471 def commit(ui, repo, *pats, **opts):
471 def commit(ui, repo, *pats, **opts):
472 """commit the specified files or all outstanding changes"""
472 """commit the specified files or all outstanding changes"""
473 if opts['text']:
473 if opts['text']:
474 ui.warn("Warning: -t and --text is deprecated,"
474 ui.warn("Warning: -t and --text is deprecated,"
475 " please use -m or --message instead.\n")
475 " please use -m or --message instead.\n")
476 message = opts['message'] or opts['text']
476 message = opts['message'] or opts['text']
477 logfile = opts['logfile']
477 logfile = opts['logfile']
478 if not message and logfile:
478 if not message and logfile:
479 try:
479 try:
480 message = open(logfile).read()
480 message = open(logfile).read()
481 except IOError, why:
481 except IOError, why:
482 ui.warn("Can't read commit message %s: %s\n" % (logfile, why))
482 ui.warn("Can't read commit message %s: %s\n" % (logfile, why))
483
483
484 if opts['addremove']:
484 if opts['addremove']:
485 addremove(ui, repo, *pats, **opts)
485 addremove(ui, repo, *pats, **opts)
486 cwd = repo.getcwd()
486 cwd = repo.getcwd()
487 if not pats and cwd:
487 if not pats and cwd:
488 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
488 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
489 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
489 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
490 fns, match = matchpats((pats and repo.getcwd()) or '', pats, opts)
490 fns, match = matchpats((pats and repo.getcwd()) or '', pats, opts)
491 if pats:
491 if pats:
492 c, a, d, u = repo.changes(files = fns, match = match)
492 c, a, d, u = repo.changes(files = fns, match = match)
493 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
493 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
494 else:
494 else:
495 files = []
495 files = []
496 repo.commit(files, message, opts['user'], opts['date'], match)
496 repo.commit(files, message, opts['user'], opts['date'], match)
497
497
498 def copy(ui, repo, source, dest):
498 def copy(ui, repo, source, dest):
499 """mark a file as copied or renamed for the next commit"""
499 """mark a file as copied or renamed for the next commit"""
500 return repo.copy(*relpath(repo, (source, dest)))
500 return repo.copy(*relpath(repo, (source, dest)))
501
501
502 def debugcheckstate(ui, repo):
502 def debugcheckstate(ui, repo):
503 """validate the correctness of the current dirstate"""
503 """validate the correctness of the current dirstate"""
504 parent1, parent2 = repo.dirstate.parents()
504 parent1, parent2 = repo.dirstate.parents()
505 repo.dirstate.read()
505 repo.dirstate.read()
506 dc = repo.dirstate.map
506 dc = repo.dirstate.map
507 keys = dc.keys()
507 keys = dc.keys()
508 keys.sort()
508 keys.sort()
509 m1n = repo.changelog.read(parent1)[0]
509 m1n = repo.changelog.read(parent1)[0]
510 m2n = repo.changelog.read(parent2)[0]
510 m2n = repo.changelog.read(parent2)[0]
511 m1 = repo.manifest.read(m1n)
511 m1 = repo.manifest.read(m1n)
512 m2 = repo.manifest.read(m2n)
512 m2 = repo.manifest.read(m2n)
513 errors = 0
513 errors = 0
514 for f in dc:
514 for f in dc:
515 state = repo.dirstate.state(f)
515 state = repo.dirstate.state(f)
516 if state in "nr" and f not in m1:
516 if state in "nr" and f not in m1:
517 ui.warn("%s in state %s, but not in manifest1\n" % (f, state))
517 ui.warn("%s in state %s, but not in manifest1\n" % (f, state))
518 errors += 1
518 errors += 1
519 if state in "a" and f in m1:
519 if state in "a" and f in m1:
520 ui.warn("%s in state %s, but also in manifest1\n" % (f, state))
520 ui.warn("%s in state %s, but also in manifest1\n" % (f, state))
521 errors += 1
521 errors += 1
522 if state in "m" and f not in m1 and f not in m2:
522 if state in "m" and f not in m1 and f not in m2:
523 ui.warn("%s in state %s, but not in either manifest\n" %
523 ui.warn("%s in state %s, but not in either manifest\n" %
524 (f, state))
524 (f, state))
525 errors += 1
525 errors += 1
526 for f in m1:
526 for f in m1:
527 state = repo.dirstate.state(f)
527 state = repo.dirstate.state(f)
528 if state not in "nrm":
528 if state not in "nrm":
529 ui.warn("%s in manifest1, but listed as state %s" % (f, state))
529 ui.warn("%s in manifest1, but listed as state %s" % (f, state))
530 errors += 1
530 errors += 1
531 if errors:
531 if errors:
532 raise Abort(".hg/dirstate inconsistent with current parent's manifest")
532 raise Abort(".hg/dirstate inconsistent with current parent's manifest")
533
533
534 def debugstate(ui, repo):
534 def debugstate(ui, repo):
535 """show the contents of the current dirstate"""
535 """show the contents of the current dirstate"""
536 repo.dirstate.read()
536 repo.dirstate.read()
537 dc = repo.dirstate.map
537 dc = repo.dirstate.map
538 keys = dc.keys()
538 keys = dc.keys()
539 keys.sort()
539 keys.sort()
540 for file_ in keys:
540 for file_ in keys:
541 ui.write("%c %3o %10d %s %s\n"
541 ui.write("%c %3o %10d %s %s\n"
542 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
542 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
543 time.strftime("%x %X",
543 time.strftime("%x %X",
544 time.localtime(dc[file_][3])), file_))
544 time.localtime(dc[file_][3])), file_))
545
545
546 def debugindex(ui, file_):
546 def debugindex(ui, file_):
547 """dump the contents of an index file"""
547 """dump the contents of an index file"""
548 r = hg.revlog(hg.opener(""), file_, "")
548 r = hg.revlog(hg.opener(""), file_, "")
549 ui.write(" rev offset length base linkrev" +
549 ui.write(" rev offset length base linkrev" +
550 " p1 p2 nodeid\n")
550 " p1 p2 nodeid\n")
551 for i in range(r.count()):
551 for i in range(r.count()):
552 e = r.index[i]
552 e = r.index[i]
553 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
553 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
554 i, e[0], e[1], e[2], e[3],
554 i, e[0], e[1], e[2], e[3],
555 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
555 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
556
556
557 def debugindexdot(ui, file_):
557 def debugindexdot(ui, file_):
558 """dump an index DAG as a .dot file"""
558 """dump an index DAG as a .dot file"""
559 r = hg.revlog(hg.opener(""), file_, "")
559 r = hg.revlog(hg.opener(""), file_, "")
560 ui.write("digraph G {\n")
560 ui.write("digraph G {\n")
561 for i in range(r.count()):
561 for i in range(r.count()):
562 e = r.index[i]
562 e = r.index[i]
563 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
563 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
564 if e[5] != hg.nullid:
564 if e[5] != hg.nullid:
565 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
565 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
566 ui.write("}\n")
566 ui.write("}\n")
567
567
568 def diff(ui, repo, *pats, **opts):
568 def diff(ui, repo, *pats, **opts):
569 """diff working directory (or selected files)"""
569 """diff working directory (or selected files)"""
570 revs = []
570 revs = []
571 if opts['rev']:
571 if opts['rev']:
572 revs = map(lambda x: repo.lookup(x), opts['rev'])
572 revs = map(lambda x: repo.lookup(x), opts['rev'])
573
573
574 if len(revs) > 2:
574 if len(revs) > 2:
575 raise Abort("too many revisions to diff")
575 raise Abort("too many revisions to diff")
576
576
577 files = []
577 files = []
578 for src, abs, rel in walk(repo, pats, opts):
578 for src, abs, rel in walk(repo, pats, opts):
579 files.append(abs)
579 files.append(abs)
580 dodiff(sys.stdout, ui, repo, files, *revs)
580 dodiff(sys.stdout, ui, repo, files, *revs)
581
581
582 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
582 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
583 node = repo.lookup(changeset)
583 node = repo.lookup(changeset)
584 prev, other = repo.changelog.parents(node)
584 prev, other = repo.changelog.parents(node)
585 change = repo.changelog.read(node)
585 change = repo.changelog.read(node)
586
586
587 fp = make_file(repo, repo.changelog, opts['output'],
587 fp = make_file(repo, repo.changelog, opts['output'],
588 node=node, total=total, seqno=seqno,
588 node=node, total=total, seqno=seqno,
589 revwidth=revwidth)
589 revwidth=revwidth)
590 if fp != sys.stdout:
590 if fp != sys.stdout:
591 ui.note("%s\n" % fp.name)
591 ui.note("%s\n" % fp.name)
592
592
593 fp.write("# HG changeset patch\n")
593 fp.write("# HG changeset patch\n")
594 fp.write("# User %s\n" % change[1])
594 fp.write("# User %s\n" % change[1])
595 fp.write("# Node ID %s\n" % hg.hex(node))
595 fp.write("# Node ID %s\n" % hg.hex(node))
596 fp.write("# Parent %s\n" % hg.hex(prev))
596 fp.write("# Parent %s\n" % hg.hex(prev))
597 if other != hg.nullid:
597 if other != hg.nullid:
598 fp.write("# Parent %s\n" % hg.hex(other))
598 fp.write("# Parent %s\n" % hg.hex(other))
599 fp.write(change[4].rstrip())
599 fp.write(change[4].rstrip())
600 fp.write("\n\n")
600 fp.write("\n\n")
601
601
602 dodiff(fp, ui, repo, None, prev, node)
602 dodiff(fp, ui, repo, None, prev, node)
603 if fp != sys.stdout: fp.close()
603 if fp != sys.stdout: fp.close()
604
604
605 def export(ui, repo, *changesets, **opts):
605 def export(ui, repo, *changesets, **opts):
606 """dump the header and diffs for one or more changesets"""
606 """dump the header and diffs for one or more changesets"""
607 if not changesets:
607 if not changesets:
608 raise Abort("export requires at least one changeset")
608 raise Abort("export requires at least one changeset")
609 seqno = 0
609 seqno = 0
610 revs = list(revrange(ui, repo, changesets))
610 revs = list(revrange(ui, repo, changesets))
611 total = len(revs)
611 total = len(revs)
612 revwidth = max(len(revs[0]), len(revs[-1]))
612 revwidth = max(len(revs[0]), len(revs[-1]))
613 ui.note(len(revs) > 1 and "Exporting patches:\n" or "Exporting patch:\n")
613 ui.note(len(revs) > 1 and "Exporting patches:\n" or "Exporting patch:\n")
614 for cset in revs:
614 for cset in revs:
615 seqno += 1
615 seqno += 1
616 doexport(ui, repo, cset, seqno, total, revwidth, opts)
616 doexport(ui, repo, cset, seqno, total, revwidth, opts)
617
617
618 def forget(ui, repo, *pats, **opts):
618 def forget(ui, repo, *pats, **opts):
619 """don't add the specified files on the next commit"""
619 """don't add the specified files on the next commit"""
620 q = dict(zip(pats, pats))
620 q = dict(zip(pats, pats))
621 forget = []
621 forget = []
622 for src, abs, rel in walk(repo, pats, opts):
622 for src, abs, rel in walk(repo, pats, opts):
623 if repo.dirstate.state(abs) == 'a':
623 if repo.dirstate.state(abs) == 'a':
624 forget.append(abs)
624 forget.append(abs)
625 if rel not in q: ui.status('forgetting ', rel, '\n')
625 if rel not in q: ui.status('forgetting ', rel, '\n')
626 repo.forget(forget)
626 repo.forget(forget)
627
627
628 def heads(ui, repo):
628 def heads(ui, repo):
629 """show current repository heads"""
629 """show current repository heads"""
630 for n in repo.changelog.heads():
630 for n in repo.changelog.heads():
631 show_changeset(ui, repo, changenode=n)
631 show_changeset(ui, repo, changenode=n)
632
632
633 def identify(ui, repo):
633 def identify(ui, repo):
634 """print information about the working copy"""
634 """print information about the working copy"""
635 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
635 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
636 if not parents:
636 if not parents:
637 ui.write("unknown\n")
637 ui.write("unknown\n")
638 return
638 return
639
639
640 hexfunc = ui.verbose and hg.hex or hg.short
640 hexfunc = ui.verbose and hg.hex or hg.short
641 (c, a, d, u) = repo.changes()
641 (c, a, d, u) = repo.changes()
642 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
642 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
643 (c or a or d) and "+" or "")]
643 (c or a or d) and "+" or "")]
644
644
645 if not ui.quiet:
645 if not ui.quiet:
646 # multiple tags for a single parent separated by '/'
646 # multiple tags for a single parent separated by '/'
647 parenttags = ['/'.join(tags)
647 parenttags = ['/'.join(tags)
648 for tags in map(repo.nodetags, parents) if tags]
648 for tags in map(repo.nodetags, parents) if tags]
649 # tags for multiple parents separated by ' + '
649 # tags for multiple parents separated by ' + '
650 if parenttags:
650 if parenttags:
651 output.append(' + '.join(parenttags))
651 output.append(' + '.join(parenttags))
652
652
653 ui.write("%s\n" % ' '.join(output))
653 ui.write("%s\n" % ' '.join(output))
654
654
655 def import_(ui, repo, patch1, *patches, **opts):
655 def import_(ui, repo, patch1, *patches, **opts):
656 """import an ordered set of patches"""
656 """import an ordered set of patches"""
657 patches = (patch1,) + patches
657 patches = (patch1,) + patches
658
658
659 d = opts["base"]
659 d = opts["base"]
660 strip = opts["strip"]
660 strip = opts["strip"]
661
661
662 for patch in patches:
662 for patch in patches:
663 ui.status("applying %s\n" % patch)
663 ui.status("applying %s\n" % patch)
664 pf = os.path.join(d, patch)
664 pf = os.path.join(d, patch)
665
665
666 message = []
666 message = []
667 user = None
667 user = None
668 hgpatch = False
668 hgpatch = False
669 for line in file(pf):
669 for line in file(pf):
670 line = line.rstrip()
670 line = line.rstrip()
671 if line.startswith("--- ") or line.startswith("diff -r"):
671 if line.startswith("--- ") or line.startswith("diff -r"):
672 break
672 break
673 elif hgpatch:
673 elif hgpatch:
674 # parse values when importing the result of an hg export
674 # parse values when importing the result of an hg export
675 if line.startswith("# User "):
675 if line.startswith("# User "):
676 user = line[7:]
676 user = line[7:]
677 ui.debug('User: %s\n' % user)
677 ui.debug('User: %s\n' % user)
678 elif not line.startswith("# ") and line:
678 elif not line.startswith("# ") and line:
679 message.append(line)
679 message.append(line)
680 hgpatch = False
680 hgpatch = False
681 elif line == '# HG changeset patch':
681 elif line == '# HG changeset patch':
682 hgpatch = True
682 hgpatch = True
683 else:
683 else:
684 message.append(line)
684 message.append(line)
685
685
686 # make sure message isn't empty
686 # make sure message isn't empty
687 if not message:
687 if not message:
688 message = "imported patch %s\n" % patch
688 message = "imported patch %s\n" % patch
689 else:
689 else:
690 message = "%s\n" % '\n'.join(message)
690 message = "%s\n" % '\n'.join(message)
691 ui.debug('message:\n%s\n' % message)
691 ui.debug('message:\n%s\n' % message)
692
692
693 f = os.popen("patch -p%d < %s" % (strip, pf))
693 f = os.popen("patch -p%d < %s" % (strip, pf))
694 files = []
694 files = []
695 for l in f.read().splitlines():
695 for l in f.read().splitlines():
696 l.rstrip('\r\n');
696 l.rstrip('\r\n');
697 ui.status("%s\n" % l)
697 ui.status("%s\n" % l)
698 if l.startswith('patching file '):
698 if l.startswith('patching file '):
699 pf = l[14:]
699 pf = l[14:]
700 if pf not in files:
700 if pf not in files:
701 files.append(pf)
701 files.append(pf)
702 patcherr = f.close()
702 patcherr = f.close()
703 if patcherr:
703 if patcherr:
704 raise Abort("patch failed")
704 raise Abort("patch failed")
705
705
706 if len(files) > 0:
706 if len(files) > 0:
707 addremove(ui, repo, *files)
707 addremove(ui, repo, *files)
708 repo.commit(files, message, user)
708 repo.commit(files, message, user)
709
709
710 def init(ui, source=None):
710 def init(ui, source=None):
711 """create a new repository in the current directory"""
711 """create a new repository in the current directory"""
712
712
713 if source:
713 if source:
714 raise Abort("no longer supported: use \"hg clone\" instead")
714 raise Abort("no longer supported: use \"hg clone\" instead")
715 hg.repository(ui, ".", create=1)
715 hg.repository(ui, ".", create=1)
716
716
717 def locate(ui, repo, *pats, **opts):
717 def locate(ui, repo, *pats, **opts):
718 """locate files matching specific patterns"""
718 """locate files matching specific patterns"""
719 end = '\n'
719 end = '\n'
720 if opts['print0']: end = '\0'
720 if opts['print0']: end = '\0'
721
721
722 for src, abs, rel in walk(repo, pats, opts, '(?:.*/|)'):
722 for src, abs, rel in walk(repo, pats, opts, '(?:.*/|)'):
723 if repo.dirstate.state(abs) == '?': continue
723 if repo.dirstate.state(abs) == '?': continue
724 if opts['fullpath']:
724 if opts['fullpath']:
725 ui.write(os.path.join(repo.root, abs), end)
725 ui.write(os.path.join(repo.root, abs), end)
726 else:
726 else:
727 ui.write(rel, end)
727 ui.write(rel, end)
728
728
729 def log(ui, repo, f=None, **opts):
729 def log(ui, repo, f=None, **opts):
730 """show the revision history of the repository or a single file"""
730 """show the revision history of the repository or a single file"""
731 if f:
731 if f:
732 files = relpath(repo, [f])
732 files = relpath(repo, [f])
733 filelog = repo.file(files[0])
733 filelog = repo.file(files[0])
734 log = filelog
734 log = filelog
735 lookup = filelog.lookup
735 lookup = filelog.lookup
736 else:
736 else:
737 files = None
737 files = None
738 filelog = None
738 filelog = None
739 log = repo.changelog
739 log = repo.changelog
740 lookup = repo.lookup
740 lookup = repo.lookup
741 revlist = []
741 revlist = []
742 revs = [log.rev(lookup(rev)) for rev in opts['rev']]
742 revs = [log.rev(lookup(rev)) for rev in opts['rev']]
743 while revs:
743 while revs:
744 if len(revs) == 1:
744 if len(revs) == 1:
745 revlist.append(revs.pop(0))
745 revlist.append(revs.pop(0))
746 else:
746 else:
747 a = revs.pop(0)
747 a = revs.pop(0)
748 b = revs.pop(0)
748 b = revs.pop(0)
749 off = a > b and -1 or 1
749 off = a > b and -1 or 1
750 revlist.extend(range(a, b + off, off))
750 revlist.extend(range(a, b + off, off))
751
751
752 for i in revlist or range(log.count() - 1, -1, -1):
752 for i in revlist or range(log.count() - 1, -1, -1):
753 show_changeset(ui, repo, filelog=filelog, rev=i)
753 show_changeset(ui, repo, filelog=filelog, rev=i)
754 if opts['patch']:
754 if opts['patch']:
755 if filelog:
755 if filelog:
756 filenode = filelog.node(i)
756 filenode = filelog.node(i)
757 i = filelog.linkrev(filenode)
757 i = filelog.linkrev(filenode)
758 changenode = repo.changelog.node(i)
758 changenode = repo.changelog.node(i)
759 prev, other = repo.changelog.parents(changenode)
759 prev, other = repo.changelog.parents(changenode)
760 dodiff(sys.stdout, ui, repo, files, prev, changenode)
760 dodiff(sys.stdout, ui, repo, files, prev, changenode)
761 ui.write("\n\n")
761 ui.write("\n\n")
762
762
763 def manifest(ui, repo, rev=None):
763 def manifest(ui, repo, rev=None):
764 """output the latest or given revision of the project manifest"""
764 """output the latest or given revision of the project manifest"""
765 if rev:
765 if rev:
766 try:
766 try:
767 # assume all revision numbers are for changesets
767 # assume all revision numbers are for changesets
768 n = repo.lookup(rev)
768 n = repo.lookup(rev)
769 change = repo.changelog.read(n)
769 change = repo.changelog.read(n)
770 n = change[0]
770 n = change[0]
771 except hg.RepoError:
771 except hg.RepoError:
772 n = repo.manifest.lookup(rev)
772 n = repo.manifest.lookup(rev)
773 else:
773 else:
774 n = repo.manifest.tip()
774 n = repo.manifest.tip()
775 m = repo.manifest.read(n)
775 m = repo.manifest.read(n)
776 mf = repo.manifest.readflags(n)
776 mf = repo.manifest.readflags(n)
777 files = m.keys()
777 files = m.keys()
778 files.sort()
778 files.sort()
779
779
780 for f in files:
780 for f in files:
781 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
781 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
782
782
783 def parents(ui, repo, rev=None):
783 def parents(ui, repo, rev=None):
784 """show the parents of the working dir or revision"""
784 """show the parents of the working dir or revision"""
785 if rev:
785 if rev:
786 p = repo.changelog.parents(repo.lookup(rev))
786 p = repo.changelog.parents(repo.lookup(rev))
787 else:
787 else:
788 p = repo.dirstate.parents()
788 p = repo.dirstate.parents()
789
789
790 for n in p:
790 for n in p:
791 if n != hg.nullid:
791 if n != hg.nullid:
792 show_changeset(ui, repo, changenode=n)
792 show_changeset(ui, repo, changenode=n)
793
793
794 def paths(ui, repo, search = None):
794 def paths(ui, repo, search = None):
795 """show path or list of available paths"""
795 """show path or list of available paths"""
796 if search:
796 if search:
797 for name, path in ui.configitems("paths"):
797 for name, path in ui.configitems("paths"):
798 if name == search:
798 if name == search:
799 ui.write("%s\n" % path)
799 ui.write("%s\n" % path)
800 return
800 return
801 ui.warn("not found!\n")
801 ui.warn("not found!\n")
802 return 1
802 return 1
803 else:
803 else:
804 for name, path in ui.configitems("paths"):
804 for name, path in ui.configitems("paths"):
805 ui.write("%s = %s\n" % (name, path))
805 ui.write("%s = %s\n" % (name, path))
806
806
807 def pull(ui, repo, source="default", **opts):
807 def pull(ui, repo, source="default", **opts):
808 """pull changes from the specified source"""
808 """pull changes from the specified source"""
809 source = ui.expandpath(source)
809 source = ui.expandpath(source)
810 ui.status('pulling from %s\n' % (source))
810 ui.status('pulling from %s\n' % (source))
811
811
812 other = hg.repository(ui, source)
812 other = hg.repository(ui, source)
813 r = repo.pull(other)
813 r = repo.pull(other)
814 if not r:
814 if not r:
815 if opts['update']:
815 if opts['update']:
816 return update(ui, repo)
816 return update(ui, repo)
817 else:
817 else:
818 ui.status("(run 'hg update' to get a working copy)\n")
818 ui.status("(run 'hg update' to get a working copy)\n")
819
819
820 return r
820 return r
821
821
822 def push(ui, repo, dest="default-push"):
822 def push(ui, repo, dest="default-push", force=False):
823 """push changes to the specified destination"""
823 """push changes to the specified destination"""
824 dest = ui.expandpath(dest)
824 dest = ui.expandpath(dest)
825 ui.status('pushing to %s\n' % (dest))
825 ui.status('pushing to %s\n' % (dest))
826
826
827 other = hg.repository(ui, dest)
827 other = hg.repository(ui, dest)
828 r = repo.push(other)
828 r = repo.push(other, force)
829 return r
829 return r
830
830
831 def rawcommit(ui, repo, *flist, **rc):
831 def rawcommit(ui, repo, *flist, **rc):
832 "raw commit interface"
832 "raw commit interface"
833 if rc['text']:
833 if rc['text']:
834 ui.warn("Warning: -t and --text is deprecated,"
834 ui.warn("Warning: -t and --text is deprecated,"
835 " please use -m or --message instead.\n")
835 " please use -m or --message instead.\n")
836 message = rc['message'] or rc['text']
836 message = rc['message'] or rc['text']
837 if not message and rc['logfile']:
837 if not message and rc['logfile']:
838 try:
838 try:
839 message = open(rc['logfile']).read()
839 message = open(rc['logfile']).read()
840 except IOError:
840 except IOError:
841 pass
841 pass
842 if not message and not rc['logfile']:
842 if not message and not rc['logfile']:
843 ui.warn("abort: missing commit message\n")
843 ui.warn("abort: missing commit message\n")
844 return 1
844 return 1
845
845
846 files = relpath(repo, list(flist))
846 files = relpath(repo, list(flist))
847 if rc['files']:
847 if rc['files']:
848 files += open(rc['files']).read().splitlines()
848 files += open(rc['files']).read().splitlines()
849
849
850 rc['parent'] = map(repo.lookup, rc['parent'])
850 rc['parent'] = map(repo.lookup, rc['parent'])
851
851
852 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
852 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
853
853
854 def recover(ui, repo):
854 def recover(ui, repo):
855 """roll back an interrupted transaction"""
855 """roll back an interrupted transaction"""
856 repo.recover()
856 repo.recover()
857
857
858 def remove(ui, repo, file1, *files):
858 def remove(ui, repo, file1, *files):
859 """remove the specified files on the next commit"""
859 """remove the specified files on the next commit"""
860 repo.remove(relpath(repo, (file1,) + files))
860 repo.remove(relpath(repo, (file1,) + files))
861
861
862 def revert(ui, repo, *names, **opts):
862 def revert(ui, repo, *names, **opts):
863 """revert modified files or dirs back to their unmodified states"""
863 """revert modified files or dirs back to their unmodified states"""
864 node = opts['rev'] and repo.lookup(opts['rev']) or \
864 node = opts['rev'] and repo.lookup(opts['rev']) or \
865 repo.dirstate.parents()[0]
865 repo.dirstate.parents()[0]
866 root = os.path.realpath(repo.root)
866 root = os.path.realpath(repo.root)
867
867
868 def trimpath(p):
868 def trimpath(p):
869 p = os.path.realpath(p)
869 p = os.path.realpath(p)
870 if p.startswith(root):
870 if p.startswith(root):
871 rest = p[len(root):]
871 rest = p[len(root):]
872 if not rest:
872 if not rest:
873 return rest
873 return rest
874 if p.startswith(os.sep):
874 if p.startswith(os.sep):
875 return rest[1:]
875 return rest[1:]
876 return p
876 return p
877
877
878 relnames = map(trimpath, names or [os.getcwd()])
878 relnames = map(trimpath, names or [os.getcwd()])
879 chosen = {}
879 chosen = {}
880
880
881 def choose(name):
881 def choose(name):
882 def body(name):
882 def body(name):
883 for r in relnames:
883 for r in relnames:
884 if not name.startswith(r):
884 if not name.startswith(r):
885 continue
885 continue
886 rest = name[len(r):]
886 rest = name[len(r):]
887 if not rest:
887 if not rest:
888 return r, True
888 return r, True
889 depth = rest.count(os.sep)
889 depth = rest.count(os.sep)
890 if not r:
890 if not r:
891 if depth == 0 or not opts['nonrecursive']:
891 if depth == 0 or not opts['nonrecursive']:
892 return r, True
892 return r, True
893 elif rest[0] == os.sep:
893 elif rest[0] == os.sep:
894 if depth == 1 or not opts['nonrecursive']:
894 if depth == 1 or not opts['nonrecursive']:
895 return r, True
895 return r, True
896 return None, False
896 return None, False
897 relname, ret = body(name)
897 relname, ret = body(name)
898 if ret:
898 if ret:
899 chosen[relname] = 1
899 chosen[relname] = 1
900 return ret
900 return ret
901
901
902 r = repo.update(node, False, True, choose, False)
902 r = repo.update(node, False, True, choose, False)
903 for n in relnames:
903 for n in relnames:
904 if n not in chosen:
904 if n not in chosen:
905 ui.warn('error: no matches for %s\n' % n)
905 ui.warn('error: no matches for %s\n' % n)
906 r = 1
906 r = 1
907 sys.stdout.flush()
907 sys.stdout.flush()
908 return r
908 return r
909
909
910 def root(ui, repo):
910 def root(ui, repo):
911 """print the root (top) of the current working dir"""
911 """print the root (top) of the current working dir"""
912 ui.write(repo.root + "\n")
912 ui.write(repo.root + "\n")
913
913
914 def serve(ui, repo, **opts):
914 def serve(ui, repo, **opts):
915 """export the repository via HTTP"""
915 """export the repository via HTTP"""
916
916
917 if opts["stdio"]:
917 if opts["stdio"]:
918 fin, fout = sys.stdin, sys.stdout
918 fin, fout = sys.stdin, sys.stdout
919 sys.stdout = sys.stderr
919 sys.stdout = sys.stderr
920
920
921 def getarg():
921 def getarg():
922 argline = fin.readline()[:-1]
922 argline = fin.readline()[:-1]
923 arg, l = argline.split()
923 arg, l = argline.split()
924 val = fin.read(int(l))
924 val = fin.read(int(l))
925 return arg, val
925 return arg, val
926 def respond(v):
926 def respond(v):
927 fout.write("%d\n" % len(v))
927 fout.write("%d\n" % len(v))
928 fout.write(v)
928 fout.write(v)
929 fout.flush()
929 fout.flush()
930
930
931 lock = None
931 lock = None
932
932
933 while 1:
933 while 1:
934 cmd = fin.readline()[:-1]
934 cmd = fin.readline()[:-1]
935 if cmd == '':
935 if cmd == '':
936 return
936 return
937 if cmd == "heads":
937 if cmd == "heads":
938 h = repo.heads()
938 h = repo.heads()
939 respond(" ".join(map(hg.hex, h)) + "\n")
939 respond(" ".join(map(hg.hex, h)) + "\n")
940 if cmd == "lock":
940 if cmd == "lock":
941 lock = repo.lock()
941 lock = repo.lock()
942 respond("")
942 respond("")
943 if cmd == "unlock":
943 if cmd == "unlock":
944 if lock:
944 if lock:
945 lock.release()
945 lock.release()
946 lock = None
946 lock = None
947 respond("")
947 respond("")
948 elif cmd == "branches":
948 elif cmd == "branches":
949 arg, nodes = getarg()
949 arg, nodes = getarg()
950 nodes = map(hg.bin, nodes.split(" "))
950 nodes = map(hg.bin, nodes.split(" "))
951 r = []
951 r = []
952 for b in repo.branches(nodes):
952 for b in repo.branches(nodes):
953 r.append(" ".join(map(hg.hex, b)) + "\n")
953 r.append(" ".join(map(hg.hex, b)) + "\n")
954 respond("".join(r))
954 respond("".join(r))
955 elif cmd == "between":
955 elif cmd == "between":
956 arg, pairs = getarg()
956 arg, pairs = getarg()
957 pairs = [map(hg.bin, p.split("-")) for p in pairs.split(" ")]
957 pairs = [map(hg.bin, p.split("-")) for p in pairs.split(" ")]
958 r = []
958 r = []
959 for b in repo.between(pairs):
959 for b in repo.between(pairs):
960 r.append(" ".join(map(hg.hex, b)) + "\n")
960 r.append(" ".join(map(hg.hex, b)) + "\n")
961 respond("".join(r))
961 respond("".join(r))
962 elif cmd == "changegroup":
962 elif cmd == "changegroup":
963 nodes = []
963 nodes = []
964 arg, roots = getarg()
964 arg, roots = getarg()
965 nodes = map(hg.bin, roots.split(" "))
965 nodes = map(hg.bin, roots.split(" "))
966
966
967 cg = repo.changegroup(nodes)
967 cg = repo.changegroup(nodes)
968 while 1:
968 while 1:
969 d = cg.read(4096)
969 d = cg.read(4096)
970 if not d:
970 if not d:
971 break
971 break
972 fout.write(d)
972 fout.write(d)
973
973
974 fout.flush()
974 fout.flush()
975
975
976 elif cmd == "addchangegroup":
976 elif cmd == "addchangegroup":
977 if not lock:
977 if not lock:
978 respond("not locked")
978 respond("not locked")
979 continue
979 continue
980 respond("")
980 respond("")
981
981
982 r = repo.addchangegroup(fin)
982 r = repo.addchangegroup(fin)
983 respond("")
983 respond("")
984
984
985 def openlog(opt, default):
985 def openlog(opt, default):
986 if opts[opt] and opts[opt] != '-':
986 if opts[opt] and opts[opt] != '-':
987 return open(opts[opt], 'w')
987 return open(opts[opt], 'w')
988 else:
988 else:
989 return default
989 return default
990
990
991 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
991 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
992 opts["address"], opts["port"],
992 opts["address"], opts["port"],
993 openlog('accesslog', sys.stdout),
993 openlog('accesslog', sys.stdout),
994 openlog('errorlog', sys.stderr))
994 openlog('errorlog', sys.stderr))
995 if ui.verbose:
995 if ui.verbose:
996 addr, port = httpd.socket.getsockname()
996 addr, port = httpd.socket.getsockname()
997 if addr == '0.0.0.0':
997 if addr == '0.0.0.0':
998 addr = socket.gethostname()
998 addr = socket.gethostname()
999 else:
999 else:
1000 try:
1000 try:
1001 addr = socket.gethostbyaddr(addr)[0]
1001 addr = socket.gethostbyaddr(addr)[0]
1002 except socket.error:
1002 except socket.error:
1003 pass
1003 pass
1004 if port != 80:
1004 if port != 80:
1005 ui.status('listening at http://%s:%d/\n' % (addr, port))
1005 ui.status('listening at http://%s:%d/\n' % (addr, port))
1006 else:
1006 else:
1007 ui.status('listening at http://%s/\n' % addr)
1007 ui.status('listening at http://%s/\n' % addr)
1008 httpd.serve_forever()
1008 httpd.serve_forever()
1009
1009
1010 def status(ui, repo, *pats, **opts):
1010 def status(ui, repo, *pats, **opts):
1011 '''show changed files in the working directory
1011 '''show changed files in the working directory
1012
1012
1013 M = modified
1013 M = modified
1014 A = added
1014 A = added
1015 R = removed
1015 R = removed
1016 ? = not tracked'''
1016 ? = not tracked'''
1017
1017
1018 files, matchfn = matchpats(repo.getcwd(), pats, opts)
1018 files, matchfn = matchpats(repo.getcwd(), pats, opts)
1019 (c, a, d, u) = repo.changes(files = files, match = matchfn)
1019 (c, a, d, u) = repo.changes(files = files, match = matchfn)
1020 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
1020 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
1021
1021
1022 for f in c:
1022 for f in c:
1023 ui.write("M ", f, "\n")
1023 ui.write("M ", f, "\n")
1024 for f in a:
1024 for f in a:
1025 ui.write("A ", f, "\n")
1025 ui.write("A ", f, "\n")
1026 for f in d:
1026 for f in d:
1027 ui.write("R ", f, "\n")
1027 ui.write("R ", f, "\n")
1028 for f in u:
1028 for f in u:
1029 ui.write("? ", f, "\n")
1029 ui.write("? ", f, "\n")
1030
1030
1031 def tag(ui, repo, name, rev=None, **opts):
1031 def tag(ui, repo, name, rev=None, **opts):
1032 """add a tag for the current tip or a given revision"""
1032 """add a tag for the current tip or a given revision"""
1033 if opts['text']:
1033 if opts['text']:
1034 ui.warn("Warning: -t and --text is deprecated,"
1034 ui.warn("Warning: -t and --text is deprecated,"
1035 " please use -m or --message instead.\n")
1035 " please use -m or --message instead.\n")
1036 if name == "tip":
1036 if name == "tip":
1037 ui.warn("abort: 'tip' is a reserved name!\n")
1037 ui.warn("abort: 'tip' is a reserved name!\n")
1038 return -1
1038 return -1
1039 if rev:
1039 if rev:
1040 r = hg.hex(repo.lookup(rev))
1040 r = hg.hex(repo.lookup(rev))
1041 else:
1041 else:
1042 r = hg.hex(repo.changelog.tip())
1042 r = hg.hex(repo.changelog.tip())
1043
1043
1044 if name.find(revrangesep) >= 0:
1044 if name.find(revrangesep) >= 0:
1045 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep)
1045 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep)
1046 return -1
1046 return -1
1047
1047
1048 if opts['local']:
1048 if opts['local']:
1049 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1049 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1050 return
1050 return
1051
1051
1052 (c, a, d, u) = repo.changes()
1052 (c, a, d, u) = repo.changes()
1053 for x in (c, a, d, u):
1053 for x in (c, a, d, u):
1054 if ".hgtags" in x:
1054 if ".hgtags" in x:
1055 ui.warn("abort: working copy of .hgtags is changed!\n")
1055 ui.warn("abort: working copy of .hgtags is changed!\n")
1056 ui.status("(please commit .hgtags manually)\n")
1056 ui.status("(please commit .hgtags manually)\n")
1057 return -1
1057 return -1
1058
1058
1059 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1059 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1060 if repo.dirstate.state(".hgtags") == '?':
1060 if repo.dirstate.state(".hgtags") == '?':
1061 repo.add([".hgtags"])
1061 repo.add([".hgtags"])
1062
1062
1063 message = (opts['message'] or opts['text'] or
1063 message = (opts['message'] or opts['text'] or
1064 "Added tag %s for changeset %s" % (name, r))
1064 "Added tag %s for changeset %s" % (name, r))
1065 repo.commit([".hgtags"], message, opts['user'], opts['date'])
1065 repo.commit([".hgtags"], message, opts['user'], opts['date'])
1066
1066
1067 def tags(ui, repo):
1067 def tags(ui, repo):
1068 """list repository tags"""
1068 """list repository tags"""
1069
1069
1070 l = repo.tagslist()
1070 l = repo.tagslist()
1071 l.reverse()
1071 l.reverse()
1072 for t, n in l:
1072 for t, n in l:
1073 try:
1073 try:
1074 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
1074 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
1075 except KeyError:
1075 except KeyError:
1076 r = " ?:?"
1076 r = " ?:?"
1077 ui.write("%-30s %s\n" % (t, r))
1077 ui.write("%-30s %s\n" % (t, r))
1078
1078
1079 def tip(ui, repo):
1079 def tip(ui, repo):
1080 """show the tip revision"""
1080 """show the tip revision"""
1081 n = repo.changelog.tip()
1081 n = repo.changelog.tip()
1082 show_changeset(ui, repo, changenode=n)
1082 show_changeset(ui, repo, changenode=n)
1083
1083
1084 def undo(ui, repo):
1084 def undo(ui, repo):
1085 """undo the last commit or pull
1085 """undo the last commit or pull
1086
1086
1087 Roll back the last pull or commit transaction on the
1087 Roll back the last pull or commit transaction on the
1088 repository, restoring the project to its earlier state.
1088 repository, restoring the project to its earlier state.
1089
1089
1090 This command should be used with care. There is only one level of
1090 This command should be used with care. There is only one level of
1091 undo and there is no redo.
1091 undo and there is no redo.
1092
1092
1093 This command is not intended for use on public repositories. Once
1093 This command is not intended for use on public repositories. Once
1094 a change is visible for pull by other users, undoing it locally is
1094 a change is visible for pull by other users, undoing it locally is
1095 ineffective.
1095 ineffective.
1096 """
1096 """
1097 repo.undo()
1097 repo.undo()
1098
1098
1099 def update(ui, repo, node=None, merge=False, clean=False):
1099 def update(ui, repo, node=None, merge=False, clean=False):
1100 '''update or merge working directory
1100 '''update or merge working directory
1101
1101
1102 If there are no outstanding changes in the working directory and
1102 If there are no outstanding changes in the working directory and
1103 there is a linear relationship between the current version and the
1103 there is a linear relationship between the current version and the
1104 requested version, the result is the requested version.
1104 requested version, the result is the requested version.
1105
1105
1106 Otherwise the result is a merge between the contents of the
1106 Otherwise the result is a merge between the contents of the
1107 current working directory and the requested version. Files that
1107 current working directory and the requested version. Files that
1108 changed between either parent are marked as changed for the next
1108 changed between either parent are marked as changed for the next
1109 commit and a commit must be performed before any further updates
1109 commit and a commit must be performed before any further updates
1110 are allowed.
1110 are allowed.
1111 '''
1111 '''
1112 node = node and repo.lookup(node) or repo.changelog.tip()
1112 node = node and repo.lookup(node) or repo.changelog.tip()
1113 return repo.update(node, allow=merge, force=clean)
1113 return repo.update(node, allow=merge, force=clean)
1114
1114
1115 def verify(ui, repo):
1115 def verify(ui, repo):
1116 """verify the integrity of the repository"""
1116 """verify the integrity of the repository"""
1117 return repo.verify()
1117 return repo.verify()
1118
1118
1119 # Command options and aliases are listed here, alphabetically
1119 # Command options and aliases are listed here, alphabetically
1120
1120
1121 table = {
1121 table = {
1122 "^add": (add,
1122 "^add": (add,
1123 [('I', 'include', [], 'include path in search'),
1123 [('I', 'include', [], 'include path in search'),
1124 ('X', 'exclude', [], 'exclude path from search')],
1124 ('X', 'exclude', [], 'exclude path from search')],
1125 "hg add [FILE]..."),
1125 "hg add [FILE]..."),
1126 "addremove": (addremove,
1126 "addremove": (addremove,
1127 [('I', 'include', [], 'include path in search'),
1127 [('I', 'include', [], 'include path in search'),
1128 ('X', 'exclude', [], 'exclude path from search')],
1128 ('X', 'exclude', [], 'exclude path from search')],
1129 "hg addremove [OPTION]... [FILE]..."),
1129 "hg addremove [OPTION]... [FILE]..."),
1130 "^annotate":
1130 "^annotate":
1131 (annotate,
1131 (annotate,
1132 [('r', 'rev', '', 'revision'),
1132 [('r', 'rev', '', 'revision'),
1133 ('u', 'user', None, 'show user'),
1133 ('u', 'user', None, 'show user'),
1134 ('n', 'number', None, 'show revision number'),
1134 ('n', 'number', None, 'show revision number'),
1135 ('c', 'changeset', None, 'show changeset'),
1135 ('c', 'changeset', None, 'show changeset'),
1136 ('I', 'include', [], 'include path in search'),
1136 ('I', 'include', [], 'include path in search'),
1137 ('X', 'exclude', [], 'exclude path from search')],
1137 ('X', 'exclude', [], 'exclude path from search')],
1138 'hg annotate [-r REV] [-u] [-n] [-c] FILE...'),
1138 'hg annotate [-r REV] [-u] [-n] [-c] FILE...'),
1139 "cat":
1139 "cat":
1140 (cat,
1140 (cat,
1141 [('o', 'output', "", 'output to file')],
1141 [('o', 'output', "", 'output to file')],
1142 'hg cat [-o OUTFILE] FILE [REV]'),
1142 'hg cat [-o OUTFILE] FILE [REV]'),
1143 "^clone":
1143 "^clone":
1144 (clone,
1144 (clone,
1145 [('U', 'noupdate', None, 'skip update after cloning')],
1145 [('U', 'noupdate', None, 'skip update after cloning')],
1146 'hg clone [-U] SOURCE [DEST]'),
1146 'hg clone [-U] SOURCE [DEST]'),
1147 "^commit|ci":
1147 "^commit|ci":
1148 (commit,
1148 (commit,
1149 [('A', 'addremove', None, 'run add/remove during commit'),
1149 [('A', 'addremove', None, 'run add/remove during commit'),
1150 ('I', 'include', [], 'include path in search'),
1150 ('I', 'include', [], 'include path in search'),
1151 ('X', 'exclude', [], 'exclude path from search'),
1151 ('X', 'exclude', [], 'exclude path from search'),
1152 ('m', 'message', "", 'commit message'),
1152 ('m', 'message', "", 'commit message'),
1153 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1153 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1154 ('l', 'logfile', "", 'commit message file'),
1154 ('l', 'logfile', "", 'commit message file'),
1155 ('d', 'date', "", 'date code'),
1155 ('d', 'date', "", 'date code'),
1156 ('u', 'user', "", 'user')],
1156 ('u', 'user', "", 'user')],
1157 'hg commit [OPTION]... [FILE]...'),
1157 'hg commit [OPTION]... [FILE]...'),
1158 "copy": (copy, [], 'hg copy SOURCE DEST'),
1158 "copy": (copy, [], 'hg copy SOURCE DEST'),
1159 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'),
1159 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'),
1160 "debugstate": (debugstate, [], 'debugstate'),
1160 "debugstate": (debugstate, [], 'debugstate'),
1161 "debugindex": (debugindex, [], 'debugindex FILE'),
1161 "debugindex": (debugindex, [], 'debugindex FILE'),
1162 "debugindexdot": (debugindexdot, [], 'debugindexdot FILE'),
1162 "debugindexdot": (debugindexdot, [], 'debugindexdot FILE'),
1163 "^diff":
1163 "^diff":
1164 (diff,
1164 (diff,
1165 [('r', 'rev', [], 'revision'),
1165 [('r', 'rev', [], 'revision'),
1166 ('I', 'include', [], 'include path in search'),
1166 ('I', 'include', [], 'include path in search'),
1167 ('X', 'exclude', [], 'exclude path from search')],
1167 ('X', 'exclude', [], 'exclude path from search')],
1168 'hg diff [-r REV1 [-r REV2]] [FILE]...'),
1168 'hg diff [-r REV1 [-r REV2]] [FILE]...'),
1169 "^export":
1169 "^export":
1170 (export,
1170 (export,
1171 [('o', 'output', "", 'output to file')],
1171 [('o', 'output', "", 'output to file')],
1172 "hg export [-o OUTFILE] REV..."),
1172 "hg export [-o OUTFILE] REV..."),
1173 "forget": (forget,
1173 "forget": (forget,
1174 [('I', 'include', [], 'include path in search'),
1174 [('I', 'include', [], 'include path in search'),
1175 ('X', 'exclude', [], 'exclude path from search')],
1175 ('X', 'exclude', [], 'exclude path from search')],
1176 "hg forget FILE..."),
1176 "hg forget FILE..."),
1177 "heads": (heads, [], 'hg heads'),
1177 "heads": (heads, [], 'hg heads'),
1178 "help": (help_, [], 'hg help [COMMAND]'),
1178 "help": (help_, [], 'hg help [COMMAND]'),
1179 "identify|id": (identify, [], 'hg identify'),
1179 "identify|id": (identify, [], 'hg identify'),
1180 "import|patch":
1180 "import|patch":
1181 (import_,
1181 (import_,
1182 [('p', 'strip', 1, 'path strip'),
1182 [('p', 'strip', 1, 'path strip'),
1183 ('b', 'base', "", 'base path')],
1183 ('b', 'base', "", 'base path')],
1184 "hg import [-p NUM] [-b BASE] PATCH..."),
1184 "hg import [-p NUM] [-b BASE] PATCH..."),
1185 "^init": (init, [], 'hg init'),
1185 "^init": (init, [], 'hg init'),
1186 "locate":
1186 "locate":
1187 (locate,
1187 (locate,
1188 [('r', 'rev', '', 'revision'),
1188 [('r', 'rev', '', 'revision'),
1189 ('0', 'print0', None, 'end records with NUL'),
1189 ('0', 'print0', None, 'end records with NUL'),
1190 ('f', 'fullpath', None, 'print complete paths'),
1190 ('f', 'fullpath', None, 'print complete paths'),
1191 ('I', 'include', [], 'include path in search'),
1191 ('I', 'include', [], 'include path in search'),
1192 ('X', 'exclude', [], 'exclude path from search')],
1192 ('X', 'exclude', [], 'exclude path from search')],
1193 'hg locate [-r REV] [-f] [-0] [PATTERN]...'),
1193 'hg locate [-r REV] [-f] [-0] [PATTERN]...'),
1194 "^log|history":
1194 "^log|history":
1195 (log,
1195 (log,
1196 [('r', 'rev', [], 'revision'),
1196 [('r', 'rev', [], 'revision'),
1197 ('p', 'patch', None, 'show patch')],
1197 ('p', 'patch', None, 'show patch')],
1198 'hg log [-r REV1 [-r REV2]] [-p] [FILE]'),
1198 'hg log [-r REV1 [-r REV2]] [-p] [FILE]'),
1199 "manifest": (manifest, [], 'hg manifest [REV]'),
1199 "manifest": (manifest, [], 'hg manifest [REV]'),
1200 "parents": (parents, [], 'hg parents [REV]'),
1200 "parents": (parents, [], 'hg parents [REV]'),
1201 "paths": (paths, [], 'hg paths [name]'),
1201 "paths": (paths, [], 'hg paths [name]'),
1202 "^pull":
1202 "^pull":
1203 (pull,
1203 (pull,
1204 [('u', 'update', None, 'update working directory')],
1204 [('u', 'update', None, 'update working directory')],
1205 'hg pull [-u] [SOURCE]'),
1205 'hg pull [-u] [SOURCE]'),
1206 "^push": (push, [], 'hg push [DEST]'),
1206 "^push":
1207 (push,
1208 [('f', 'force', None, 'force push')],
1209 'hg push [DEST]'),
1207 "rawcommit":
1210 "rawcommit":
1208 (rawcommit,
1211 (rawcommit,
1209 [('p', 'parent', [], 'parent'),
1212 [('p', 'parent', [], 'parent'),
1210 ('d', 'date', "", 'date code'),
1213 ('d', 'date', "", 'date code'),
1211 ('u', 'user', "", 'user'),
1214 ('u', 'user', "", 'user'),
1212 ('F', 'files', "", 'file list'),
1215 ('F', 'files', "", 'file list'),
1213 ('m', 'message', "", 'commit message'),
1216 ('m', 'message', "", 'commit message'),
1214 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1217 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1215 ('l', 'logfile', "", 'commit message file')],
1218 ('l', 'logfile', "", 'commit message file')],
1216 'hg rawcommit [OPTION]... [FILE]...'),
1219 'hg rawcommit [OPTION]... [FILE]...'),
1217 "recover": (recover, [], "hg recover"),
1220 "recover": (recover, [], "hg recover"),
1218 "^remove|rm": (remove, [], "hg remove FILE..."),
1221 "^remove|rm": (remove, [], "hg remove FILE..."),
1219 "^revert":
1222 "^revert":
1220 (revert,
1223 (revert,
1221 [("n", "nonrecursive", None, "don't recurse into subdirs"),
1224 [("n", "nonrecursive", None, "don't recurse into subdirs"),
1222 ("r", "rev", "", "revision")],
1225 ("r", "rev", "", "revision")],
1223 "hg revert [-n] [-r REV] [NAME]..."),
1226 "hg revert [-n] [-r REV] [NAME]..."),
1224 "root": (root, [], "hg root"),
1227 "root": (root, [], "hg root"),
1225 "^serve":
1228 "^serve":
1226 (serve,
1229 (serve,
1227 [('A', 'accesslog', '', 'access log file'),
1230 [('A', 'accesslog', '', 'access log file'),
1228 ('E', 'errorlog', '', 'error log file'),
1231 ('E', 'errorlog', '', 'error log file'),
1229 ('p', 'port', 8000, 'listen port'),
1232 ('p', 'port', 8000, 'listen port'),
1230 ('a', 'address', '', 'interface address'),
1233 ('a', 'address', '', 'interface address'),
1231 ('n', 'name', os.getcwd(), 'repository name'),
1234 ('n', 'name', os.getcwd(), 'repository name'),
1232 ('', 'stdio', None, 'for remote clients'),
1235 ('', 'stdio', None, 'for remote clients'),
1233 ('t', 'templates', "", 'template map')],
1236 ('t', 'templates', "", 'template map')],
1234 "hg serve [OPTION]..."),
1237 "hg serve [OPTION]..."),
1235 "^status": (status,
1238 "^status": (status,
1236 [('I', 'include', [], 'include path in search'),
1239 [('I', 'include', [], 'include path in search'),
1237 ('X', 'exclude', [], 'exclude path from search')],
1240 ('X', 'exclude', [], 'exclude path from search')],
1238 'hg status [FILE]...'),
1241 'hg status [FILE]...'),
1239 "tag":
1242 "tag":
1240 (tag,
1243 (tag,
1241 [('l', 'local', None, 'make the tag local'),
1244 [('l', 'local', None, 'make the tag local'),
1242 ('m', 'message', "", 'commit message'),
1245 ('m', 'message', "", 'commit message'),
1243 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1246 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1244 ('d', 'date', "", 'date code'),
1247 ('d', 'date', "", 'date code'),
1245 ('u', 'user', "", 'user')],
1248 ('u', 'user', "", 'user')],
1246 'hg tag [OPTION]... NAME [REV]'),
1249 'hg tag [OPTION]... NAME [REV]'),
1247 "tags": (tags, [], 'hg tags'),
1250 "tags": (tags, [], 'hg tags'),
1248 "tip": (tip, [], 'hg tip'),
1251 "tip": (tip, [], 'hg tip'),
1249 "undo": (undo, [], 'hg undo'),
1252 "undo": (undo, [], 'hg undo'),
1250 "^update|up|checkout|co":
1253 "^update|up|checkout|co":
1251 (update,
1254 (update,
1252 [('m', 'merge', None, 'allow merging of conflicts'),
1255 [('m', 'merge', None, 'allow merging of conflicts'),
1253 ('C', 'clean', None, 'overwrite locally modified files')],
1256 ('C', 'clean', None, 'overwrite locally modified files')],
1254 'hg update [-m] [-C] [REV]'),
1257 'hg update [-m] [-C] [REV]'),
1255 "verify": (verify, [], 'hg verify'),
1258 "verify": (verify, [], 'hg verify'),
1256 "version": (show_version, [], 'hg version'),
1259 "version": (show_version, [], 'hg version'),
1257 }
1260 }
1258
1261
1259 globalopts = [('v', 'verbose', None, 'verbose'),
1262 globalopts = [('v', 'verbose', None, 'verbose'),
1260 ('', 'debug', None, 'debug'),
1263 ('', 'debug', None, 'debug'),
1261 ('q', 'quiet', None, 'quiet'),
1264 ('q', 'quiet', None, 'quiet'),
1262 ('', 'profile', None, 'profile'),
1265 ('', 'profile', None, 'profile'),
1263 ('R', 'repository', "", 'repository root directory'),
1266 ('R', 'repository', "", 'repository root directory'),
1264 ('', 'traceback', None, 'print traceback on exception'),
1267 ('', 'traceback', None, 'print traceback on exception'),
1265 ('y', 'noninteractive', None, 'run non-interactively'),
1268 ('y', 'noninteractive', None, 'run non-interactively'),
1266 ('', 'version', None, 'output version information and exit'),
1269 ('', 'version', None, 'output version information and exit'),
1267 ('', 'time', None, 'time how long the command takes'),
1270 ('', 'time', None, 'time how long the command takes'),
1268 ]
1271 ]
1269
1272
1270 norepo = "clone init version help debugindex debugindexdot"
1273 norepo = "clone init version help debugindex debugindexdot"
1271
1274
1272 def find(cmd):
1275 def find(cmd):
1273 for e in table.keys():
1276 for e in table.keys():
1274 if re.match("(%s)$" % e, cmd):
1277 if re.match("(%s)$" % e, cmd):
1275 return table[e]
1278 return table[e]
1276
1279
1277 raise UnknownCommand(cmd)
1280 raise UnknownCommand(cmd)
1278
1281
1279 class SignalInterrupt(Exception):
1282 class SignalInterrupt(Exception):
1280 """Exception raised on SIGTERM and SIGHUP."""
1283 """Exception raised on SIGTERM and SIGHUP."""
1281
1284
1282 def catchterm(*args):
1285 def catchterm(*args):
1283 raise SignalInterrupt
1286 raise SignalInterrupt
1284
1287
1285 def run():
1288 def run():
1286 sys.exit(dispatch(sys.argv[1:]))
1289 sys.exit(dispatch(sys.argv[1:]))
1287
1290
1288 class ParseError(Exception):
1291 class ParseError(Exception):
1289 """Exception raised on errors in parsing the command line."""
1292 """Exception raised on errors in parsing the command line."""
1290
1293
1291 def parse(args):
1294 def parse(args):
1292 options = {}
1295 options = {}
1293 cmdoptions = {}
1296 cmdoptions = {}
1294
1297
1295 try:
1298 try:
1296 args = fancyopts.fancyopts(args, globalopts, options)
1299 args = fancyopts.fancyopts(args, globalopts, options)
1297 except fancyopts.getopt.GetoptError, inst:
1300 except fancyopts.getopt.GetoptError, inst:
1298 raise ParseError(None, inst)
1301 raise ParseError(None, inst)
1299
1302
1300 if options["version"]:
1303 if options["version"]:
1301 return ("version", show_version, [], options, cmdoptions)
1304 return ("version", show_version, [], options, cmdoptions)
1302 elif not args:
1305 elif not args:
1303 return ("help", help_, [], options, cmdoptions)
1306 return ("help", help_, [], options, cmdoptions)
1304 else:
1307 else:
1305 cmd, args = args[0], args[1:]
1308 cmd, args = args[0], args[1:]
1306
1309
1307 i = find(cmd)
1310 i = find(cmd)
1308
1311
1309 # combine global options into local
1312 # combine global options into local
1310 c = list(i[1])
1313 c = list(i[1])
1311 for o in globalopts:
1314 for o in globalopts:
1312 c.append((o[0], o[1], options[o[1]], o[3]))
1315 c.append((o[0], o[1], options[o[1]], o[3]))
1313
1316
1314 try:
1317 try:
1315 args = fancyopts.fancyopts(args, c, cmdoptions)
1318 args = fancyopts.fancyopts(args, c, cmdoptions)
1316 except fancyopts.getopt.GetoptError, inst:
1319 except fancyopts.getopt.GetoptError, inst:
1317 raise ParseError(cmd, inst)
1320 raise ParseError(cmd, inst)
1318
1321
1319 # separate global options back out
1322 # separate global options back out
1320 for o in globalopts:
1323 for o in globalopts:
1321 n = o[1]
1324 n = o[1]
1322 options[n] = cmdoptions[n]
1325 options[n] = cmdoptions[n]
1323 del cmdoptions[n]
1326 del cmdoptions[n]
1324
1327
1325 return (cmd, i[0], args, options, cmdoptions)
1328 return (cmd, i[0], args, options, cmdoptions)
1326
1329
1327 def dispatch(args):
1330 def dispatch(args):
1328 signal.signal(signal.SIGTERM, catchterm)
1331 signal.signal(signal.SIGTERM, catchterm)
1329 try:
1332 try:
1330 signal.signal(signal.SIGHUP, catchterm)
1333 signal.signal(signal.SIGHUP, catchterm)
1331 except AttributeError:
1334 except AttributeError:
1332 pass
1335 pass
1333
1336
1334 try:
1337 try:
1335 cmd, func, args, options, cmdoptions = parse(args)
1338 cmd, func, args, options, cmdoptions = parse(args)
1336 except ParseError, inst:
1339 except ParseError, inst:
1337 u = ui.ui()
1340 u = ui.ui()
1338 if inst.args[0]:
1341 if inst.args[0]:
1339 u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1]))
1342 u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1]))
1340 help_(u, inst.args[0])
1343 help_(u, inst.args[0])
1341 else:
1344 else:
1342 u.warn("hg: %s\n" % inst.args[1])
1345 u.warn("hg: %s\n" % inst.args[1])
1343 help_(u)
1346 help_(u)
1344 sys.exit(-1)
1347 sys.exit(-1)
1345 except UnknownCommand, inst:
1348 except UnknownCommand, inst:
1346 u = ui.ui()
1349 u = ui.ui()
1347 u.warn("hg: unknown command '%s'\n" % inst.args[0])
1350 u.warn("hg: unknown command '%s'\n" % inst.args[0])
1348 help_(u)
1351 help_(u)
1349 sys.exit(1)
1352 sys.exit(1)
1350
1353
1351 if options["time"]:
1354 if options["time"]:
1352 def get_times():
1355 def get_times():
1353 t = os.times()
1356 t = os.times()
1354 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
1357 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
1355 t = (t[0], t[1], t[2], t[3], time.clock())
1358 t = (t[0], t[1], t[2], t[3], time.clock())
1356 return t
1359 return t
1357 s = get_times()
1360 s = get_times()
1358 def print_time():
1361 def print_time():
1359 t = get_times()
1362 t = get_times()
1360 u = ui.ui()
1363 u = ui.ui()
1361 u.warn("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n" %
1364 u.warn("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n" %
1362 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
1365 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
1363 atexit.register(print_time)
1366 atexit.register(print_time)
1364
1367
1365 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
1368 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
1366 not options["noninteractive"])
1369 not options["noninteractive"])
1367
1370
1368 try:
1371 try:
1369 try:
1372 try:
1370 if cmd not in norepo.split():
1373 if cmd not in norepo.split():
1371 path = options["repository"] or ""
1374 path = options["repository"] or ""
1372 repo = hg.repository(ui=u, path=path)
1375 repo = hg.repository(ui=u, path=path)
1373 d = lambda: func(u, repo, *args, **cmdoptions)
1376 d = lambda: func(u, repo, *args, **cmdoptions)
1374 else:
1377 else:
1375 d = lambda: func(u, *args, **cmdoptions)
1378 d = lambda: func(u, *args, **cmdoptions)
1376
1379
1377 if options['profile']:
1380 if options['profile']:
1378 import hotshot, hotshot.stats
1381 import hotshot, hotshot.stats
1379 prof = hotshot.Profile("hg.prof")
1382 prof = hotshot.Profile("hg.prof")
1380 r = prof.runcall(d)
1383 r = prof.runcall(d)
1381 prof.close()
1384 prof.close()
1382 stats = hotshot.stats.load("hg.prof")
1385 stats = hotshot.stats.load("hg.prof")
1383 stats.strip_dirs()
1386 stats.strip_dirs()
1384 stats.sort_stats('time', 'calls')
1387 stats.sort_stats('time', 'calls')
1385 stats.print_stats(40)
1388 stats.print_stats(40)
1386 return r
1389 return r
1387 else:
1390 else:
1388 return d()
1391 return d()
1389 except:
1392 except:
1390 if options['traceback']:
1393 if options['traceback']:
1391 traceback.print_exc()
1394 traceback.print_exc()
1392 raise
1395 raise
1393 except util.CommandError, inst:
1396 except util.CommandError, inst:
1394 u.warn("abort: %s\n" % inst.args)
1397 u.warn("abort: %s\n" % inst.args)
1395 except hg.RepoError, inst:
1398 except hg.RepoError, inst:
1396 u.warn("abort: ", inst, "!\n")
1399 u.warn("abort: ", inst, "!\n")
1397 except SignalInterrupt:
1400 except SignalInterrupt:
1398 u.warn("killed!\n")
1401 u.warn("killed!\n")
1399 except KeyboardInterrupt:
1402 except KeyboardInterrupt:
1400 u.warn("interrupted!\n")
1403 u.warn("interrupted!\n")
1401 except IOError, inst:
1404 except IOError, inst:
1402 if hasattr(inst, "code"):
1405 if hasattr(inst, "code"):
1403 u.warn("abort: %s\n" % inst)
1406 u.warn("abort: %s\n" % inst)
1404 elif hasattr(inst, "reason"):
1407 elif hasattr(inst, "reason"):
1405 u.warn("abort: error: %s\n" % inst.reason[1])
1408 u.warn("abort: error: %s\n" % inst.reason[1])
1406 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
1409 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
1407 if u.debugflag: u.warn("broken pipe\n")
1410 if u.debugflag: u.warn("broken pipe\n")
1408 else:
1411 else:
1409 raise
1412 raise
1410 except OSError, inst:
1413 except OSError, inst:
1411 if hasattr(inst, "filename"):
1414 if hasattr(inst, "filename"):
1412 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
1415 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
1413 else:
1416 else:
1414 u.warn("abort: %s\n" % inst.strerror)
1417 u.warn("abort: %s\n" % inst.strerror)
1415 except Abort, inst:
1418 except Abort, inst:
1416 u.warn('abort: ', inst.args[0] % inst.args[1:], '\n')
1419 u.warn('abort: ', inst.args[0] % inst.args[1:], '\n')
1417 sys.exit(1)
1420 sys.exit(1)
1418 except TypeError, inst:
1421 except TypeError, inst:
1419 # was this an argument error?
1422 # was this an argument error?
1420 tb = traceback.extract_tb(sys.exc_info()[2])
1423 tb = traceback.extract_tb(sys.exc_info()[2])
1421 if len(tb) > 2: # no
1424 if len(tb) > 2: # no
1422 raise
1425 raise
1423 u.debug(inst, "\n")
1426 u.debug(inst, "\n")
1424 u.warn("%s: invalid arguments\n" % cmd)
1427 u.warn("%s: invalid arguments\n" % cmd)
1425 help_(u, cmd)
1428 help_(u, cmd)
1426
1429
1427 sys.exit(-1)
1430 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now