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