##// END OF EJS Templates
Restructure option handling...
mpm@selenic.com -
r592:74175ce8 default
parent child Browse files
Show More
@@ -1,1080 +1,1102 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, re, sys, signal
8 import os, re, sys, signal
9 import fancyopts, ui, hg, util
9 import fancyopts, ui, hg, util
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
12
12
13 class UnknownCommand(Exception): pass
13 class UnknownCommand(Exception): pass
14
14
15 def filterfiles(filters, files):
15 def filterfiles(filters, files):
16 l = [ x for x in files if x in filters ]
16 l = [ x for x in files if x in filters ]
17
17
18 for t in filters:
18 for t in filters:
19 if t and t[-1] != "/": t += "/"
19 if t and t[-1] != "/": t += "/"
20 l += [ x for x in files if x.startswith(t) ]
20 l += [ x for x in files if x.startswith(t) ]
21 return l
21 return l
22
22
23 def relfilter(repo, files):
23 def relfilter(repo, files):
24 if os.getcwd() != repo.root:
24 if os.getcwd() != repo.root:
25 p = os.getcwd()[len(repo.root) + 1: ]
25 p = os.getcwd()[len(repo.root) + 1: ]
26 return filterfiles([util.pconvert(p)], files)
26 return filterfiles([util.pconvert(p)], files)
27 return files
27 return files
28
28
29 def relpath(repo, args):
29 def relpath(repo, args):
30 if os.getcwd() != repo.root:
30 if os.getcwd() != repo.root:
31 p = os.getcwd()[len(repo.root) + 1: ]
31 p = os.getcwd()[len(repo.root) + 1: ]
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x)))
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x)))
33 for x in args ]
33 for x in args ]
34 return args
34 return args
35
35
36 revrangesep = ':'
36 revrangesep = ':'
37
37
38 def revrange(ui, repo, revs = [], revlog = None):
38 def revrange(ui, repo, revs = [], revlog = None):
39 if revlog is None:
39 if revlog is None:
40 revlog = repo.changelog
40 revlog = repo.changelog
41 revcount = revlog.count()
41 revcount = revlog.count()
42 def fix(val, defval):
42 def fix(val, defval):
43 if not val: return defval
43 if not val: return defval
44 try:
44 try:
45 num = int(val)
45 num = int(val)
46 if str(num) != val: raise ValueError
46 if str(num) != val: raise ValueError
47 if num < 0: num += revcount
47 if num < 0: num += revcount
48 if not (0 <= num < revcount):
48 if not (0 <= num < revcount):
49 raise ValueError
49 raise ValueError
50 except ValueError:
50 except ValueError:
51 try:
51 try:
52 num = repo.changelog.rev(repo.lookup(val))
52 num = repo.changelog.rev(repo.lookup(val))
53 except KeyError:
53 except KeyError:
54 try:
54 try:
55 num = revlog.rev(revlog.lookup(val))
55 num = revlog.rev(revlog.lookup(val))
56 except KeyError:
56 except KeyError:
57 ui.warn('abort: invalid revision identifier %s\n' % val)
57 ui.warn('abort: invalid revision identifier %s\n' % val)
58 sys.exit(1)
58 sys.exit(1)
59 return num
59 return num
60 for spec in revs:
60 for spec in revs:
61 if spec.find(revrangesep) >= 0:
61 if spec.find(revrangesep) >= 0:
62 start, end = spec.split(revrangesep, 1)
62 start, end = spec.split(revrangesep, 1)
63 start = fix(start, 0)
63 start = fix(start, 0)
64 end = fix(end, revcount - 1)
64 end = fix(end, revcount - 1)
65 if end > start:
65 if end > start:
66 end += 1
66 end += 1
67 step = 1
67 step = 1
68 else:
68 else:
69 end -= 1
69 end -= 1
70 step = -1
70 step = -1
71 for rev in xrange(start, end, step):
71 for rev in xrange(start, end, step):
72 yield str(rev)
72 yield str(rev)
73 else:
73 else:
74 yield spec
74 yield spec
75
75
76 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None):
76 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None):
77 def date(c):
77 def date(c):
78 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
78 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
79
79
80 (c, a, d, u) = repo.changes(node1, node2, files)
80 (c, a, d, u) = repo.changes(node1, node2, files)
81 if files:
81 if files:
82 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
82 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
83
83
84 if not c and not a and not d:
84 if not c and not a and not d:
85 return
85 return
86
86
87 if node2:
87 if node2:
88 change = repo.changelog.read(node2)
88 change = repo.changelog.read(node2)
89 mmap2 = repo.manifest.read(change[0])
89 mmap2 = repo.manifest.read(change[0])
90 def read(f): return repo.file(f).read(mmap2[f])
90 def read(f): return repo.file(f).read(mmap2[f])
91 date2 = date(change)
91 date2 = date(change)
92 else:
92 else:
93 date2 = time.asctime()
93 date2 = time.asctime()
94 if not node1:
94 if not node1:
95 node1 = repo.dirstate.parents()[0]
95 node1 = repo.dirstate.parents()[0]
96 def read(f): return repo.wfile(f).read()
96 def read(f): return repo.wfile(f).read()
97
97
98 if ui.quiet:
98 if ui.quiet:
99 r = None
99 r = None
100 else:
100 else:
101 hexfunc = ui.verbose and hg.hex or hg.short
101 hexfunc = ui.verbose and hg.hex or hg.short
102 r = [hexfunc(node) for node in [node1, node2] if node]
102 r = [hexfunc(node) for node in [node1, node2] if node]
103
103
104 change = repo.changelog.read(node1)
104 change = repo.changelog.read(node1)
105 mmap = repo.manifest.read(change[0])
105 mmap = repo.manifest.read(change[0])
106 date1 = date(change)
106 date1 = date(change)
107
107
108 for f in c:
108 for f in c:
109 to = None
109 to = None
110 if f in mmap:
110 if f in mmap:
111 to = repo.file(f).read(mmap[f])
111 to = repo.file(f).read(mmap[f])
112 tn = read(f)
112 tn = read(f)
113 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
113 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
114 for f in a:
114 for f in a:
115 to = None
115 to = None
116 tn = read(f)
116 tn = read(f)
117 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
117 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
118 for f in d:
118 for f in d:
119 to = repo.file(f).read(mmap[f])
119 to = repo.file(f).read(mmap[f])
120 tn = None
120 tn = None
121 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
121 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
122
122
123 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
123 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
124 """show a single changeset or file revision"""
124 """show a single changeset or file revision"""
125 changelog = repo.changelog
125 changelog = repo.changelog
126 if filelog:
126 if filelog:
127 log = filelog
127 log = filelog
128 filerev = rev
128 filerev = rev
129 node = filenode = filelog.node(filerev)
129 node = filenode = filelog.node(filerev)
130 changerev = filelog.linkrev(filenode)
130 changerev = filelog.linkrev(filenode)
131 changenode = changenode or changelog.node(changerev)
131 changenode = changenode or changelog.node(changerev)
132 else:
132 else:
133 log = changelog
133 log = changelog
134 changerev = rev
134 changerev = rev
135 if changenode is None:
135 if changenode is None:
136 changenode = changelog.node(changerev)
136 changenode = changelog.node(changerev)
137 elif not changerev:
137 elif not changerev:
138 rev = changerev = changelog.rev(changenode)
138 rev = changerev = changelog.rev(changenode)
139 node = changenode
139 node = changenode
140
140
141 if ui.quiet:
141 if ui.quiet:
142 ui.write("%d:%s\n" % (rev, hg.hex(node)))
142 ui.write("%d:%s\n" % (rev, hg.hex(node)))
143 return
143 return
144
144
145 changes = changelog.read(changenode)
145 changes = changelog.read(changenode)
146
146
147 parents = [(log.rev(parent), hg.hex(parent))
147 parents = [(log.rev(parent), hg.hex(parent))
148 for parent in log.parents(node)
148 for parent in log.parents(node)
149 if ui.debugflag or parent != hg.nullid]
149 if ui.debugflag or parent != hg.nullid]
150 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
150 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
151 parents = []
151 parents = []
152
152
153 if filelog:
153 if filelog:
154 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
154 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
155 for parent in parents:
155 for parent in parents:
156 ui.write("parent: %d:%s\n" % parent)
156 ui.write("parent: %d:%s\n" % parent)
157 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
157 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
158 else:
158 else:
159 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
159 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
160 for tag in repo.nodetags(changenode):
160 for tag in repo.nodetags(changenode):
161 ui.status("tag: %s\n" % tag)
161 ui.status("tag: %s\n" % tag)
162 for parent in parents:
162 for parent in parents:
163 ui.write("parent: %d:%s\n" % parent)
163 ui.write("parent: %d:%s\n" % parent)
164 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
164 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
165 hg.hex(changes[0])))
165 hg.hex(changes[0])))
166 ui.status("user: %s\n" % changes[1])
166 ui.status("user: %s\n" % changes[1])
167 ui.status("date: %s\n" % time.asctime(
167 ui.status("date: %s\n" % time.asctime(
168 time.localtime(float(changes[2].split(' ')[0]))))
168 time.localtime(float(changes[2].split(' ')[0]))))
169 if ui.debugflag:
169 if ui.debugflag:
170 files = repo.changes(changelog.parents(changenode)[0], changenode)
170 files = repo.changes(changelog.parents(changenode)[0], changenode)
171 for key, value in zip(["files:", "files+:", "files-:"], files):
171 for key, value in zip(["files:", "files+:", "files-:"], files):
172 if value:
172 if value:
173 ui.note("%-12s %s\n" % (key, " ".join(value)))
173 ui.note("%-12s %s\n" % (key, " ".join(value)))
174 else:
174 else:
175 ui.note("files: %s\n" % " ".join(changes[3]))
175 ui.note("files: %s\n" % " ".join(changes[3]))
176 description = changes[4].strip()
176 description = changes[4].strip()
177 if description:
177 if description:
178 if ui.verbose:
178 if ui.verbose:
179 ui.status("description:\n")
179 ui.status("description:\n")
180 ui.status(description)
180 ui.status(description)
181 ui.status("\n\n")
181 ui.status("\n\n")
182 else:
182 else:
183 ui.status("summary: %s\n" % description.splitlines()[0])
183 ui.status("summary: %s\n" % description.splitlines()[0])
184 ui.status("\n")
184 ui.status("\n")
185
185
186 def show_version(ui):
186 def show_version(ui):
187 """output version and copyright information"""
187 """output version and copyright information"""
188 ui.write("Mercurial version %s\n" % version.get_version())
188 ui.write("Mercurial version %s\n" % version.get_version())
189 ui.status(
189 ui.status(
190 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
190 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
191 "This is free software; see the source for copying conditions. "
191 "This is free software; see the source for copying conditions. "
192 "There is NO\nwarranty; "
192 "There is NO\nwarranty; "
193 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
193 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
194 )
194 )
195
195
196 def help(ui, cmd=None):
196 def help(ui, cmd=None):
197 '''show help for a given command or all commands'''
197 '''show help for a given command or all commands'''
198 if cmd:
198 if cmd:
199 try:
199 try:
200 i = find(cmd)
200 i = find(cmd)
201 ui.write("%s\n\n" % i[2])
201 ui.write("%s\n\n" % i[2])
202
202
203 if i[1]:
203 if i[1]:
204 for s, l, d, c in i[1]:
204 for s, l, d, c in i[1]:
205 opt=' '
205 opt=' '
206 if s: opt = opt + '-' + s + ' '
206 if s: opt = opt + '-' + s + ' '
207 if l: opt = opt + '--' + l + ' '
207 if l: opt = opt + '--' + l + ' '
208 if d: opt = opt + '(' + str(d) + ')'
208 if d: opt = opt + '(' + str(d) + ')'
209 ui.write(opt, "\n")
209 ui.write(opt, "\n")
210 if c: ui.write(' %s\n' % c)
210 if c: ui.write(' %s\n' % c)
211 ui.write("\n")
211 ui.write("\n")
212
212
213 ui.write(i[0].__doc__, "\n")
213 ui.write(i[0].__doc__, "\n")
214 except UnknownCommand:
214 except UnknownCommand:
215 ui.warn("hg: unknown command %s\n" % cmd)
215 ui.warn("hg: unknown command %s\n" % cmd)
216 sys.exit(0)
216 sys.exit(0)
217 else:
217 else:
218 if not ui.quiet:
218 if not ui.quiet:
219 show_version(ui)
219 show_version(ui)
220 ui.write('\n')
220 ui.write('\n')
221 ui.write('hg commands:\n\n')
221 ui.write('hg commands:\n\n')
222
222
223 h = {}
223 h = {}
224 for c, e in table.items():
224 for c, e in table.items():
225 f = c.split("|")[0]
225 f = c.split("|")[0]
226 if f.startswith("debug"):
226 if f.startswith("debug"):
227 continue
227 continue
228 d = ""
228 d = ""
229 if e[0].__doc__:
229 if e[0].__doc__:
230 d = e[0].__doc__.splitlines(0)[0].rstrip()
230 d = e[0].__doc__.splitlines(0)[0].rstrip()
231 h[f] = d
231 h[f] = d
232
232
233 fns = h.keys()
233 fns = h.keys()
234 fns.sort()
234 fns.sort()
235 m = max(map(len, fns))
235 m = max(map(len, fns))
236 for f in fns:
236 for f in fns:
237 ui.write(' %-*s %s\n' % (m, f, h[f]))
237 ui.write(' %-*s %s\n' % (m, f, h[f]))
238
238
239 # Commands start here, listed alphabetically
239 # Commands start here, listed alphabetically
240
240
241 def add(ui, repo, file, *files):
241 def add(ui, repo, file, *files):
242 '''add the specified files on the next commit'''
242 '''add the specified files on the next commit'''
243 repo.add(relpath(repo, (file,) + files))
243 repo.add(relpath(repo, (file,) + files))
244
244
245 def addremove(ui, repo, *files):
245 def addremove(ui, repo, *files):
246 """add all new files, delete all missing files"""
246 """add all new files, delete all missing files"""
247 if files:
247 if files:
248 files = relpath(repo, files)
248 files = relpath(repo, files)
249 d = []
249 d = []
250 u = []
250 u = []
251 for f in files:
251 for f in files:
252 p = repo.wjoin(f)
252 p = repo.wjoin(f)
253 s = repo.dirstate.state(f)
253 s = repo.dirstate.state(f)
254 isfile = os.path.isfile(p)
254 isfile = os.path.isfile(p)
255 if s != 'r' and not isfile:
255 if s != 'r' and not isfile:
256 d.append(f)
256 d.append(f)
257 elif s not in 'nmai' and isfile:
257 elif s not in 'nmai' and isfile:
258 u.append(f)
258 u.append(f)
259 else:
259 else:
260 (c, a, d, u) = repo.changes(None, None)
260 (c, a, d, u) = repo.changes(None, None)
261 repo.add(u)
261 repo.add(u)
262 repo.remove(d)
262 repo.remove(d)
263
263
264 def annotate(u, repo, file, *files, **ops):
264 def annotate(u, repo, file, *files, **ops):
265 """show changeset information per file line"""
265 """show changeset information per file line"""
266 def getnode(rev):
266 def getnode(rev):
267 return hg.short(repo.changelog.node(rev))
267 return hg.short(repo.changelog.node(rev))
268
268
269 def getname(rev):
269 def getname(rev):
270 try:
270 try:
271 return bcache[rev]
271 return bcache[rev]
272 except KeyError:
272 except KeyError:
273 cl = repo.changelog.read(repo.changelog.node(rev))
273 cl = repo.changelog.read(repo.changelog.node(rev))
274 name = cl[1]
274 name = cl[1]
275 f = name.find('@')
275 f = name.find('@')
276 if f >= 0:
276 if f >= 0:
277 name = name[:f]
277 name = name[:f]
278 f = name.find('<')
278 f = name.find('<')
279 if f >= 0:
279 if f >= 0:
280 name = name[f+1:]
280 name = name[f+1:]
281 bcache[rev] = name
281 bcache[rev] = name
282 return name
282 return name
283
283
284 bcache = {}
284 bcache = {}
285 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
285 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
286 if not ops['user'] and not ops['changeset']:
286 if not ops['user'] and not ops['changeset']:
287 ops['number'] = 1
287 ops['number'] = 1
288
288
289 node = repo.dirstate.parents()[0]
289 node = repo.dirstate.parents()[0]
290 if ops['revision']:
290 if ops['revision']:
291 node = repo.changelog.lookup(ops['revision'])
291 node = repo.changelog.lookup(ops['revision'])
292 change = repo.changelog.read(node)
292 change = repo.changelog.read(node)
293 mmap = repo.manifest.read(change[0])
293 mmap = repo.manifest.read(change[0])
294 for f in relpath(repo, (file,) + files):
294 for f in relpath(repo, (file,) + files):
295 lines = repo.file(f).annotate(mmap[f])
295 lines = repo.file(f).annotate(mmap[f])
296 pieces = []
296 pieces = []
297
297
298 for o, f in opmap:
298 for o, f in opmap:
299 if ops[o]:
299 if ops[o]:
300 l = [ f(n) for n,t in lines ]
300 l = [ f(n) for n,t in lines ]
301 m = max(map(len, l))
301 m = max(map(len, l))
302 pieces.append([ "%*s" % (m, x) for x in l])
302 pieces.append([ "%*s" % (m, x) for x in l])
303
303
304 for p,l in zip(zip(*pieces), lines):
304 for p,l in zip(zip(*pieces), lines):
305 u.write(" ".join(p) + ": " + l[1])
305 u.write(" ".join(p) + ": " + l[1])
306
306
307 def cat(ui, repo, file, rev = []):
307 def cat(ui, repo, file, rev = []):
308 """output the latest or given revision of a file"""
308 """output the latest or given revision of a file"""
309 r = repo.file(relpath(repo, [file])[0])
309 r = repo.file(relpath(repo, [file])[0])
310 n = r.tip()
310 n = r.tip()
311 if rev: n = r.lookup(rev)
311 if rev: n = r.lookup(rev)
312 sys.stdout.write(r.read(n))
312 sys.stdout.write(r.read(n))
313
313
314 def clone(ui, source, dest = None, **opts):
314 def clone(ui, source, dest = None, **opts):
315 """make a copy of an existing repository"""
315 """make a copy of an existing repository"""
316 source = ui.expandpath(source)
316 source = ui.expandpath(source)
317
317
318 if dest is None:
318 if dest is None:
319 dest = os.path.basename(os.path.normpath(source))
319 dest = os.path.basename(os.path.normpath(source))
320
320
321 if os.path.exists(dest):
321 if os.path.exists(dest):
322 ui.warn("abort: destination '%s' already exists\n" % dest)
322 ui.warn("abort: destination '%s' already exists\n" % dest)
323 return 1
323 return 1
324
324
325 class dircleanup:
325 class dircleanup:
326 def __init__(self, dir):
326 def __init__(self, dir):
327 self.dir = dir
327 self.dir = dir
328 os.mkdir(dir)
328 os.mkdir(dir)
329 def close(self):
329 def close(self):
330 self.dir = None
330 self.dir = None
331 def __del__(self):
331 def __del__(self):
332 if self.dir:
332 if self.dir:
333 import shutil
333 import shutil
334 shutil.rmtree(self.dir, True)
334 shutil.rmtree(self.dir, True)
335
335
336 d = dircleanup(dest)
336 d = dircleanup(dest)
337
337
338 link = 0
338 link = 0
339 abspath = source
339 abspath = source
340 if not (source.startswith("http://") or
340 if not (source.startswith("http://") or
341 source.startswith("hg://") or
341 source.startswith("hg://") or
342 source.startswith("old-http://")):
342 source.startswith("old-http://")):
343 abspath = os.path.abspath(source)
343 abspath = os.path.abspath(source)
344 d1 = os.stat(dest).st_dev
344 d1 = os.stat(dest).st_dev
345 d2 = os.stat(source).st_dev
345 d2 = os.stat(source).st_dev
346 if d1 == d2: link = 1
346 if d1 == d2: link = 1
347
347
348 if link:
348 if link:
349 ui.note("copying by hardlink\n")
349 ui.note("copying by hardlink\n")
350 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest))
350 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest))
351 try:
351 try:
352 os.remove(os.path.join(dest, ".hg", "dirstate"))
352 os.remove(os.path.join(dest, ".hg", "dirstate"))
353 except: pass
353 except: pass
354
354
355 repo = hg.repository(ui, dest)
355 repo = hg.repository(ui, dest)
356
356
357 else:
357 else:
358 repo = hg.repository(ui, dest, create=1)
358 repo = hg.repository(ui, dest, create=1)
359 other = hg.repository(ui, source)
359 other = hg.repository(ui, source)
360 fetch = repo.findincoming(other)
360 fetch = repo.findincoming(other)
361 if fetch:
361 if fetch:
362 cg = other.changegroup(fetch)
362 cg = other.changegroup(fetch)
363 repo.addchangegroup(cg)
363 repo.addchangegroup(cg)
364
364
365 f = repo.opener("hgrc", "w")
365 f = repo.opener("hgrc", "w")
366 f.write("[paths]\n")
366 f.write("[paths]\n")
367 f.write("default = %s\n" % abspath)
367 f.write("default = %s\n" % abspath)
368
368
369 if not opts['noupdate']:
369 if not opts['noupdate']:
370 update(ui, repo)
370 update(ui, repo)
371
371
372 d.close()
372 d.close()
373
373
374 def commit(ui, repo, *files, **opts):
374 def commit(ui, repo, *files, **opts):
375 """commit the specified files or all outstanding changes"""
375 """commit the specified files or all outstanding changes"""
376 text = opts['text']
376 text = opts['text']
377 if not text and opts['logfile']:
377 if not text and opts['logfile']:
378 try: text = open(opts['logfile']).read()
378 try: text = open(opts['logfile']).read()
379 except IOError: pass
379 except IOError: pass
380
380
381 if opts['addremove']:
381 if opts['addremove']:
382 addremove(ui, repo, *files)
382 addremove(ui, repo, *files)
383 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
383 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
384
384
385 def copy(ui, repo, source, dest):
385 def copy(ui, repo, source, dest):
386 """mark a file as copied or renamed for the next commit"""
386 """mark a file as copied or renamed for the next commit"""
387 return repo.copy(*relpath(repo, (source, dest)))
387 return repo.copy(*relpath(repo, (source, dest)))
388
388
389 def debugcheckdirstate(ui, repo):
389 def debugcheckdirstate(ui, repo):
390 parent1, parent2 = repo.dirstate.parents()
390 parent1, parent2 = repo.dirstate.parents()
391 repo.dirstate.read()
391 repo.dirstate.read()
392 dc = repo.dirstate.map
392 dc = repo.dirstate.map
393 keys = dc.keys()
393 keys = dc.keys()
394 keys.sort()
394 keys.sort()
395 m1n = repo.changelog.read(parent1)[0]
395 m1n = repo.changelog.read(parent1)[0]
396 m2n = repo.changelog.read(parent2)[0]
396 m2n = repo.changelog.read(parent2)[0]
397 m1 = repo.manifest.read(m1n)
397 m1 = repo.manifest.read(m1n)
398 m2 = repo.manifest.read(m2n)
398 m2 = repo.manifest.read(m2n)
399 errors = 0
399 errors = 0
400 for f in dc:
400 for f in dc:
401 state = repo.dirstate.state(f)
401 state = repo.dirstate.state(f)
402 if state in "nr" and f not in m1:
402 if state in "nr" and f not in m1:
403 ui.warn("%s in state %s, but not in manifest1\n" % (f, state))
403 ui.warn("%s in state %s, but not in manifest1\n" % (f, state))
404 errors += 1
404 errors += 1
405 if state in "a" and f in m1:
405 if state in "a" and f in m1:
406 ui.warn("%s in state %s, but also in manifest1\n" % (f, state))
406 ui.warn("%s in state %s, but also in manifest1\n" % (f, state))
407 errors += 1
407 errors += 1
408 if state in "m" and f not in m1 and f not in m2:
408 if state in "m" and f not in m1 and f not in m2:
409 ui.warn("%s in state %s, but not in either manifest\n" %
409 ui.warn("%s in state %s, but not in either manifest\n" %
410 (f, state))
410 (f, state))
411 errors += 1
411 errors += 1
412 for f in m1:
412 for f in m1:
413 state = repo.dirstate.state(f)
413 state = repo.dirstate.state(f)
414 if state not in "nrm":
414 if state not in "nrm":
415 ui.warn("%s in manifest1, but listed as state %s" % (f, state))
415 ui.warn("%s in manifest1, but listed as state %s" % (f, state))
416 errors += 1
416 errors += 1
417 if errors:
417 if errors:
418 ui.warn(".hg/dirstate inconsistent with current parent's manifest\n")
418 ui.warn(".hg/dirstate inconsistent with current parent's manifest\n")
419 sys.exit(1)
419 sys.exit(1)
420
420
421 def debugdumpdirstate(ui, repo):
421 def debugdumpdirstate(ui, repo):
422 repo.dirstate.read()
422 repo.dirstate.read()
423 dc = repo.dirstate.map
423 dc = repo.dirstate.map
424 keys = dc.keys()
424 keys = dc.keys()
425 keys.sort()
425 keys.sort()
426 for file in keys:
426 for file in keys:
427 ui.write("%c %s\n" % (dc[file][0], file))
427 ui.write("%c %s\n" % (dc[file][0], file))
428
428
429 def debugindex(ui, file):
429 def debugindex(ui, file):
430 r = hg.revlog(hg.opener(""), file, "")
430 r = hg.revlog(hg.opener(""), file, "")
431 ui.write(" rev offset length base linkrev" +
431 ui.write(" rev offset length base linkrev" +
432 " p1 p2 nodeid\n")
432 " p1 p2 nodeid\n")
433 for i in range(r.count()):
433 for i in range(r.count()):
434 e = r.index[i]
434 e = r.index[i]
435 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
435 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
436 i, e[0], e[1], e[2], e[3],
436 i, e[0], e[1], e[2], e[3],
437 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
437 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
438
438
439 def debugindexdot(ui, file):
439 def debugindexdot(ui, file):
440 r = hg.revlog(hg.opener(""), file, "")
440 r = hg.revlog(hg.opener(""), file, "")
441 ui.write("digraph G {\n")
441 ui.write("digraph G {\n")
442 for i in range(r.count()):
442 for i in range(r.count()):
443 e = r.index[i]
443 e = r.index[i]
444 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
444 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
445 if e[5] != hg.nullid:
445 if e[5] != hg.nullid:
446 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
446 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
447 ui.write("}\n")
447 ui.write("}\n")
448
448
449 def diff(ui, repo, *files, **opts):
449 def diff(ui, repo, *files, **opts):
450 """diff working directory (or selected files)"""
450 """diff working directory (or selected files)"""
451 revs = []
451 revs = []
452 if opts['rev']:
452 if opts['rev']:
453 revs = map(lambda x: repo.lookup(x), opts['rev'])
453 revs = map(lambda x: repo.lookup(x), opts['rev'])
454
454
455 if len(revs) > 2:
455 if len(revs) > 2:
456 ui.warn("too many revisions to diff\n")
456 ui.warn("too many revisions to diff\n")
457 sys.exit(1)
457 sys.exit(1)
458
458
459 if files:
459 if files:
460 files = relpath(repo, files)
460 files = relpath(repo, files)
461 else:
461 else:
462 files = relpath(repo, [""])
462 files = relpath(repo, [""])
463
463
464 dodiff(sys.stdout, ui, repo, files, *revs)
464 dodiff(sys.stdout, ui, repo, files, *revs)
465
465
466 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
466 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
467 node = repo.lookup(changeset)
467 node = repo.lookup(changeset)
468 prev, other = repo.changelog.parents(node)
468 prev, other = repo.changelog.parents(node)
469 change = repo.changelog.read(node)
469 change = repo.changelog.read(node)
470
470
471 def expand(name):
471 def expand(name):
472 expansions = {
472 expansions = {
473 '%': lambda: '%',
473 '%': lambda: '%',
474 'H': lambda: hg.hex(node),
474 'H': lambda: hg.hex(node),
475 'N': lambda: str(total),
475 'N': lambda: str(total),
476 'R': lambda: str(repo.changelog.rev(node)),
476 'R': lambda: str(repo.changelog.rev(node)),
477 'b': lambda: os.path.basename(repo.root),
477 'b': lambda: os.path.basename(repo.root),
478 'h': lambda: hg.short(node),
478 'h': lambda: hg.short(node),
479 'n': lambda: str(seqno).zfill(len(str(total))),
479 'n': lambda: str(seqno).zfill(len(str(total))),
480 'r': lambda: str(repo.changelog.rev(node)).zfill(revwidth),
480 'r': lambda: str(repo.changelog.rev(node)).zfill(revwidth),
481 }
481 }
482 newname = []
482 newname = []
483 namelen = len(name)
483 namelen = len(name)
484 i = 0
484 i = 0
485 while i < namelen:
485 while i < namelen:
486 c = name[i]
486 c = name[i]
487 if c == '%':
487 if c == '%':
488 i += 1
488 i += 1
489 c = name[i]
489 c = name[i]
490 c = expansions[c]()
490 c = expansions[c]()
491 newname.append(c)
491 newname.append(c)
492 i += 1
492 i += 1
493 return ''.join(newname)
493 return ''.join(newname)
494
494
495 if opts['output'] and opts['output'] != '-':
495 if opts['output'] and opts['output'] != '-':
496 try:
496 try:
497 fp = open(expand(opts['output']), 'w')
497 fp = open(expand(opts['output']), 'w')
498 except KeyError, inst:
498 except KeyError, inst:
499 ui.warn("error: invalid format spec '%%%s' in output file name\n" %
499 ui.warn("error: invalid format spec '%%%s' in output file name\n" %
500 inst.args[0])
500 inst.args[0])
501 sys.exit(1)
501 sys.exit(1)
502 else:
502 else:
503 fp = sys.stdout
503 fp = sys.stdout
504
504
505 fp.write("# HG changeset patch\n")
505 fp.write("# HG changeset patch\n")
506 fp.write("# User %s\n" % change[1])
506 fp.write("# User %s\n" % change[1])
507 fp.write("# Node ID %s\n" % hg.hex(node))
507 fp.write("# Node ID %s\n" % hg.hex(node))
508 fp.write("# Parent %s\n" % hg.hex(prev))
508 fp.write("# Parent %s\n" % hg.hex(prev))
509 if other != hg.nullid:
509 if other != hg.nullid:
510 fp.write("# Parent %s\n" % hg.hex(other))
510 fp.write("# Parent %s\n" % hg.hex(other))
511 fp.write(change[4].rstrip())
511 fp.write(change[4].rstrip())
512 fp.write("\n\n")
512 fp.write("\n\n")
513
513
514 dodiff(fp, ui, repo, None, prev, node)
514 dodiff(fp, ui, repo, None, prev, node)
515
515
516 def export(ui, repo, *changesets, **opts):
516 def export(ui, repo, *changesets, **opts):
517 """dump the header and diffs for one or more changesets"""
517 """dump the header and diffs for one or more changesets"""
518 seqno = 0
518 seqno = 0
519 revs = list(revrange(ui, repo, changesets))
519 revs = list(revrange(ui, repo, changesets))
520 total = len(revs)
520 total = len(revs)
521 revwidth = max(len(revs[0]), len(revs[-1]))
521 revwidth = max(len(revs[0]), len(revs[-1]))
522 for cset in revs:
522 for cset in revs:
523 seqno += 1
523 seqno += 1
524 doexport(ui, repo, cset, seqno, total, revwidth, opts)
524 doexport(ui, repo, cset, seqno, total, revwidth, opts)
525
525
526 def forget(ui, repo, file, *files):
526 def forget(ui, repo, file, *files):
527 """don't add the specified files on the next commit"""
527 """don't add the specified files on the next commit"""
528 repo.forget(relpath(repo, (file,) + files))
528 repo.forget(relpath(repo, (file,) + files))
529
529
530 def heads(ui, repo):
530 def heads(ui, repo):
531 """show current repository heads"""
531 """show current repository heads"""
532 for n in repo.changelog.heads():
532 for n in repo.changelog.heads():
533 show_changeset(ui, repo, changenode=n)
533 show_changeset(ui, repo, changenode=n)
534
534
535 def identify(ui, repo):
535 def identify(ui, repo):
536 """print information about the working copy"""
536 """print information about the working copy"""
537 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
537 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
538 if not parents:
538 if not parents:
539 ui.write("unknown\n")
539 ui.write("unknown\n")
540 return
540 return
541
541
542 hexfunc = ui.verbose and hg.hex or hg.short
542 hexfunc = ui.verbose and hg.hex or hg.short
543 (c, a, d, u) = repo.changes(None, None)
543 (c, a, d, u) = repo.changes(None, None)
544 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
544 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
545 (c or a or d) and "+" or "")]
545 (c or a or d) and "+" or "")]
546
546
547 if not ui.quiet:
547 if not ui.quiet:
548 # multiple tags for a single parent separated by '/'
548 # multiple tags for a single parent separated by '/'
549 parenttags = ['/'.join(tags)
549 parenttags = ['/'.join(tags)
550 for tags in map(repo.nodetags, parents) if tags]
550 for tags in map(repo.nodetags, parents) if tags]
551 # tags for multiple parents separated by ' + '
551 # tags for multiple parents separated by ' + '
552 output.append(' + '.join(parenttags))
552 output.append(' + '.join(parenttags))
553
553
554 ui.write("%s\n" % ' '.join(output))
554 ui.write("%s\n" % ' '.join(output))
555
555
556 def import_(ui, repo, patch1, *patches, **opts):
556 def import_(ui, repo, patch1, *patches, **opts):
557 """import an ordered set of patches"""
557 """import an ordered set of patches"""
558 try:
558 try:
559 import psyco
559 import psyco
560 psyco.full()
560 psyco.full()
561 except:
561 except:
562 pass
562 pass
563
563
564 patches = (patch1,) + patches
564 patches = (patch1,) + patches
565
565
566 d = opts["base"]
566 d = opts["base"]
567 strip = opts["strip"]
567 strip = opts["strip"]
568
568
569 for patch in patches:
569 for patch in patches:
570 ui.status("applying %s\n" % patch)
570 ui.status("applying %s\n" % patch)
571 pf = os.path.join(d, patch)
571 pf = os.path.join(d, patch)
572
572
573 text = ""
573 text = ""
574 for l in file(pf):
574 for l in file(pf):
575 if l[:4] == "--- ": break
575 if l[:4] == "--- ": break
576 text += l
576 text += l
577
577
578 # make sure text isn't empty
578 # make sure text isn't empty
579 if not text: text = "imported patch %s\n" % patch
579 if not text: text = "imported patch %s\n" % patch
580
580
581 f = os.popen("patch -p%d < %s" % (strip, pf))
581 f = os.popen("patch -p%d < %s" % (strip, pf))
582 files = []
582 files = []
583 for l in f.read().splitlines():
583 for l in f.read().splitlines():
584 l.rstrip('\r\n');
584 l.rstrip('\r\n');
585 ui.status("%s\n" % l)
585 ui.status("%s\n" % l)
586 if l[:14] == 'patching file ':
586 if l[:14] == 'patching file ':
587 pf = l[14:]
587 pf = l[14:]
588 if pf not in files:
588 if pf not in files:
589 files.append(pf)
589 files.append(pf)
590 patcherr = f.close()
590 patcherr = f.close()
591 if patcherr:
591 if patcherr:
592 sys.stderr.write("patch failed")
592 sys.stderr.write("patch failed")
593 sys.exit(1)
593 sys.exit(1)
594
594
595 if len(files) > 0:
595 if len(files) > 0:
596 addremove(ui, repo, *files)
596 addremove(ui, repo, *files)
597 repo.commit(files, text)
597 repo.commit(files, text)
598
598
599 def init(ui, source=None):
599 def init(ui, source=None):
600 """create a new repository in the current directory"""
600 """create a new repository in the current directory"""
601
601
602 if source:
602 if source:
603 ui.warn("no longer supported: use \"hg clone\" instead\n")
603 ui.warn("no longer supported: use \"hg clone\" instead\n")
604 sys.exit(1)
604 sys.exit(1)
605 repo = hg.repository(ui, ".", create=1)
605 repo = hg.repository(ui, ".", create=1)
606
606
607 def log(ui, repo, f=None, **opts):
607 def log(ui, repo, f=None, **opts):
608 """show the revision history of the repository or a single file"""
608 """show the revision history of the repository or a single file"""
609 if f:
609 if f:
610 filelog = repo.file(relpath(repo, [f])[0])
610 filelog = repo.file(relpath(repo, [f])[0])
611 log = filelog
611 log = filelog
612 lookup = filelog.lookup
612 lookup = filelog.lookup
613 else:
613 else:
614 filelog = None
614 filelog = None
615 log = repo.changelog
615 log = repo.changelog
616 lookup = repo.lookup
616 lookup = repo.lookup
617 revlist = []
617 revlist = []
618 revs = [log.rev(lookup(rev)) for rev in opts['rev']]
618 revs = [log.rev(lookup(rev)) for rev in opts['rev']]
619 while revs:
619 while revs:
620 if len(revs) == 1:
620 if len(revs) == 1:
621 revlist.append(revs.pop(0))
621 revlist.append(revs.pop(0))
622 else:
622 else:
623 a = revs.pop(0)
623 a = revs.pop(0)
624 b = revs.pop(0)
624 b = revs.pop(0)
625 off = a > b and -1 or 1
625 off = a > b and -1 or 1
626 revlist.extend(range(a, b + off, off))
626 revlist.extend(range(a, b + off, off))
627 for i in revlist or range(log.count() - 1, -1, -1):
627 for i in revlist or range(log.count() - 1, -1, -1):
628 show_changeset(ui, repo, filelog=filelog, rev=i)
628 show_changeset(ui, repo, filelog=filelog, rev=i)
629
629
630 def manifest(ui, repo, rev = []):
630 def manifest(ui, repo, rev = []):
631 """output the latest or given revision of the project manifest"""
631 """output the latest or given revision of the project manifest"""
632 n = repo.manifest.tip()
632 n = repo.manifest.tip()
633 if rev:
633 if rev:
634 n = repo.manifest.lookup(rev)
634 n = repo.manifest.lookup(rev)
635 m = repo.manifest.read(n)
635 m = repo.manifest.read(n)
636 mf = repo.manifest.readflags(n)
636 mf = repo.manifest.readflags(n)
637 files = m.keys()
637 files = m.keys()
638 files.sort()
638 files.sort()
639
639
640 for f in files:
640 for f in files:
641 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
641 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
642
642
643 def parents(ui, repo, node = None):
643 def parents(ui, repo, node = None):
644 '''show the parents of the current working dir'''
644 '''show the parents of the current working dir'''
645 if node:
645 if node:
646 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
646 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
647 else:
647 else:
648 p = repo.dirstate.parents()
648 p = repo.dirstate.parents()
649
649
650 for n in p:
650 for n in p:
651 if n != hg.nullid:
651 if n != hg.nullid:
652 show_changeset(ui, repo, changenode=n)
652 show_changeset(ui, repo, changenode=n)
653
653
654 def pull(ui, repo, source="default", **opts):
654 def pull(ui, repo, source="default", **opts):
655 """pull changes from the specified source"""
655 """pull changes from the specified source"""
656 source = ui.expandpath(source)
656 source = ui.expandpath(source)
657
657
658 ui.status('pulling from %s\n' % (source))
658 ui.status('pulling from %s\n' % (source))
659
659
660 other = hg.repository(ui, source)
660 other = hg.repository(ui, source)
661 fetch = repo.findincoming(other)
661 fetch = repo.findincoming(other)
662 if not fetch:
662 if not fetch:
663 ui.status("no changes found\n")
663 ui.status("no changes found\n")
664 return
664 return
665
665
666 cg = other.changegroup(fetch)
666 cg = other.changegroup(fetch)
667 r = repo.addchangegroup(cg)
667 r = repo.addchangegroup(cg)
668 if cg and not r:
668 if cg and not r:
669 if opts['update']:
669 if opts['update']:
670 return update(ui, repo)
670 return update(ui, repo)
671 else:
671 else:
672 ui.status("(run 'hg update' to get a working copy)\n")
672 ui.status("(run 'hg update' to get a working copy)\n")
673
673
674 return r
674 return r
675
675
676 def push(ui, repo, dest="default-push"):
676 def push(ui, repo, dest="default-push"):
677 """push changes to the specified destination"""
677 """push changes to the specified destination"""
678 dest = ui.expandpath(dest)
678 dest = ui.expandpath(dest)
679
679
680 if not dest.startswith("ssh://"):
680 if not dest.startswith("ssh://"):
681 ui.warn("abort: can only push to ssh:// destinations currently\n")
681 ui.warn("abort: can only push to ssh:// destinations currently\n")
682 return 1
682 return 1
683
683
684 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
684 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
685 if not m:
685 if not m:
686 ui.warn("abort: couldn't parse destination %s\n" % dest)
686 ui.warn("abort: couldn't parse destination %s\n" % dest)
687 return 1
687 return 1
688
688
689 user, host, port, path = map(m.group, (2, 3, 5, 7))
689 user, host, port, path = map(m.group, (2, 3, 5, 7))
690 uhost = user and ("%s@%s" % (user, host)) or host
690 uhost = user and ("%s@%s" % (user, host)) or host
691 port = port and (" -p %s") % port or ""
691 port = port and (" -p %s") % port or ""
692 path = path or ""
692 path = path or ""
693
693
694 sport = random.randrange(30000, 60000)
694 sport = random.randrange(30000, 60000)
695 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
695 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
696 cmd = cmd % (uhost, port, sport+1, sport, path, sport+1)
696 cmd = cmd % (uhost, port, sport+1, sport, path, sport+1)
697
697
698 child = os.fork()
698 child = os.fork()
699 if not child:
699 if not child:
700 sys.stdout = file("/dev/null", "w")
700 sys.stdout = file("/dev/null", "w")
701 sys.stderr = sys.stdout
701 sys.stderr = sys.stdout
702 hgweb.server(repo.root, "pull", "", "localhost", sport)
702 hgweb.server(repo.root, "pull", "", "localhost", sport)
703 else:
703 else:
704 ui.status("connecting to %s\n" % host)
704 ui.status("connecting to %s\n" % host)
705 r = os.system(cmd)
705 r = os.system(cmd)
706 os.kill(child, signal.SIGTERM)
706 os.kill(child, signal.SIGTERM)
707 return r
707 return r
708
708
709 def rawcommit(ui, repo, *flist, **rc):
709 def rawcommit(ui, repo, *flist, **rc):
710 "raw commit interface"
710 "raw commit interface"
711
711
712 text = rc['text']
712 text = rc['text']
713 if not text and rc['logfile']:
713 if not text and rc['logfile']:
714 try: text = open(rc['logfile']).read()
714 try: text = open(rc['logfile']).read()
715 except IOError: pass
715 except IOError: pass
716 if not text and not rc['logfile']:
716 if not text and not rc['logfile']:
717 ui.warn("abort: missing commit text\n")
717 ui.warn("abort: missing commit text\n")
718 return 1
718 return 1
719
719
720 files = relpath(repo, list(flist))
720 files = relpath(repo, list(flist))
721 if rc['files']:
721 if rc['files']:
722 files += open(rc['files']).read().splitlines()
722 files += open(rc['files']).read().splitlines()
723
723
724 rc['parent'] = map(repo.lookup, rc['parent'])
724 rc['parent'] = map(repo.lookup, rc['parent'])
725
725
726 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
726 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
727
727
728 def recover(ui, repo):
728 def recover(ui, repo):
729 """roll back an interrupted transaction"""
729 """roll back an interrupted transaction"""
730 repo.recover()
730 repo.recover()
731
731
732 def remove(ui, repo, file, *files):
732 def remove(ui, repo, file, *files):
733 """remove the specified files on the next commit"""
733 """remove the specified files on the next commit"""
734 repo.remove(relpath(repo, (file,) + files))
734 repo.remove(relpath(repo, (file,) + files))
735
735
736 def revert(ui, repo, *names, **opts):
736 def revert(ui, repo, *names, **opts):
737 """revert modified files or dirs back to their unmodified states"""
737 """revert modified files or dirs back to their unmodified states"""
738 node = opts['rev'] and repo.lookup(opts['rev']) or \
738 node = opts['rev'] and repo.lookup(opts['rev']) or \
739 repo.dirstate.parents()[0]
739 repo.dirstate.parents()[0]
740 root = os.path.realpath(repo.root)
740 root = os.path.realpath(repo.root)
741
741
742 def trimpath(p):
742 def trimpath(p):
743 p = os.path.realpath(p)
743 p = os.path.realpath(p)
744 if p.startswith(root):
744 if p.startswith(root):
745 rest = p[len(root):]
745 rest = p[len(root):]
746 if not rest:
746 if not rest:
747 return rest
747 return rest
748 if p.startswith(os.sep):
748 if p.startswith(os.sep):
749 return rest[1:]
749 return rest[1:]
750 return p
750 return p
751
751
752 relnames = map(trimpath, names or [os.getcwd()])
752 relnames = map(trimpath, names or [os.getcwd()])
753 chosen = {}
753 chosen = {}
754
754
755 def choose(name):
755 def choose(name):
756 def body(name):
756 def body(name):
757 for r in relnames:
757 for r in relnames:
758 if not name.startswith(r): continue
758 if not name.startswith(r): continue
759 rest = name[len(r):]
759 rest = name[len(r):]
760 if not rest: return r, True
760 if not rest: return r, True
761 depth = rest.count(os.sep)
761 depth = rest.count(os.sep)
762 if not r:
762 if not r:
763 if depth == 0 or not opts['nonrecursive']: return r, True
763 if depth == 0 or not opts['nonrecursive']: return r, True
764 elif rest[0] == os.sep:
764 elif rest[0] == os.sep:
765 if depth == 1 or not opts['nonrecursive']: return r, True
765 if depth == 1 or not opts['nonrecursive']: return r, True
766 return None, False
766 return None, False
767 relname, ret = body(name)
767 relname, ret = body(name)
768 if ret:
768 if ret:
769 chosen[relname] = 1
769 chosen[relname] = 1
770 return ret
770 return ret
771
771
772 r = repo.update(node, False, True, choose, False)
772 r = repo.update(node, False, True, choose, False)
773 for n in relnames:
773 for n in relnames:
774 if n not in chosen:
774 if n not in chosen:
775 ui.warn('error: no matches for %s\n' % n)
775 ui.warn('error: no matches for %s\n' % n)
776 r = 1
776 r = 1
777 sys.stdout.flush()
777 sys.stdout.flush()
778 return r
778 return r
779
779
780 def root(ui, repo):
780 def root(ui, repo):
781 """print the root (top) of the current working dir"""
781 """print the root (top) of the current working dir"""
782 ui.write(repo.root + "\n")
782 ui.write(repo.root + "\n")
783
783
784 def serve(ui, repo, **opts):
784 def serve(ui, repo, **opts):
785 """export the repository via HTTP"""
785 """export the repository via HTTP"""
786 hgweb.server(repo.root, opts["name"], opts["templates"],
786 hgweb.server(repo.root, opts["name"], opts["templates"],
787 opts["address"], opts["port"])
787 opts["address"], opts["port"])
788
788
789 def status(ui, repo):
789 def status(ui, repo):
790 '''show changed files in the working directory
790 '''show changed files in the working directory
791
791
792 C = changed
792 C = changed
793 A = added
793 A = added
794 R = removed
794 R = removed
795 ? = not tracked'''
795 ? = not tracked'''
796
796
797 (c, a, d, u) = repo.changes(None, None)
797 (c, a, d, u) = repo.changes(None, None)
798 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
798 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
799
799
800 for f in c: ui.write("C ", f, "\n")
800 for f in c: ui.write("C ", f, "\n")
801 for f in a: ui.write("A ", f, "\n")
801 for f in a: ui.write("A ", f, "\n")
802 for f in d: ui.write("R ", f, "\n")
802 for f in d: ui.write("R ", f, "\n")
803 for f in u: ui.write("? ", f, "\n")
803 for f in u: ui.write("? ", f, "\n")
804
804
805 def tag(ui, repo, name, rev = None, **opts):
805 def tag(ui, repo, name, rev = None, **opts):
806 """add a tag for the current tip or a given revision"""
806 """add a tag for the current tip or a given revision"""
807
807
808 if name == "tip":
808 if name == "tip":
809 ui.warn("abort: 'tip' is a reserved name!\n")
809 ui.warn("abort: 'tip' is a reserved name!\n")
810 return -1
810 return -1
811 if name.find(revrangesep) >= 0:
811 if name.find(revrangesep) >= 0:
812 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep)
812 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep)
813 return -1
813 return -1
814
814
815 (c, a, d, u) = repo.changes(None, None)
815 (c, a, d, u) = repo.changes(None, None)
816 for x in (c, a, d, u):
816 for x in (c, a, d, u):
817 if ".hgtags" in x:
817 if ".hgtags" in x:
818 ui.warn("abort: working copy of .hgtags is changed!\n")
818 ui.warn("abort: working copy of .hgtags is changed!\n")
819 ui.status("(please commit .hgtags manually)\n")
819 ui.status("(please commit .hgtags manually)\n")
820 return -1
820 return -1
821
821
822 if rev:
822 if rev:
823 r = hg.hex(repo.lookup(rev))
823 r = hg.hex(repo.lookup(rev))
824 else:
824 else:
825 r = hg.hex(repo.changelog.tip())
825 r = hg.hex(repo.changelog.tip())
826
826
827 add = 0
827 add = 0
828 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
828 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
829 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
829 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
830 if add: repo.add([".hgtags"])
830 if add: repo.add([".hgtags"])
831
831
832 if not opts['text']:
832 if not opts['text']:
833 opts['text'] = "Added tag %s for changeset %s" % (name, r)
833 opts['text'] = "Added tag %s for changeset %s" % (name, r)
834
834
835 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
835 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
836
836
837 def tags(ui, repo):
837 def tags(ui, repo):
838 """list repository tags"""
838 """list repository tags"""
839
839
840 l = repo.tagslist()
840 l = repo.tagslist()
841 l.reverse()
841 l.reverse()
842 for t, n in l:
842 for t, n in l:
843 try:
843 try:
844 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
844 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
845 except KeyError:
845 except KeyError:
846 r = " ?:?"
846 r = " ?:?"
847 ui.write("%-30s %s\n" % (t, r))
847 ui.write("%-30s %s\n" % (t, r))
848
848
849 def tip(ui, repo):
849 def tip(ui, repo):
850 """show the tip revision"""
850 """show the tip revision"""
851 n = repo.changelog.tip()
851 n = repo.changelog.tip()
852 show_changeset(ui, repo, changenode=n)
852 show_changeset(ui, repo, changenode=n)
853
853
854 def undo(ui, repo):
854 def undo(ui, repo):
855 """undo the last transaction"""
855 """undo the last transaction"""
856 repo.undo()
856 repo.undo()
857
857
858 def update(ui, repo, node=None, merge=False, clean=False):
858 def update(ui, repo, node=None, merge=False, clean=False):
859 '''update or merge working directory
859 '''update or merge working directory
860
860
861 If there are no outstanding changes in the working directory and
861 If there are no outstanding changes in the working directory and
862 there is a linear relationship between the current version and the
862 there is a linear relationship between the current version and the
863 requested version, the result is the requested version.
863 requested version, the result is the requested version.
864
864
865 Otherwise the result is a merge between the contents of the
865 Otherwise the result is a merge between the contents of the
866 current working directory and the requested version. Files that
866 current working directory and the requested version. Files that
867 changed between either parent are marked as changed for the next
867 changed between either parent are marked as changed for the next
868 commit and a commit must be performed before any further updates
868 commit and a commit must be performed before any further updates
869 are allowed.
869 are allowed.
870 '''
870 '''
871 node = node and repo.lookup(node) or repo.changelog.tip()
871 node = node and repo.lookup(node) or repo.changelog.tip()
872 return repo.update(node, allow=merge, force=clean)
872 return repo.update(node, allow=merge, force=clean)
873
873
874 def verify(ui, repo):
874 def verify(ui, repo):
875 """verify the integrity of the repository"""
875 """verify the integrity of the repository"""
876 return repo.verify()
876 return repo.verify()
877
877
878 # Command options and aliases are listed here, alphabetically
878 # Command options and aliases are listed here, alphabetically
879
879
880 table = {
880 table = {
881 "add": (add, [], "hg add [files]"),
881 "add": (add, [], "hg add [files]"),
882 "addremove": (addremove, [], "hg addremove [files]"),
882 "addremove": (addremove, [], "hg addremove [files]"),
883 "annotate": (annotate,
883 "annotate": (annotate,
884 [('r', 'revision', '', 'revision'),
884 [('r', 'revision', '', 'revision'),
885 ('u', 'user', None, 'show user'),
885 ('u', 'user', None, 'show user'),
886 ('n', 'number', None, 'show revision number'),
886 ('n', 'number', None, 'show revision number'),
887 ('c', 'changeset', None, 'show changeset')],
887 ('c', 'changeset', None, 'show changeset')],
888 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
888 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
889 "cat": (cat, [], 'hg cat <file> [rev]'),
889 "cat": (cat, [], 'hg cat <file> [rev]'),
890 "clone": (clone, [('U', 'noupdate', None, 'skip update after cloning')],
890 "clone": (clone, [('U', 'noupdate', None, 'skip update after cloning')],
891 'hg clone [options] <source> [dest]'),
891 'hg clone [options] <source> [dest]'),
892 "commit|ci": (commit,
892 "commit|ci": (commit,
893 [('t', 'text', "", 'commit text'),
893 [('t', 'text', "", 'commit text'),
894 ('A', 'addremove', None, 'run add/remove during commit'),
894 ('A', 'addremove', None, 'run add/remove during commit'),
895 ('l', 'logfile', "", 'commit text file'),
895 ('l', 'logfile', "", 'commit text file'),
896 ('d', 'date', "", 'date code'),
896 ('d', 'date', "", 'date code'),
897 ('u', 'user', "", 'user')],
897 ('u', 'user', "", 'user')],
898 'hg commit [files]'),
898 'hg commit [files]'),
899 "copy": (copy, [], 'hg copy <source> <dest>'),
899 "copy": (copy, [], 'hg copy <source> <dest>'),
900 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
900 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
901 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
901 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
902 "debugindex": (debugindex, [], 'debugindex <file>'),
902 "debugindex": (debugindex, [], 'debugindex <file>'),
903 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
903 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
904 "diff": (diff, [('r', 'rev', [], 'revision')],
904 "diff": (diff, [('r', 'rev', [], 'revision')],
905 'hg diff [-r A] [-r B] [files]'),
905 'hg diff [-r A] [-r B] [files]'),
906 "export": (export, [('o', 'output', "", 'output to file')],
906 "export": (export, [('o', 'output', "", 'output to file')],
907 "hg export [-o file] <changeset> ..."),
907 "hg export [-o file] <changeset> ..."),
908 "forget": (forget, [], "hg forget [files]"),
908 "forget": (forget, [], "hg forget [files]"),
909 "heads": (heads, [], 'hg heads'),
909 "heads": (heads, [], 'hg heads'),
910 "help": (help, [], 'hg help [command]'),
910 "help": (help, [], 'hg help [command]'),
911 "identify|id": (identify, [], 'hg identify'),
911 "identify|id": (identify, [], 'hg identify'),
912 "import|patch": (import_,
912 "import|patch": (import_,
913 [('p', 'strip', 1, 'path strip'),
913 [('p', 'strip', 1, 'path strip'),
914 ('b', 'base', "", 'base path')],
914 ('b', 'base', "", 'base path')],
915 "hg import [options] <patches>"),
915 "hg import [options] <patches>"),
916 "init": (init, [], 'hg init'),
916 "init": (init, [], 'hg init'),
917 "log|history": (log,
917 "log|history": (log,
918 [('r', 'rev', [], 'revision')],
918 [('r', 'rev', [], 'revision')],
919 'hg log [-r A] [-r B] [file]'),
919 'hg log [-r A] [-r B] [file]'),
920 "manifest": (manifest, [], 'hg manifest [rev]'),
920 "manifest": (manifest, [], 'hg manifest [rev]'),
921 "parents": (parents, [], 'hg parents [node]'),
921 "parents": (parents, [], 'hg parents [node]'),
922 "pull": (pull,
922 "pull": (pull,
923 [('u', 'update', None, 'update working directory')],
923 [('u', 'update', None, 'update working directory')],
924 'hg pull [options] [source]'),
924 'hg pull [options] [source]'),
925 "push": (push, [], 'hg push <destination>'),
925 "push": (push, [], 'hg push <destination>'),
926 "rawcommit": (rawcommit,
926 "rawcommit": (rawcommit,
927 [('p', 'parent', [], 'parent'),
927 [('p', 'parent', [], 'parent'),
928 ('d', 'date', "", 'date code'),
928 ('d', 'date', "", 'date code'),
929 ('u', 'user', "", 'user'),
929 ('u', 'user', "", 'user'),
930 ('F', 'files', "", 'file list'),
930 ('F', 'files', "", 'file list'),
931 ('t', 'text', "", 'commit text'),
931 ('t', 'text', "", 'commit text'),
932 ('l', 'logfile', "", 'commit text file')],
932 ('l', 'logfile', "", 'commit text file')],
933 'hg rawcommit [options] [files]'),
933 'hg rawcommit [options] [files]'),
934 "recover": (recover, [], "hg recover"),
934 "recover": (recover, [], "hg recover"),
935 "remove|rm": (remove, [], "hg remove [files]"),
935 "remove|rm": (remove, [], "hg remove [files]"),
936 "revert": (revert,
936 "revert": (revert,
937 [("n", "nonrecursive", None, "don't recurse into subdirs"),
937 [("n", "nonrecursive", None, "don't recurse into subdirs"),
938 ("r", "rev", "", "revision")],
938 ("r", "rev", "", "revision")],
939 "hg revert [files|dirs]"),
939 "hg revert [files|dirs]"),
940 "root": (root, [], "hg root"),
940 "root": (root, [], "hg root"),
941 "serve": (serve, [('p', 'port', 8000, 'listen port'),
941 "serve": (serve, [('p', 'port', 8000, 'listen port'),
942 ('a', 'address', '', 'interface address'),
942 ('a', 'address', '', 'interface address'),
943 ('n', 'name', os.getcwd(), 'repository name'),
943 ('n', 'name', os.getcwd(), 'repository name'),
944 ('t', 'templates', "", 'template map')],
944 ('t', 'templates', "", 'template map')],
945 "hg serve [options]"),
945 "hg serve [options]"),
946 "status": (status, [], 'hg status'),
946 "status": (status, [], 'hg status'),
947 "tag": (tag, [('t', 'text', "", 'commit text'),
947 "tag": (tag, [('t', 'text', "", 'commit text'),
948 ('d', 'date', "", 'date code'),
948 ('d', 'date', "", 'date code'),
949 ('u', 'user', "", 'user')],
949 ('u', 'user', "", 'user')],
950 'hg tag [options] <name> [rev]'),
950 'hg tag [options] <name> [rev]'),
951 "tags": (tags, [], 'hg tags'),
951 "tags": (tags, [], 'hg tags'),
952 "tip": (tip, [], 'hg tip'),
952 "tip": (tip, [], 'hg tip'),
953 "undo": (undo, [], 'hg undo'),
953 "undo": (undo, [], 'hg undo'),
954 "update|up|checkout|co":
954 "update|up|checkout|co":
955 (update,
955 (update,
956 [('m', 'merge', None, 'allow merging of conflicts'),
956 [('m', 'merge', None, 'allow merging of conflicts'),
957 ('C', 'clean', None, 'overwrite locally modified files')],
957 ('C', 'clean', None, 'overwrite locally modified files')],
958 'hg update [options] [node]'),
958 'hg update [options] [node]'),
959 "verify": (verify, [], 'hg verify'),
959 "verify": (verify, [], 'hg verify'),
960 "version": (show_version, [], 'hg version'),
960 "version": (show_version, [], 'hg version'),
961 }
961 }
962
962
963 norepo = "clone init version help debugindex debugindexdot"
963 norepo = "clone init version help debugindex debugindexdot"
964
964
965 def find(cmd):
965 def find(cmd):
966 for e in table.keys():
966 for e in table.keys():
967 if re.match("(%s)$" % e, cmd):
967 if re.match("(%s)$" % e, cmd):
968 return table[e]
968 return table[e]
969
969
970 raise UnknownCommand(cmd)
970 raise UnknownCommand(cmd)
971
971
972 class SignalInterrupt(Exception): pass
972 class SignalInterrupt(Exception): pass
973
973
974 def catchterm(*args):
974 def catchterm(*args):
975 raise SignalInterrupt
975 raise SignalInterrupt
976
976
977 def run():
977 def run():
978 sys.exit(dispatch(sys.argv[1:]))
978 sys.exit(dispatch(sys.argv[1:]))
979
979
980 def dispatch(args):
980 def dispatch(args):
981 signal.signal(signal.SIGTERM, catchterm)
982
983 def get_ui():
984 return ui.ui(options["verbose"], options["debug"], options["quiet"],
985 not options["noninteractive"])
986
981 options = {}
987 options = {}
982 opts = [('v', 'verbose', None, 'verbose'),
988 opts = [('v', 'verbose', None, 'verbose'),
983 ('', 'debug', None, 'debug'),
989 ('', 'debug', None, 'debug'),
984 ('q', 'quiet', None, 'quiet'),
990 ('q', 'quiet', None, 'quiet'),
985 ('', 'profile', None, 'profile'),
991 ('', 'profile', None, 'profile'),
986 ('R', 'repository', "", 'repository root directory'),
992 ('R', 'repository', "", 'repository root directory'),
987 ('', 'traceback', None, 'print traceback on exception'),
993 ('', 'traceback', None, 'print traceback on exception'),
988 ('y', 'noninteractive', None, 'run non-interactively'),
994 ('y', 'noninteractive', None, 'run non-interactively'),
989 ('', 'version', None, 'output version information and exit'),
995 ('', 'version', None, 'output version information and exit'),
990 ]
996 ]
991
997
998 try:
992 args = fancyopts.fancyopts(args, opts, options,
999 args = fancyopts.fancyopts(args, opts, options,
993 'hg [options] <command> [options] [files]')
1000 'hg [options] <command> [options] [files]')
1001 except fancyopts.getopt.GetoptError, inst:
1002 u = ui.ui()
1003 u.warn("hg: %s\n" % (inst))
1004 sys.exit(-1)
994
1005
995 if not args:
1006 if not args:
996 cmd = "help"
1007 cmd = "help"
997 else:
1008 else:
998 cmd, args = args[0], args[1:]
1009 cmd, args = args[0], args[1:]
999
1010
1000 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
1001 not options["noninteractive"])
1002
1003 if options["version"]:
1011 if options["version"]:
1004 show_version(u)
1012 show_version(get_ui())
1005 sys.exit(0)
1013 sys.exit(0)
1006
1014
1007 try:
1015 try:
1008 i = find(cmd)
1016 i = find(cmd)
1009 except UnknownCommand:
1017 except UnknownCommand:
1018 u = get_ui()
1010 u.warn("hg: unknown command '%s'\n" % cmd)
1019 u.warn("hg: unknown command '%s'\n" % cmd)
1011 help(u)
1020 help(u)
1012 sys.exit(1)
1021 sys.exit(1)
1013
1022
1014 signal.signal(signal.SIGTERM, catchterm)
1023 # combine global options into local
1024 c = list(i[1])
1025 l = len(c)
1026 for o in opts:
1027 c.append((o[0], o[1], options[o[1]], o[3]))
1015
1028
1016 cmdoptions = {}
1029 cmdoptions = {}
1017 try:
1030 try:
1018 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
1031 args = fancyopts.fancyopts(args, c, cmdoptions, i[2])
1019 except fancyopts.getopt.GetoptError, inst:
1032 except fancyopts.getopt.GetoptError, inst:
1033 u = get_ui()
1020 u.warn("hg %s: %s\n" % (cmd, inst))
1034 u.warn("hg %s: %s\n" % (cmd, inst))
1021 help(u, cmd)
1035 help(u, cmd)
1022 sys.exit(-1)
1036 sys.exit(-1)
1023
1037
1038 # separate global options back out
1039 for o in opts:
1040 n = o[1]
1041 options[n] = cmdoptions[n]
1042 del cmdoptions[n]
1043
1044 u = get_ui()
1045
1024 try:
1046 try:
1025 try:
1047 try:
1026 if cmd not in norepo.split():
1048 if cmd not in norepo.split():
1027 path = options["repository"] or ""
1049 path = options["repository"] or ""
1028 repo = hg.repository(ui=u, path=path)
1050 repo = hg.repository(ui=u, path=path)
1029 d = lambda: i[0](u, repo, *args, **cmdoptions)
1051 d = lambda: i[0](u, repo, *args, **cmdoptions)
1030 else:
1052 else:
1031 d = lambda: i[0](u, *args, **cmdoptions)
1053 d = lambda: i[0](u, *args, **cmdoptions)
1032
1054
1033 if options['profile']:
1055 if options['profile']:
1034 import hotshot, hotshot.stats
1056 import hotshot, hotshot.stats
1035 prof = hotshot.Profile("hg.prof")
1057 prof = hotshot.Profile("hg.prof")
1036 r = prof.runcall(d)
1058 r = prof.runcall(d)
1037 prof.close()
1059 prof.close()
1038 stats = hotshot.stats.load("hg.prof")
1060 stats = hotshot.stats.load("hg.prof")
1039 stats.strip_dirs()
1061 stats.strip_dirs()
1040 stats.sort_stats('time', 'calls')
1062 stats.sort_stats('time', 'calls')
1041 stats.print_stats(40)
1063 stats.print_stats(40)
1042 return r
1064 return r
1043 else:
1065 else:
1044 return d()
1066 return d()
1045 except:
1067 except:
1046 if options['traceback']:
1068 if options['traceback']:
1047 traceback.print_exc()
1069 traceback.print_exc()
1048 raise
1070 raise
1049 except util.CommandError, inst:
1071 except util.CommandError, inst:
1050 u.warn("abort: %s\n" % inst.args)
1072 u.warn("abort: %s\n" % inst.args)
1051 except hg.RepoError, inst:
1073 except hg.RepoError, inst:
1052 u.warn("abort: ", inst, "!\n")
1074 u.warn("abort: ", inst, "!\n")
1053 except SignalInterrupt:
1075 except SignalInterrupt:
1054 u.warn("killed!\n")
1076 u.warn("killed!\n")
1055 except KeyboardInterrupt:
1077 except KeyboardInterrupt:
1056 u.warn("interrupted!\n")
1078 u.warn("interrupted!\n")
1057 except IOError, inst:
1079 except IOError, inst:
1058 if hasattr(inst, "code"):
1080 if hasattr(inst, "code"):
1059 u.warn("abort: %s\n" % inst)
1081 u.warn("abort: %s\n" % inst)
1060 elif hasattr(inst, "reason"):
1082 elif hasattr(inst, "reason"):
1061 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
1083 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
1062 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
1084 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
1063 u.warn("broken pipe\n")
1085 u.warn("broken pipe\n")
1064 else:
1086 else:
1065 raise
1087 raise
1066 except OSError, inst:
1088 except OSError, inst:
1067 if hasattr(inst, "filename"):
1089 if hasattr(inst, "filename"):
1068 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
1090 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
1069 else:
1091 else:
1070 u.warn("abort: %s\n" % inst.strerror)
1092 u.warn("abort: %s\n" % inst.strerror)
1071 except TypeError, inst:
1093 except TypeError, inst:
1072 # was this an argument error?
1094 # was this an argument error?
1073 tb = traceback.extract_tb(sys.exc_info()[2])
1095 tb = traceback.extract_tb(sys.exc_info()[2])
1074 if len(tb) > 2: # no
1096 if len(tb) > 2: # no
1075 raise
1097 raise
1076 u.debug(inst, "\n")
1098 u.debug(inst, "\n")
1077 u.warn("%s: invalid arguments\n" % i[0].__name__)
1099 u.warn("%s: invalid arguments\n" % i[0].__name__)
1078 help(u, cmd)
1100 help(u, cmd)
1079
1101
1080 sys.exit(-1)
1102 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now