##// END OF EJS Templates
Improvements for hg identify:...
Thomas Arendsen Hein -
r386:494c8e3f default
parent child Browse files
Show More
@@ -1,759 +1,762 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
9 import fancyopts, ui, hg
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback random signal errno")
11 demandload(globals(), "mdiff time hgweb traceback random signal errno")
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] != os.sep: t += os.sep
19 if t and t[-1] != os.sep: t += os.sep
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([p], files)
26 return filterfiles([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 [ os.path.normpath(os.path.join(p, x)) for x in args ]
32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
33 return args
33 return args
34
34
35 def dodiff(repo, path, files = None, node1 = None, node2 = None):
35 def dodiff(repo, path, files = None, node1 = None, node2 = None):
36 def date(c):
36 def date(c):
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
38
38
39 if node2:
39 if node2:
40 change = repo.changelog.read(node2)
40 change = repo.changelog.read(node2)
41 mmap2 = repo.manifest.read(change[0])
41 mmap2 = repo.manifest.read(change[0])
42 (c, a, d) = repo.diffrevs(node1, node2)
42 (c, a, d) = repo.diffrevs(node1, node2)
43 def read(f): return repo.file(f).read(mmap2[f])
43 def read(f): return repo.file(f).read(mmap2[f])
44 date2 = date(change)
44 date2 = date(change)
45 else:
45 else:
46 date2 = time.asctime()
46 date2 = time.asctime()
47 (c, a, d, u) = repo.diffdir(path, node1)
47 (c, a, d, u) = repo.diffdir(path, node1)
48 if not node1:
48 if not node1:
49 node1 = repo.dirstate.parents()[0]
49 node1 = repo.dirstate.parents()[0]
50 def read(f): return file(os.path.join(repo.root, f)).read()
50 def read(f): return file(os.path.join(repo.root, f)).read()
51
51
52 change = repo.changelog.read(node1)
52 change = repo.changelog.read(node1)
53 mmap = repo.manifest.read(change[0])
53 mmap = repo.manifest.read(change[0])
54 date1 = date(change)
54 date1 = date(change)
55
55
56 if files:
56 if files:
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
58
58
59 for f in c:
59 for f in c:
60 to = None
60 to = None
61 if f in mmap:
61 if f in mmap:
62 to = repo.file(f).read(mmap[f])
62 to = repo.file(f).read(mmap[f])
63 tn = read(f)
63 tn = read(f)
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
65 for f in a:
65 for f in a:
66 to = None
66 to = None
67 tn = read(f)
67 tn = read(f)
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
69 for f in d:
69 for f in d:
70 to = repo.file(f).read(mmap[f])
70 to = repo.file(f).read(mmap[f])
71 tn = None
71 tn = None
72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
73
73
74 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
74 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
75 """show a single changeset or file revision"""
75 """show a single changeset or file revision"""
76 changelog = repo.changelog
76 changelog = repo.changelog
77 if filelog:
77 if filelog:
78 log = filelog
78 log = filelog
79 filerev = rev
79 filerev = rev
80 node = filenode = filelog.node(filerev)
80 node = filenode = filelog.node(filerev)
81 changerev = filelog.linkrev(filenode)
81 changerev = filelog.linkrev(filenode)
82 changenode = changenode or changelog.node(changerev)
82 changenode = changenode or changelog.node(changerev)
83 else:
83 else:
84 log = changelog
84 log = changelog
85 changerev = rev
85 changerev = rev
86 if changenode is None:
86 if changenode is None:
87 changenode = changelog.node(changerev)
87 changenode = changelog.node(changerev)
88 elif not changerev:
88 elif not changerev:
89 rev = changerev = changelog.rev(changenode)
89 rev = changerev = changelog.rev(changenode)
90 node = changenode
90 node = changenode
91
91
92 if ui.quiet:
92 if ui.quiet:
93 ui.write("%d:%s\n" % (rev, hg.hex(node)))
93 ui.write("%d:%s\n" % (rev, hg.hex(node)))
94 return
94 return
95
95
96 changes = changelog.read(changenode)
96 changes = changelog.read(changenode)
97
97
98 parents = [(log.rev(parent), hg.hex(parent))
98 parents = [(log.rev(parent), hg.hex(parent))
99 for parent in log.parents(node)
99 for parent in log.parents(node)
100 if ui.debugflag or parent != hg.nullid]
100 if ui.debugflag or parent != hg.nullid]
101 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
101 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
102 parents = []
102 parents = []
103
103
104 if filelog:
104 if filelog:
105 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
105 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
106 for parent in parents:
106 for parent in parents:
107 ui.write("parent: %d:%s\n" % parent)
107 ui.write("parent: %d:%s\n" % parent)
108 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
108 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
109 else:
109 else:
110 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
110 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
111 for parent in parents:
111 for parent in parents:
112 ui.write("parent: %d:%s\n" % parent)
112 ui.write("parent: %d:%s\n" % parent)
113 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
113 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
114 hg.hex(changes[0])))
114 hg.hex(changes[0])))
115 ui.status("user: %s\n" % changes[1])
115 ui.status("user: %s\n" % changes[1])
116 ui.status("date: %s\n" % time.asctime(
116 ui.status("date: %s\n" % time.asctime(
117 time.localtime(float(changes[2].split(' ')[0]))))
117 time.localtime(float(changes[2].split(' ')[0]))))
118 ui.note("files: %s\n" % " ".join(changes[3]))
118 ui.note("files: %s\n" % " ".join(changes[3]))
119 description = changes[4].strip()
119 description = changes[4].strip()
120 if description:
120 if description:
121 if ui.verbose:
121 if ui.verbose:
122 ui.status("description:\n")
122 ui.status("description:\n")
123 ui.status(description)
123 ui.status(description)
124 ui.status("\n")
124 ui.status("\n")
125 else:
125 else:
126 ui.status("summary: %s\n" % description.splitlines()[0])
126 ui.status("summary: %s\n" % description.splitlines()[0])
127 ui.status("\n")
127 ui.status("\n")
128
128
129 def help(ui, cmd=None):
129 def help(ui, cmd=None):
130 '''show help for a given command or all commands'''
130 '''show help for a given command or all commands'''
131 if cmd:
131 if cmd:
132 try:
132 try:
133 i = find(cmd)
133 i = find(cmd)
134 ui.write("%s\n\n" % i[2])
134 ui.write("%s\n\n" % i[2])
135
135
136 if i[1]:
136 if i[1]:
137 for s, l, d, c in i[1]:
137 for s, l, d, c in i[1]:
138 opt=' '
138 opt=' '
139 if s: opt = opt + '-' + s + ' '
139 if s: opt = opt + '-' + s + ' '
140 if l: opt = opt + '--' + l + ' '
140 if l: opt = opt + '--' + l + ' '
141 if d: opt = opt + '(' + str(d) + ')'
141 if d: opt = opt + '(' + str(d) + ')'
142 ui.write(opt, "\n")
142 ui.write(opt, "\n")
143 if c: ui.write(' %s\n' % c)
143 if c: ui.write(' %s\n' % c)
144 ui.write("\n")
144 ui.write("\n")
145
145
146 ui.write(i[0].__doc__, "\n")
146 ui.write(i[0].__doc__, "\n")
147 except UnknownCommand:
147 except UnknownCommand:
148 ui.warn("hg: unknown command %s\n" % cmd)
148 ui.warn("hg: unknown command %s\n" % cmd)
149 sys.exit(0)
149 sys.exit(0)
150 else:
150 else:
151 ui.status('hg commands:\n\n')
151 ui.status('hg commands:\n\n')
152
152
153 h = {}
153 h = {}
154 for e in table.values():
154 for e in table.values():
155 f = e[0]
155 f = e[0]
156 if f.__name__.startswith("debug"): continue
156 if f.__name__.startswith("debug"): continue
157 d = ""
157 d = ""
158 if f.__doc__:
158 if f.__doc__:
159 d = f.__doc__.splitlines(0)[0].rstrip()
159 d = f.__doc__.splitlines(0)[0].rstrip()
160 h[f.__name__] = d
160 h[f.__name__] = d
161
161
162 fns = h.keys()
162 fns = h.keys()
163 fns.sort()
163 fns.sort()
164 m = max(map(len, fns))
164 m = max(map(len, fns))
165 for f in fns:
165 for f in fns:
166 ui.status(' %-*s %s\n' % (m, f, h[f]))
166 ui.status(' %-*s %s\n' % (m, f, h[f]))
167
167
168 # Commands start here, listed alphabetically
168 # Commands start here, listed alphabetically
169
169
170 def add(ui, repo, file, *files):
170 def add(ui, repo, file, *files):
171 '''add the specified files on the next commit'''
171 '''add the specified files on the next commit'''
172 repo.add(relpath(repo, (file,) + files))
172 repo.add(relpath(repo, (file,) + files))
173
173
174 def addremove(ui, repo, *files):
174 def addremove(ui, repo, *files):
175 """add all new files, delete all missing files"""
175 """add all new files, delete all missing files"""
176 if files:
176 if files:
177 files = relpath(repo, files)
177 files = relpath(repo, files)
178 d = []
178 d = []
179 u = []
179 u = []
180 for f in files:
180 for f in files:
181 p = repo.wjoin(f)
181 p = repo.wjoin(f)
182 s = repo.dirstate.state(f)
182 s = repo.dirstate.state(f)
183 isfile = os.path.isfile(p)
183 isfile = os.path.isfile(p)
184 if s != 'r' and not isfile:
184 if s != 'r' and not isfile:
185 d.append(f)
185 d.append(f)
186 elif s not in 'nmai' and isfile:
186 elif s not in 'nmai' and isfile:
187 u.append(f)
187 u.append(f)
188 else:
188 else:
189 (c, a, d, u) = repo.diffdir(repo.root)
189 (c, a, d, u) = repo.diffdir(repo.root)
190 repo.add(u)
190 repo.add(u)
191 repo.remove(d)
191 repo.remove(d)
192
192
193 def annotate(u, repo, file, *files, **ops):
193 def annotate(u, repo, file, *files, **ops):
194 """show changeset information per file line"""
194 """show changeset information per file line"""
195 def getnode(rev):
195 def getnode(rev):
196 return hg.short(repo.changelog.node(rev))
196 return hg.short(repo.changelog.node(rev))
197
197
198 def getname(rev):
198 def getname(rev):
199 try:
199 try:
200 return bcache[rev]
200 return bcache[rev]
201 except KeyError:
201 except KeyError:
202 cl = repo.changelog.read(repo.changelog.node(rev))
202 cl = repo.changelog.read(repo.changelog.node(rev))
203 name = cl[1]
203 name = cl[1]
204 f = name.find('@')
204 f = name.find('@')
205 if f >= 0:
205 if f >= 0:
206 name = name[:f]
206 name = name[:f]
207 bcache[rev] = name
207 bcache[rev] = name
208 return name
208 return name
209
209
210 bcache = {}
210 bcache = {}
211 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
211 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
212 if not ops['user'] and not ops['changeset']:
212 if not ops['user'] and not ops['changeset']:
213 ops['number'] = 1
213 ops['number'] = 1
214
214
215 node = repo.dirstate.parents()[0]
215 node = repo.dirstate.parents()[0]
216 if ops['revision']:
216 if ops['revision']:
217 node = repo.changelog.lookup(ops['revision'])
217 node = repo.changelog.lookup(ops['revision'])
218 change = repo.changelog.read(node)
218 change = repo.changelog.read(node)
219 mmap = repo.manifest.read(change[0])
219 mmap = repo.manifest.read(change[0])
220 maxuserlen = 0
220 maxuserlen = 0
221 maxchangelen = 0
221 maxchangelen = 0
222 for f in relpath(repo, (file,) + files):
222 for f in relpath(repo, (file,) + files):
223 lines = repo.file(f).annotate(mmap[f])
223 lines = repo.file(f).annotate(mmap[f])
224 pieces = []
224 pieces = []
225
225
226 for o, f in opmap:
226 for o, f in opmap:
227 if ops[o]:
227 if ops[o]:
228 l = [ f(n) for n,t in lines ]
228 l = [ f(n) for n,t in lines ]
229 m = max(map(len, l))
229 m = max(map(len, l))
230 pieces.append([ "%*s" % (m, x) for x in l])
230 pieces.append([ "%*s" % (m, x) for x in l])
231
231
232 for p,l in zip(zip(*pieces), lines):
232 for p,l in zip(zip(*pieces), lines):
233 u.write(" ".join(p) + ": " + l[1])
233 u.write(" ".join(p) + ": " + l[1])
234
234
235 def cat(ui, repo, file, rev = []):
235 def cat(ui, repo, file, rev = []):
236 """output the latest or given revision of a file"""
236 """output the latest or given revision of a file"""
237 r = repo.file(relpath(repo, [file])[0])
237 r = repo.file(relpath(repo, [file])[0])
238 n = r.tip()
238 n = r.tip()
239 if rev: n = r.lookup(rev)
239 if rev: n = r.lookup(rev)
240 sys.stdout.write(r.read(n))
240 sys.stdout.write(r.read(n))
241
241
242 def commit(ui, repo, *files, **opts):
242 def commit(ui, repo, *files, **opts):
243 """commit the specified files or all outstanding changes"""
243 """commit the specified files or all outstanding changes"""
244 text = opts['text']
244 text = opts['text']
245 if not text and opts['logfile']:
245 if not text and opts['logfile']:
246 try: text = open(opts['logfile']).read()
246 try: text = open(opts['logfile']).read()
247 except IOError: pass
247 except IOError: pass
248
248
249 if opts['addremove']:
249 if opts['addremove']:
250 addremove(ui, repo, *files)
250 addremove(ui, repo, *files)
251 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
251 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
252
252
253 def copy(ui, repo, source, dest):
253 def copy(ui, repo, source, dest):
254 """mark a file as copied or renamed for the next commit"""
254 """mark a file as copied or renamed for the next commit"""
255 return repo.copy(*relpath(repo, (source, dest)))
255 return repo.copy(*relpath(repo, (source, dest)))
256
256
257 def debugaddchangegroup(ui, repo):
257 def debugaddchangegroup(ui, repo):
258 data = sys.stdin.read()
258 data = sys.stdin.read()
259 repo.addchangegroup(data)
259 repo.addchangegroup(data)
260
260
261 def debugchangegroup(ui, repo, roots):
261 def debugchangegroup(ui, repo, roots):
262 newer = repo.newer(map(repo.lookup, roots))
262 newer = repo.newer(map(repo.lookup, roots))
263 for chunk in repo.changegroup(newer):
263 for chunk in repo.changegroup(newer):
264 sys.stdout.write(chunk)
264 sys.stdout.write(chunk)
265
265
266 def debugindex(ui, file):
266 def debugindex(ui, file):
267 r = hg.revlog(open, file, "")
267 r = hg.revlog(open, file, "")
268 print " rev offset length base linkrev"+\
268 print " rev offset length base linkrev"+\
269 " p1 p2 nodeid"
269 " p1 p2 nodeid"
270 for i in range(r.count()):
270 for i in range(r.count()):
271 e = r.index[i]
271 e = r.index[i]
272 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
272 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
273 i, e[0], e[1], e[2], e[3],
273 i, e[0], e[1], e[2], e[3],
274 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
274 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
275
275
276 def debugindexdot(ui, file):
276 def debugindexdot(ui, file):
277 r = hg.revlog(open, file, "")
277 r = hg.revlog(open, file, "")
278 print "digraph G {"
278 print "digraph G {"
279 for i in range(r.count()):
279 for i in range(r.count()):
280 e = r.index[i]
280 e = r.index[i]
281 print "\t%d -> %d" % (r.rev(e[4]), i)
281 print "\t%d -> %d" % (r.rev(e[4]), i)
282 if e[5] != hg.nullid:
282 if e[5] != hg.nullid:
283 print "\t%d -> %d" % (r.rev(e[5]), i)
283 print "\t%d -> %d" % (r.rev(e[5]), i)
284 print "}"
284 print "}"
285
285
286 def diff(ui, repo, *files, **opts):
286 def diff(ui, repo, *files, **opts):
287 """diff working directory (or selected files)"""
287 """diff working directory (or selected files)"""
288 revs = []
288 revs = []
289 if opts['rev']:
289 if opts['rev']:
290 revs = map(lambda x: repo.lookup(x), opts['rev'])
290 revs = map(lambda x: repo.lookup(x), opts['rev'])
291
291
292 if len(revs) > 2:
292 if len(revs) > 2:
293 self.ui.warn("too many revisions to diff\n")
293 self.ui.warn("too many revisions to diff\n")
294 sys.exit(1)
294 sys.exit(1)
295
295
296 if files:
296 if files:
297 files = relpath(repo, files)
297 files = relpath(repo, files)
298 else:
298 else:
299 files = relpath(repo, [""])
299 files = relpath(repo, [""])
300
300
301 dodiff(repo, os.getcwd(), files, *revs)
301 dodiff(repo, os.getcwd(), files, *revs)
302
302
303 def export(ui, repo, changeset):
303 def export(ui, repo, changeset):
304 """dump the changeset header and diffs for a revision"""
304 """dump the changeset header and diffs for a revision"""
305 node = repo.lookup(changeset)
305 node = repo.lookup(changeset)
306 prev, other = repo.changelog.parents(node)
306 prev, other = repo.changelog.parents(node)
307 change = repo.changelog.read(node)
307 change = repo.changelog.read(node)
308 print "# HG changeset patch"
308 print "# HG changeset patch"
309 print "# User %s" % change[1]
309 print "# User %s" % change[1]
310 print "# Node ID %s" % hg.hex(node)
310 print "# Node ID %s" % hg.hex(node)
311 print "# Parent %s" % hg.hex(prev)
311 print "# Parent %s" % hg.hex(prev)
312 print
312 print
313 if other != hg.nullid:
313 if other != hg.nullid:
314 print "# Parent %s" % hg.hex(other)
314 print "# Parent %s" % hg.hex(other)
315 print change[4].rstrip()
315 print change[4].rstrip()
316 print
316 print
317
317
318 dodiff(repo, "", None, prev, node)
318 dodiff(repo, "", None, prev, node)
319
319
320 def forget(ui, repo, file, *files):
320 def forget(ui, repo, file, *files):
321 """don't add the specified files on the next commit"""
321 """don't add the specified files on the next commit"""
322 repo.forget(relpath(repo, (file,) + files))
322 repo.forget(relpath(repo, (file,) + files))
323
323
324 def heads(ui, repo):
324 def heads(ui, repo):
325 """show current repository heads"""
325 """show current repository heads"""
326 for n in repo.changelog.heads():
326 for n in repo.changelog.heads():
327 show_changeset(ui, repo, changenode=n)
327 show_changeset(ui, repo, changenode=n)
328
328
329 def history(ui, repo):
329 def history(ui, repo):
330 """show the changelog history"""
330 """show the changelog history"""
331 for i in range(repo.changelog.count() - 1, -1, -1):
331 for i in range(repo.changelog.count() - 1, -1, -1):
332 show_changeset(ui, repo, rev=i)
332 show_changeset(ui, repo, rev=i)
333
333
334 def identify(ui, repo):
334 def identify(ui, repo):
335 """print information about the working copy"""
335 """print information about the working copy"""
336 (c, a, d, u) = repo.diffdir(repo.root)
337 mflag = (c or a or d or u) and "+" or ""
338 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
336 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
339 if not parents:
337 if not parents:
340 ui.write("unknown\n")
338 ui.write("unknown\n")
341 return
339 return
342
340
343 tstring = ''
341 hexfunc = ui.verbose and hg.hex or hg.short
342 (c, a, d, u) = repo.diffdir(repo.root)
343 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
344 (c or a or d) and "+" or "")]
345
344 if not ui.quiet:
346 if not ui.quiet:
345 tags = sum(map(repo.nodetags, parents), [])
347 # multiple tags for a single parent separated by '/'
346 tstring = " " + ' + '.join(tags)
348 parenttags = ['/'.join(tags)
349 for tags in map(repo.nodetags, parents) if tags]
350 # tags for multiple parents separated by ' + '
351 output.append(' + '.join(parenttags))
347
352
348 hexfunc = ui.verbose and hg.hex or hg.short
353 ui.write("%s\n" % ' '.join(output))
349 pstring = '+'.join([hexfunc(parent) for parent in parents])
350 ui.write("%s%s%s\n" % (pstring, mflag, tstring))
351
354
352 def init(ui, source=None):
355 def init(ui, source=None):
353 """create a new repository or copy an existing one"""
356 """create a new repository or copy an existing one"""
354
357
355 if source:
358 if source:
356 paths = {}
359 paths = {}
357 for name, path in ui.configitems("paths"):
360 for name, path in ui.configitems("paths"):
358 paths[name] = path
361 paths[name] = path
359
362
360 if source in paths: source = paths[source]
363 if source in paths: source = paths[source]
361
364
362 link = 0
365 link = 0
363 if not source.startswith("http://"):
366 if not source.startswith("http://"):
364 d1 = os.stat(os.getcwd()).st_dev
367 d1 = os.stat(os.getcwd()).st_dev
365 d2 = os.stat(source).st_dev
368 d2 = os.stat(source).st_dev
366 if d1 == d2: link = 1
369 if d1 == d2: link = 1
367
370
368 if link:
371 if link:
369 ui.debug("copying by hardlink\n")
372 ui.debug("copying by hardlink\n")
370 os.system("cp -al %s/.hg .hg" % source)
373 os.system("cp -al %s/.hg .hg" % source)
371 try:
374 try:
372 os.remove(".hg/dirstate")
375 os.remove(".hg/dirstate")
373 except: pass
376 except: pass
374
377
375 repo = hg.repository(ui, ".")
378 repo = hg.repository(ui, ".")
376
379
377 else:
380 else:
378 repo = hg.repository(ui, ".", create=1)
381 repo = hg.repository(ui, ".", create=1)
379 other = hg.repository(ui, source)
382 other = hg.repository(ui, source)
380 cg = repo.getchangegroup(other)
383 cg = repo.getchangegroup(other)
381 repo.addchangegroup(cg)
384 repo.addchangegroup(cg)
382 else:
385 else:
383 repo = hg.repository(ui, ".", create=1)
386 repo = hg.repository(ui, ".", create=1)
384
387
385 f = repo.opener("hgrc", "w")
388 f = repo.opener("hgrc", "w")
386 f.write("[paths]\n")
389 f.write("[paths]\n")
387 f.write("default = %s\n" % source)
390 f.write("default = %s\n" % source)
388
391
389 def log(ui, repo, f):
392 def log(ui, repo, f):
390 """show the revision history of a single file"""
393 """show the revision history of a single file"""
391 f = relpath(repo, [f])[0]
394 f = relpath(repo, [f])[0]
392
395
393 r = repo.file(f)
396 r = repo.file(f)
394 for i in range(r.count() - 1, -1, -1):
397 for i in range(r.count() - 1, -1, -1):
395 show_changeset(ui, repo, filelog=r, rev=i)
398 show_changeset(ui, repo, filelog=r, rev=i)
396
399
397 def manifest(ui, repo, rev = []):
400 def manifest(ui, repo, rev = []):
398 """output the latest or given revision of the project manifest"""
401 """output the latest or given revision of the project manifest"""
399 n = repo.manifest.tip()
402 n = repo.manifest.tip()
400 if rev:
403 if rev:
401 n = repo.manifest.lookup(rev)
404 n = repo.manifest.lookup(rev)
402 m = repo.manifest.read(n)
405 m = repo.manifest.read(n)
403 mf = repo.manifest.readflags(n)
406 mf = repo.manifest.readflags(n)
404 files = m.keys()
407 files = m.keys()
405 files.sort()
408 files.sort()
406
409
407 for f in files:
410 for f in files:
408 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
411 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
409
412
410 def parents(ui, repo, node = None):
413 def parents(ui, repo, node = None):
411 '''show the parents of the current working dir'''
414 '''show the parents of the current working dir'''
412 if node:
415 if node:
413 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
416 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
414 else:
417 else:
415 p = repo.dirstate.parents()
418 p = repo.dirstate.parents()
416
419
417 for n in p:
420 for n in p:
418 if n != hg.nullid:
421 if n != hg.nullid:
419 show_changeset(ui, repo, changenode=n)
422 show_changeset(ui, repo, changenode=n)
420
423
421 def patch(ui, repo, patch1, *patches, **opts):
424 def patch(ui, repo, patch1, *patches, **opts):
422 """import an ordered set of patches"""
425 """import an ordered set of patches"""
423 try:
426 try:
424 import psyco
427 import psyco
425 psyco.full()
428 psyco.full()
426 except:
429 except:
427 pass
430 pass
428
431
429 patches = (patch1,) + patches
432 patches = (patch1,) + patches
430
433
431 d = opts["base"]
434 d = opts["base"]
432 strip = opts["strip"]
435 strip = opts["strip"]
433 quiet = opts["quiet"] and "> /dev/null" or ""
436 quiet = opts["quiet"] and "> /dev/null" or ""
434
437
435 for patch in patches:
438 for patch in patches:
436 ui.status("applying %s\n" % patch)
439 ui.status("applying %s\n" % patch)
437 pf = os.path.join(d, patch)
440 pf = os.path.join(d, patch)
438
441
439 text = ""
442 text = ""
440 for l in file(pf):
443 for l in file(pf):
441 if l[:4] == "--- ": break
444 if l[:4] == "--- ": break
442 text += l
445 text += l
443
446
444 # make sure text isn't empty
447 # make sure text isn't empty
445 if not text: text = "imported patch %s\n" % patch
448 if not text: text = "imported patch %s\n" % patch
446
449
447 f = os.popen("patch -p%d < %s" % (strip, pf))
450 f = os.popen("patch -p%d < %s" % (strip, pf))
448 files = []
451 files = []
449 for l in f.read().splitlines():
452 for l in f.read().splitlines():
450 l.rstrip('\r\n');
453 l.rstrip('\r\n');
451 if not quiet:
454 if not quiet:
452 print l
455 print l
453 if l[:14] == 'patching file ':
456 if l[:14] == 'patching file ':
454 files.append(l[14:])
457 files.append(l[14:])
455 f.close()
458 f.close()
456
459
457 if len(files) > 0:
460 if len(files) > 0:
458 addremove(ui, repo, *files)
461 addremove(ui, repo, *files)
459 repo.commit(files, text)
462 repo.commit(files, text)
460
463
461 def pull(ui, repo, source="default"):
464 def pull(ui, repo, source="default"):
462 """pull changes from the specified source"""
465 """pull changes from the specified source"""
463 paths = {}
466 paths = {}
464 for name, path in ui.configitems("paths"):
467 for name, path in ui.configitems("paths"):
465 paths[name] = path
468 paths[name] = path
466
469
467 if source in paths: source = paths[source]
470 if source in paths: source = paths[source]
468
471
469 other = hg.repository(ui, source)
472 other = hg.repository(ui, source)
470 cg = repo.getchangegroup(other)
473 cg = repo.getchangegroup(other)
471 repo.addchangegroup(cg)
474 repo.addchangegroup(cg)
472
475
473 def push(ui, repo, dest="default-push"):
476 def push(ui, repo, dest="default-push"):
474 """push changes to the specified destination"""
477 """push changes to the specified destination"""
475 paths = {}
478 paths = {}
476 for name, path in ui.configitems("paths"):
479 for name, path in ui.configitems("paths"):
477 paths[name] = path
480 paths[name] = path
478
481
479 if dest in paths: dest = paths[dest]
482 if dest in paths: dest = paths[dest]
480
483
481 if not dest.startswith("ssh://"):
484 if not dest.startswith("ssh://"):
482 ui.warn("abort: can only push to ssh:// destinations currently\n")
485 ui.warn("abort: can only push to ssh:// destinations currently\n")
483 return 1
486 return 1
484
487
485 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
488 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
486 if not m:
489 if not m:
487 ui.warn("abort: couldn't parse destination %s\n" % dest)
490 ui.warn("abort: couldn't parse destination %s\n" % dest)
488 return 1
491 return 1
489
492
490 user, host, port, path = map(m.group, (2, 3, 5, 7))
493 user, host, port, path = map(m.group, (2, 3, 5, 7))
491 host = user and ("%s@%s" % (user, host)) or host
494 host = user and ("%s@%s" % (user, host)) or host
492 port = port and (" -p %s") % port or ""
495 port = port and (" -p %s") % port or ""
493 path = path or ""
496 path = path or ""
494
497
495 sport = random.randrange(30000, 60000)
498 sport = random.randrange(30000, 60000)
496 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
499 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
497 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
500 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
498
501
499 child = os.fork()
502 child = os.fork()
500 if not child:
503 if not child:
501 sys.stdout = file("/dev/null", "w")
504 sys.stdout = file("/dev/null", "w")
502 sys.stderr = sys.stdout
505 sys.stderr = sys.stdout
503 hgweb.server(repo.root, "pull", "", "localhost", sport)
506 hgweb.server(repo.root, "pull", "", "localhost", sport)
504 else:
507 else:
505 r = os.system(cmd)
508 r = os.system(cmd)
506 os.kill(child, signal.SIGTERM)
509 os.kill(child, signal.SIGTERM)
507 return r
510 return r
508
511
509 def rawcommit(ui, repo, flist, **rc):
512 def rawcommit(ui, repo, flist, **rc):
510 "raw commit interface"
513 "raw commit interface"
511
514
512 text = rc['text']
515 text = rc['text']
513 if not text and rc['logfile']:
516 if not text and rc['logfile']:
514 try: text = open(rc['logfile']).read()
517 try: text = open(rc['logfile']).read()
515 except IOError: pass
518 except IOError: pass
516 if not text and not rc['logfile']:
519 if not text and not rc['logfile']:
517 print "missing commit text"
520 print "missing commit text"
518 return 1
521 return 1
519
522
520 files = relpath(repo, flist)
523 files = relpath(repo, flist)
521 if rc['files']:
524 if rc['files']:
522 files += open(rc['files']).read().splitlines()
525 files += open(rc['files']).read().splitlines()
523
526
524 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
527 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
525
528
526 def recover(ui, repo):
529 def recover(ui, repo):
527 """roll back an interrupted transaction"""
530 """roll back an interrupted transaction"""
528 repo.recover()
531 repo.recover()
529
532
530 def remove(ui, repo, file, *files):
533 def remove(ui, repo, file, *files):
531 """remove the specified files on the next commit"""
534 """remove the specified files on the next commit"""
532 repo.remove(relpath(repo, (file,) + files))
535 repo.remove(relpath(repo, (file,) + files))
533
536
534 def serve(ui, repo, **opts):
537 def serve(ui, repo, **opts):
535 """export the repository via HTTP"""
538 """export the repository via HTTP"""
536 hgweb.server(repo.root, opts["name"], opts["templates"],
539 hgweb.server(repo.root, opts["name"], opts["templates"],
537 opts["address"], opts["port"])
540 opts["address"], opts["port"])
538
541
539 def status(ui, repo):
542 def status(ui, repo):
540 '''show changed files in the working directory
543 '''show changed files in the working directory
541
544
542 C = changed
545 C = changed
543 A = added
546 A = added
544 R = removed
547 R = removed
545 ? = not tracked'''
548 ? = not tracked'''
546
549
547 (c, a, d, u) = repo.diffdir(os.getcwd())
550 (c, a, d, u) = repo.diffdir(os.getcwd())
548 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
551 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
549
552
550 for f in c: print "C", f
553 for f in c: print "C", f
551 for f in a: print "A", f
554 for f in a: print "A", f
552 for f in d: print "R", f
555 for f in d: print "R", f
553 for f in u: print "?", f
556 for f in u: print "?", f
554
557
555 def tags(ui, repo):
558 def tags(ui, repo):
556 """list repository tags"""
559 """list repository tags"""
557
560
558 l = repo.tagslist()
561 l = repo.tagslist()
559 l.reverse()
562 l.reverse()
560 for t,n in l:
563 for t,n in l:
561 try:
564 try:
562 r = repo.changelog.rev(n)
565 r = repo.changelog.rev(n)
563 except KeyError:
566 except KeyError:
564 r = "?"
567 r = "?"
565 print "%-30s %5d:%s" % (t, repo.changelog.rev(n), hg.hex(n))
568 print "%-30s %5d:%s" % (t, repo.changelog.rev(n), hg.hex(n))
566
569
567 def tip(ui, repo):
570 def tip(ui, repo):
568 """show the tip revision"""
571 """show the tip revision"""
569 n = repo.changelog.tip()
572 n = repo.changelog.tip()
570 show_changeset(ui, repo, changenode=n)
573 show_changeset(ui, repo, changenode=n)
571
574
572 def undo(ui, repo):
575 def undo(ui, repo):
573 """undo the last transaction"""
576 """undo the last transaction"""
574 repo.undo()
577 repo.undo()
575
578
576 def update(ui, repo, node=None, merge=False, clean=False):
579 def update(ui, repo, node=None, merge=False, clean=False):
577 '''update or merge working directory
580 '''update or merge working directory
578
581
579 If there are no outstanding changes in the working directory and
582 If there are no outstanding changes in the working directory and
580 there is a linear relationship between the current version and the
583 there is a linear relationship between the current version and the
581 requested version, the result is the requested version.
584 requested version, the result is the requested version.
582
585
583 Otherwise the result is a merge between the contents of the
586 Otherwise the result is a merge between the contents of the
584 current working directory and the requested version. Files that
587 current working directory and the requested version. Files that
585 changed between either parent are marked as changed for the next
588 changed between either parent are marked as changed for the next
586 commit and a commit must be performed before any further updates
589 commit and a commit must be performed before any further updates
587 are allowed.
590 are allowed.
588 '''
591 '''
589 node = node and repo.lookup(node) or repo.changelog.tip()
592 node = node and repo.lookup(node) or repo.changelog.tip()
590 return repo.update(node, allow=merge, force=clean)
593 return repo.update(node, allow=merge, force=clean)
591
594
592 def verify(ui, repo):
595 def verify(ui, repo):
593 """verify the integrity of the repository"""
596 """verify the integrity of the repository"""
594 return repo.verify()
597 return repo.verify()
595
598
596 # Command options and aliases are listed here, alphabetically
599 # Command options and aliases are listed here, alphabetically
597
600
598 table = {
601 table = {
599 "add": (add, [], "hg add [files]"),
602 "add": (add, [], "hg add [files]"),
600 "addremove": (addremove, [], "hg addremove [files]"),
603 "addremove": (addremove, [], "hg addremove [files]"),
601 "ann|annotate": (annotate,
604 "ann|annotate": (annotate,
602 [('r', 'revision', '', 'revision'),
605 [('r', 'revision', '', 'revision'),
603 ('u', 'user', None, 'show user'),
606 ('u', 'user', None, 'show user'),
604 ('n', 'number', None, 'show revision number'),
607 ('n', 'number', None, 'show revision number'),
605 ('c', 'changeset', None, 'show changeset')],
608 ('c', 'changeset', None, 'show changeset')],
606 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
609 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
607 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
610 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
608 "commit|ci": (commit,
611 "commit|ci": (commit,
609 [('t', 'text', "", 'commit text'),
612 [('t', 'text', "", 'commit text'),
610 ('A', 'addremove', None, 'run add/remove during commit'),
613 ('A', 'addremove', None, 'run add/remove during commit'),
611 ('l', 'logfile', "", 'commit text file'),
614 ('l', 'logfile', "", 'commit text file'),
612 ('d', 'date', "", 'data'),
615 ('d', 'date', "", 'data'),
613 ('u', 'user', "", 'user')],
616 ('u', 'user', "", 'user')],
614 'hg commit [files]'),
617 'hg commit [files]'),
615 "copy": (copy, [], 'hg copy <source> <dest>'),
618 "copy": (copy, [], 'hg copy <source> <dest>'),
616 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
619 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
617 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
620 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
618 "debugindex": (debugindex, [], 'debugindex <file>'),
621 "debugindex": (debugindex, [], 'debugindex <file>'),
619 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
622 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
620 "diff": (diff, [('r', 'rev', [], 'revision')],
623 "diff": (diff, [('r', 'rev', [], 'revision')],
621 'hg diff [-r A] [-r B] [files]'),
624 'hg diff [-r A] [-r B] [files]'),
622 "export": (export, [], "hg export <changeset>"),
625 "export": (export, [], "hg export <changeset>"),
623 "forget": (forget, [], "hg forget [files]"),
626 "forget": (forget, [], "hg forget [files]"),
624 "heads": (heads, [], 'hg heads'),
627 "heads": (heads, [], 'hg heads'),
625 "history": (history, [], 'hg history'),
628 "history": (history, [], 'hg history'),
626 "help": (help, [], 'hg help [command]'),
629 "help": (help, [], 'hg help [command]'),
627 "identify|id": (identify, [], 'hg identify'),
630 "identify|id": (identify, [], 'hg identify'),
628 "init": (init, [], 'hg init [url]'),
631 "init": (init, [], 'hg init [url]'),
629 "log": (log, [], 'hg log <file>'),
632 "log": (log, [], 'hg log <file>'),
630 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
633 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
631 "parents": (parents, [], 'hg parents [node]'),
634 "parents": (parents, [], 'hg parents [node]'),
632 "patch|import": (patch,
635 "patch|import": (patch,
633 [('p', 'strip', 1, 'path strip'),
636 [('p', 'strip', 1, 'path strip'),
634 ('b', 'base', "", 'base path'),
637 ('b', 'base', "", 'base path'),
635 ('q', 'quiet', "", 'silence diff')],
638 ('q', 'quiet', "", 'silence diff')],
636 "hg import [options] patches"),
639 "hg import [options] patches"),
637 "pull|merge": (pull, [], 'hg pull [source]'),
640 "pull|merge": (pull, [], 'hg pull [source]'),
638 "push": (push, [], 'hg push <destination>'),
641 "push": (push, [], 'hg push <destination>'),
639 "rawcommit": (rawcommit,
642 "rawcommit": (rawcommit,
640 [('p', 'parent', [], 'parent'),
643 [('p', 'parent', [], 'parent'),
641 ('d', 'date', "", 'data'),
644 ('d', 'date', "", 'data'),
642 ('u', 'user', "", 'user'),
645 ('u', 'user', "", 'user'),
643 ('F', 'files', "", 'file list'),
646 ('F', 'files', "", 'file list'),
644 ('t', 'text', "", 'commit text'),
647 ('t', 'text', "", 'commit text'),
645 ('l', 'logfile', "", 'commit text file')],
648 ('l', 'logfile', "", 'commit text file')],
646 'hg rawcommit [options] [files]'),
649 'hg rawcommit [options] [files]'),
647 "recover": (recover, [], "hg recover"),
650 "recover": (recover, [], "hg recover"),
648 "remove": (remove, [], "hg remove [files]"),
651 "remove": (remove, [], "hg remove [files]"),
649 "serve": (serve, [('p', 'port', 8000, 'listen port'),
652 "serve": (serve, [('p', 'port', 8000, 'listen port'),
650 ('a', 'address', '', 'interface address'),
653 ('a', 'address', '', 'interface address'),
651 ('n', 'name', os.getcwd(), 'repository name'),
654 ('n', 'name', os.getcwd(), 'repository name'),
652 ('t', 'templates', "", 'template map')],
655 ('t', 'templates', "", 'template map')],
653 "hg serve [options]"),
656 "hg serve [options]"),
654 "status": (status, [], 'hg status'),
657 "status": (status, [], 'hg status'),
655 "tags": (tags, [], 'hg tags'),
658 "tags": (tags, [], 'hg tags'),
656 "tip": (tip, [], 'hg tip'),
659 "tip": (tip, [], 'hg tip'),
657 "undo": (undo, [], 'hg undo'),
660 "undo": (undo, [], 'hg undo'),
658 "update|up|checkout|co|resolve": (update,
661 "update|up|checkout|co|resolve": (update,
659 [('m', 'merge', None,
662 [('m', 'merge', None,
660 'allow merging of conflicts'),
663 'allow merging of conflicts'),
661 ('C', 'clean', None,
664 ('C', 'clean', None,
662 'overwrite locally modified files')],
665 'overwrite locally modified files')],
663 'hg update [options] [node]'),
666 'hg update [options] [node]'),
664 "verify": (verify, [], 'hg verify'),
667 "verify": (verify, [], 'hg verify'),
665 }
668 }
666
669
667 norepo = "init branch help debugindex debugindexdot"
670 norepo = "init branch help debugindex debugindexdot"
668
671
669 def find(cmd):
672 def find(cmd):
670 i = None
673 i = None
671 for e in table.keys():
674 for e in table.keys():
672 if re.match("(%s)$" % e, cmd):
675 if re.match("(%s)$" % e, cmd):
673 return table[e]
676 return table[e]
674
677
675 raise UnknownCommand(cmd)
678 raise UnknownCommand(cmd)
676
679
677 class SignalInterrupt(Exception): pass
680 class SignalInterrupt(Exception): pass
678
681
679 def catchterm(*args):
682 def catchterm(*args):
680 raise SignalInterrupt
683 raise SignalInterrupt
681
684
682 def run():
685 def run():
683 sys.exit(dispatch(sys.argv[1:]))
686 sys.exit(dispatch(sys.argv[1:]))
684
687
685 def dispatch(args):
688 def dispatch(args):
686 options = {}
689 options = {}
687 opts = [('v', 'verbose', None, 'verbose'),
690 opts = [('v', 'verbose', None, 'verbose'),
688 ('d', 'debug', None, 'debug'),
691 ('d', 'debug', None, 'debug'),
689 ('q', 'quiet', None, 'quiet'),
692 ('q', 'quiet', None, 'quiet'),
690 ('p', 'profile', None, 'profile'),
693 ('p', 'profile', None, 'profile'),
691 ('y', 'noninteractive', None, 'run non-interactively'),
694 ('y', 'noninteractive', None, 'run non-interactively'),
692 ]
695 ]
693
696
694 args = fancyopts.fancyopts(args, opts, options,
697 args = fancyopts.fancyopts(args, opts, options,
695 'hg [options] <command> [options] [files]')
698 'hg [options] <command> [options] [files]')
696
699
697 if not args:
700 if not args:
698 cmd = "help"
701 cmd = "help"
699 else:
702 else:
700 cmd, args = args[0], args[1:]
703 cmd, args = args[0], args[1:]
701
704
702 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
705 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
703 not options["noninteractive"])
706 not options["noninteractive"])
704
707
705 try:
708 try:
706 i = find(cmd)
709 i = find(cmd)
707 except UnknownCommand:
710 except UnknownCommand:
708 u.warn("hg: unknown command '%s'\n" % cmd)
711 u.warn("hg: unknown command '%s'\n" % cmd)
709 help(u)
712 help(u)
710 sys.exit(1)
713 sys.exit(1)
711
714
712 signal.signal(signal.SIGTERM, catchterm)
715 signal.signal(signal.SIGTERM, catchterm)
713
716
714 cmdoptions = {}
717 cmdoptions = {}
715 try:
718 try:
716 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
719 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
717 except fancyopts.getopt.GetoptError, inst:
720 except fancyopts.getopt.GetoptError, inst:
718 u.warn("hg %s: %s\n" % (cmd, inst))
721 u.warn("hg %s: %s\n" % (cmd, inst))
719 help(u, cmd)
722 help(u, cmd)
720 sys.exit(-1)
723 sys.exit(-1)
721
724
722 if cmd not in norepo.split():
725 if cmd not in norepo.split():
723 repo = hg.repository(ui = u)
726 repo = hg.repository(ui = u)
724 d = lambda: i[0](u, repo, *args, **cmdoptions)
727 d = lambda: i[0](u, repo, *args, **cmdoptions)
725 else:
728 else:
726 d = lambda: i[0](u, *args, **cmdoptions)
729 d = lambda: i[0](u, *args, **cmdoptions)
727
730
728 try:
731 try:
729 if options['profile']:
732 if options['profile']:
730 import hotshot, hotshot.stats
733 import hotshot, hotshot.stats
731 prof = hotshot.Profile("hg.prof")
734 prof = hotshot.Profile("hg.prof")
732 r = prof.runcall(d)
735 r = prof.runcall(d)
733 prof.close()
736 prof.close()
734 stats = hotshot.stats.load("hg.prof")
737 stats = hotshot.stats.load("hg.prof")
735 stats.strip_dirs()
738 stats.strip_dirs()
736 stats.sort_stats('time', 'calls')
739 stats.sort_stats('time', 'calls')
737 stats.print_stats(40)
740 stats.print_stats(40)
738 return r
741 return r
739 else:
742 else:
740 return d()
743 return d()
741 except SignalInterrupt:
744 except SignalInterrupt:
742 u.warn("killed!\n")
745 u.warn("killed!\n")
743 except KeyboardInterrupt:
746 except KeyboardInterrupt:
744 u.warn("interrupted!\n")
747 u.warn("interrupted!\n")
745 except IOError, inst:
748 except IOError, inst:
746 if inst.errno == errno.EPIPE:
749 if inst.errno == errno.EPIPE:
747 u.warn("broken pipe\n")
750 u.warn("broken pipe\n")
748 else:
751 else:
749 raise
752 raise
750 except TypeError, inst:
753 except TypeError, inst:
751 # was this an argument error?
754 # was this an argument error?
752 tb = traceback.extract_tb(sys.exc_info()[2])
755 tb = traceback.extract_tb(sys.exc_info()[2])
753 if len(tb) > 2: # no
756 if len(tb) > 2: # no
754 raise
757 raise
755 u.debug(inst, "\n")
758 u.debug(inst, "\n")
756 u.warn("%s: invalid arguments\n" % i[0].__name__)
759 u.warn("%s: invalid arguments\n" % i[0].__name__)
757 help(u, cmd)
760 help(u, cmd)
758 sys.exit(-1)
761 sys.exit(-1)
759
762
General Comments 0
You need to be logged in to leave comments. Login now