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