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