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