##// END OF EJS Templates
Handle unknown commands nicely...
mpm@selenic.com -
r252:5eda6c54 default
parent child Browse files
Show More
@@ -1,587 +1,591 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, time, mdiff
8 import os, re, sys, signal, time, mdiff
9 from mercurial import fancyopts, ui, hg
9 from mercurial import fancyopts, ui, hg
10
10
11 class UnknownCommand(Exception): pass
11 class UnknownCommand(Exception): pass
12
12
13 def filterfiles(filters, files):
13 def filterfiles(filters, files):
14 l = [ x for x in files if x in filters ]
14 l = [ x for x in files if x in filters ]
15
15
16 for t in filters:
16 for t in filters:
17 if t and t[-1] != os.sep: t += os.sep
17 if t and t[-1] != os.sep: t += os.sep
18 l += [ x for x in files if x.startswith(t) ]
18 l += [ x for x in files if x.startswith(t) ]
19 return l
19 return l
20
20
21 def relfilter(repo, files):
21 def relfilter(repo, files):
22 if os.getcwd() != repo.root:
22 if os.getcwd() != repo.root:
23 p = os.getcwd()[len(repo.root) + 1: ]
23 p = os.getcwd()[len(repo.root) + 1: ]
24 return filterfiles(p, files)
24 return filterfiles(p, files)
25 return files
25 return files
26
26
27 def relpath(repo, args):
27 def relpath(repo, args):
28 if os.getcwd() != repo.root:
28 if os.getcwd() != repo.root:
29 p = os.getcwd()[len(repo.root) + 1: ]
29 p = os.getcwd()[len(repo.root) + 1: ]
30 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
30 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
31 return args
31 return args
32
32
33 def dodiff(repo, files = None, node1 = None, node2 = None):
33 def dodiff(repo, files = None, node1 = None, node2 = None):
34 def date(c):
34 def date(c):
35 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
35 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
36
36
37 if node2:
37 if node2:
38 change = repo.changelog.read(node2)
38 change = repo.changelog.read(node2)
39 mmap2 = repo.manifest.read(change[0])
39 mmap2 = repo.manifest.read(change[0])
40 (c, a, d) = repo.diffrevs(node1, node2)
40 (c, a, d) = repo.diffrevs(node1, node2)
41 def read(f): return repo.file(f).read(mmap2[f])
41 def read(f): return repo.file(f).read(mmap2[f])
42 date2 = date(change)
42 date2 = date(change)
43 else:
43 else:
44 date2 = time.asctime()
44 date2 = time.asctime()
45 (c, a, d, u) = repo.diffdir(repo.root, node1)
45 (c, a, d, u) = repo.diffdir(repo.root, node1)
46 if not node1:
46 if not node1:
47 node1 = repo.dirstate.parents()[0]
47 node1 = repo.dirstate.parents()[0]
48 def read(f): return file(os.path.join(repo.root, f)).read()
48 def read(f): return file(os.path.join(repo.root, f)).read()
49
49
50 change = repo.changelog.read(node1)
50 change = repo.changelog.read(node1)
51 mmap = repo.manifest.read(change[0])
51 mmap = repo.manifest.read(change[0])
52 date1 = date(change)
52 date1 = date(change)
53
53
54 if files:
54 if files:
55 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
55 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
56
56
57 for f in c:
57 for f in c:
58 to = repo.file(f).read(mmap[f])
58 to = repo.file(f).read(mmap[f])
59 tn = read(f)
59 tn = read(f)
60 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
60 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
61 for f in a:
61 for f in a:
62 to = ""
62 to = ""
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 d:
65 for f in d:
66 to = repo.file(f).read(mmap[f])
66 to = repo.file(f).read(mmap[f])
67 tn = ""
67 tn = ""
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
69
69
70 def help(ui, cmd=None):
70 def help(ui, cmd=None):
71 '''show help'''
71 '''show help'''
72 if cmd:
72 if cmd:
73 try:
73 try:
74 i = find(cmd)
74 i = find(cmd)
75 ui.write("%s\n\n" % i[2])
75 ui.write("%s\n\n" % i[2])
76 ui.write(i[0].__doc__, "\n")
76 ui.write(i[0].__doc__, "\n")
77 except UnknownCommand:
77 except UnknownCommand:
78 ui.warn("unknown command %s", cmd)
78 ui.warn("unknown command %s" % cmd)
79 sys.exit(0)
79 sys.exit(0)
80
80
81 ui.status("""\
81 ui.status("""\
82 hg commands:
82 hg commands:
83
83
84 add [files...] add the given files in the next commit
84 add [files...] add the given files in the next commit
85 addremove add all new files, delete all missing files
85 addremove add all new files, delete all missing files
86 annotate [files...] show changeset number per file line
86 annotate [files...] show changeset number per file line
87 branch <path> create a branch of <path> in this directory
87 branch <path> create a branch of <path> in this directory
88 checkout [changeset] checkout the latest or given changeset
88 checkout [changeset] checkout the latest or given changeset
89 commit commit all changes to the repository
89 commit commit all changes to the repository
90 diff [files...] diff working directory (or selected files)
90 diff [files...] diff working directory (or selected files)
91 dump <file> [rev] dump the latest or given revision of a file
91 dump <file> [rev] dump the latest or given revision of a file
92 dumpmanifest [rev] dump the latest or given revision of the manifest
92 dumpmanifest [rev] dump the latest or given revision of the manifest
93 export <rev> dump the changeset header and diffs for a revision
93 export <rev> dump the changeset header and diffs for a revision
94 history show changeset history
94 history show changeset history
95 init create a new repository in this directory
95 init create a new repository in this directory
96 log <file> show revision history of a single file
96 log <file> show revision history of a single file
97 merge <path> merge changes from <path> into local repository
97 merge <path> merge changes from <path> into local repository
98 recover rollback an interrupted transaction
98 recover rollback an interrupted transaction
99 remove [files...] remove the given files in the next commit
99 remove [files...] remove the given files in the next commit
100 serve export the repository via HTTP
100 serve export the repository via HTTP
101 status show new, missing, and changed files in working dir
101 status show new, missing, and changed files in working dir
102 tags show current changeset tags
102 tags show current changeset tags
103 undo undo the last transaction
103 undo undo the last transaction
104 """)
104 """)
105
105
106 def add(ui, repo, file, *files):
106 def add(ui, repo, file, *files):
107 '''add the specified files on the next commit'''
107 '''add the specified files on the next commit'''
108 repo.add(relpath(repo, (file,) + files))
108 repo.add(relpath(repo, (file,) + files))
109
109
110 def addremove(ui, repo):
110 def addremove(ui, repo):
111 (c, a, d, u) = repo.diffdir(repo.root)
111 (c, a, d, u) = repo.diffdir(repo.root)
112 repo.add(a)
112 repo.add(a)
113 repo.remove(d)
113 repo.remove(d)
114
114
115 def annotate(u, repo, file, *files, **ops):
115 def annotate(u, repo, file, *files, **ops):
116 def getnode(rev):
116 def getnode(rev):
117 return hg.short(repo.changelog.node(rev))
117 return hg.short(repo.changelog.node(rev))
118
118
119 def getname(rev):
119 def getname(rev):
120 try:
120 try:
121 return bcache[rev]
121 return bcache[rev]
122 except KeyError:
122 except KeyError:
123 cl = repo.changelog.read(repo.changelog.node(rev))
123 cl = repo.changelog.read(repo.changelog.node(rev))
124 name = cl[1]
124 name = cl[1]
125 f = name.find('@')
125 f = name.find('@')
126 if f >= 0:
126 if f >= 0:
127 name = name[:f]
127 name = name[:f]
128 bcache[rev] = name
128 bcache[rev] = name
129 return name
129 return name
130
130
131 bcache = {}
131 bcache = {}
132 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
132 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
133 if not ops['user'] and not ops['changeset']:
133 if not ops['user'] and not ops['changeset']:
134 ops['number'] = 1
134 ops['number'] = 1
135
135
136 node = repo.dirstate.parents()[0]
136 node = repo.dirstate.parents()[0]
137 if ops['revision']:
137 if ops['revision']:
138 node = repo.changelog.lookup(ops['revision'])
138 node = repo.changelog.lookup(ops['revision'])
139 change = repo.changelog.read(node)
139 change = repo.changelog.read(node)
140 mmap = repo.manifest.read(change[0])
140 mmap = repo.manifest.read(change[0])
141 maxuserlen = 0
141 maxuserlen = 0
142 maxchangelen = 0
142 maxchangelen = 0
143 for f in relpath(repo, (file,) + files):
143 for f in relpath(repo, (file,) + files):
144 lines = repo.file(f).annotate(mmap[f])
144 lines = repo.file(f).annotate(mmap[f])
145 pieces = []
145 pieces = []
146
146
147 for o, f in opmap:
147 for o, f in opmap:
148 if ops[o]:
148 if ops[o]:
149 l = [ f(n) for n,t in lines ]
149 l = [ f(n) for n,t in lines ]
150 m = max(map(len, l))
150 m = max(map(len, l))
151 pieces.append([ "%*s" % (m, x) for x in l])
151 pieces.append([ "%*s" % (m, x) for x in l])
152
152
153 for p,l in zip(zip(*pieces), lines):
153 for p,l in zip(zip(*pieces), lines):
154 u.write(" ".join(p) + ": " + l[1])
154 u.write(" ".join(p) + ": " + l[1])
155
155
156 def branch(ui, path):
156 def branch(ui, path):
157 '''branch from a local repository'''
157 '''branch from a local repository'''
158 # this should eventually support remote repos
158 # this should eventually support remote repos
159 os.system("cp -al %s/.hg .hg" % path)
159 os.system("cp -al %s/.hg .hg" % path)
160
160
161 def cat(ui, repo, file, rev = []):
161 def cat(ui, repo, file, rev = []):
162 r = repo.file(file)
162 r = repo.file(file)
163 n = r.tip()
163 n = r.tip()
164 if rev: n = r.lookup(rev)
164 if rev: n = r.lookup(rev)
165 sys.stdout.write(r.read(n))
165 sys.stdout.write(r.read(n))
166
166
167 def checkout(ui, repo, changeset=None):
167 def checkout(ui, repo, changeset=None):
168 '''checkout a given changeset or the current tip'''
168 '''checkout a given changeset or the current tip'''
169 (c, a, d, u) = repo.diffdir(repo.root)
169 (c, a, d, u) = repo.diffdir(repo.root)
170 if c or a or d:
170 if c or a or d:
171 ui.warn("aborting (outstanding changes in working directory)\n")
171 ui.warn("aborting (outstanding changes in working directory)\n")
172 sys.exit(1)
172 sys.exit(1)
173
173
174 node = repo.changelog.tip()
174 node = repo.changelog.tip()
175 if changeset:
175 if changeset:
176 node = repo.lookup(changeset)
176 node = repo.lookup(changeset)
177 repo.checkout(node)
177 repo.checkout(node)
178
178
179 def commit(ui, repo, *files):
179 def commit(ui, repo, *files):
180 """commit the specified files or all outstanding changes"""
180 """commit the specified files or all outstanding changes"""
181 repo.commit(relpath(repo, files))
181 repo.commit(relpath(repo, files))
182
182
183 def debugaddchangegroup(ui, repo):
183 def debugaddchangegroup(ui, repo):
184 data = sys.stdin.read()
184 data = sys.stdin.read()
185 repo.addchangegroup(data)
185 repo.addchangegroup(data)
186
186
187 def debugchangegroup(ui, repo, roots):
187 def debugchangegroup(ui, repo, roots):
188 newer = repo.newer(map(repo.lookup, roots))
188 newer = repo.newer(map(repo.lookup, roots))
189 for chunk in repo.changegroup(newer):
189 for chunk in repo.changegroup(newer):
190 sys.stdout.write(chunk)
190 sys.stdout.write(chunk)
191
191
192 def debugindex(ui, file):
192 def debugindex(ui, file):
193 r = hg.revlog(open, file, "")
193 r = hg.revlog(open, file, "")
194 print " rev offset length base linkrev"+\
194 print " rev offset length base linkrev"+\
195 " p1 p2 nodeid"
195 " p1 p2 nodeid"
196 for i in range(r.count()):
196 for i in range(r.count()):
197 e = r.index[i]
197 e = r.index[i]
198 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
198 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
199 i, e[0], e[1], e[2], e[3],
199 i, e[0], e[1], e[2], e[3],
200 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
200 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
201
201
202 def debugindexdot(ui, file):
202 def debugindexdot(ui, file):
203 r = hg.revlog(open, file, "")
203 r = hg.revlog(open, file, "")
204 print "digraph G {"
204 print "digraph G {"
205 for i in range(r.count()):
205 for i in range(r.count()):
206 e = r.index[i]
206 e = r.index[i]
207 print "\t%d -> %d" % (r.rev(e[4]), i)
207 print "\t%d -> %d" % (r.rev(e[4]), i)
208 if e[5] != hg.nullid:
208 if e[5] != hg.nullid:
209 print "\t%d -> %d" % (r.rev(e[5]), i)
209 print "\t%d -> %d" % (r.rev(e[5]), i)
210 print "}"
210 print "}"
211
211
212 def diff(ui, repo, *files, **opts):
212 def diff(ui, repo, *files, **opts):
213 revs = []
213 revs = []
214 if opts['rev']:
214 if opts['rev']:
215 revs = map(lambda x: repo.lookup(x), opts['rev'])
215 revs = map(lambda x: repo.lookup(x), opts['rev'])
216
216
217 if len(revs) > 2:
217 if len(revs) > 2:
218 self.ui.warn("too many revisions to diff\n")
218 self.ui.warn("too many revisions to diff\n")
219 sys.exit(1)
219 sys.exit(1)
220
220
221 if files:
221 if files:
222 files = relpath(repo, files)
222 files = relpath(repo, files)
223 else:
223 else:
224 files = relpath(repo, [""])
224 files = relpath(repo, [""])
225
225
226 dodiff(repo, files, *revs)
226 dodiff(repo, files, *revs)
227
227
228 def export(ui, repo, changeset):
228 def export(ui, repo, changeset):
229 node = repo.lookup(changeset)
229 node = repo.lookup(changeset)
230 prev, other = repo.changelog.parents(node)
230 prev, other = repo.changelog.parents(node)
231 change = repo.changelog.read(node)
231 change = repo.changelog.read(node)
232 print "# HG changeset patch"
232 print "# HG changeset patch"
233 print "# User %s" % change[1]
233 print "# User %s" % change[1]
234 print "# Node ID %s" % hg.hex(node)
234 print "# Node ID %s" % hg.hex(node)
235 print "# Parent %s" % hg.hex(prev)
235 print "# Parent %s" % hg.hex(prev)
236 print
236 print
237 if other != hg.nullid:
237 if other != hg.nullid:
238 print "# Parent %s" % hg.hex(other)
238 print "# Parent %s" % hg.hex(other)
239 print change[4].rstrip()
239 print change[4].rstrip()
240 print
240 print
241
241
242 dodiff(repo, None, prev, node)
242 dodiff(repo, None, prev, node)
243
243
244 def forget(ui, repo, file, *files):
244 def forget(ui, repo, file, *files):
245 """don't add the specified files on the next commit"""
245 """don't add the specified files on the next commit"""
246 repo.forget(relpath(repo, (file,) + files))
246 repo.forget(relpath(repo, (file,) + files))
247
247
248 def heads(ui, repo):
248 def heads(ui, repo):
249 '''show current repository heads'''
249 '''show current repository heads'''
250 for n in repo.changelog.heads():
250 for n in repo.changelog.heads():
251 i = repo.changelog.rev(n)
251 i = repo.changelog.rev(n)
252 changes = repo.changelog.read(n)
252 changes = repo.changelog.read(n)
253 (p1, p2) = repo.changelog.parents(n)
253 (p1, p2) = repo.changelog.parents(n)
254 (h, h1, h2) = map(hg.hex, (n, p1, p2))
254 (h, h1, h2) = map(hg.hex, (n, p1, p2))
255 (i1, i2) = map(repo.changelog.rev, (p1, p2))
255 (i1, i2) = map(repo.changelog.rev, (p1, p2))
256 print "rev: %4d:%s" % (i, h)
256 print "rev: %4d:%s" % (i, h)
257 print "parents: %4d:%s" % (i1, h1)
257 print "parents: %4d:%s" % (i1, h1)
258 if i2: print " %4d:%s" % (i2, h2)
258 if i2: print " %4d:%s" % (i2, h2)
259 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
259 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
260 hg.hex(changes[0]))
260 hg.hex(changes[0]))
261 print "user:", changes[1]
261 print "user:", changes[1]
262 print "date:", time.asctime(
262 print "date:", time.asctime(
263 time.localtime(float(changes[2].split(' ')[0])))
263 time.localtime(float(changes[2].split(' ')[0])))
264 if ui.verbose: print "files:", " ".join(changes[3])
264 if ui.verbose: print "files:", " ".join(changes[3])
265 print "description:"
265 print "description:"
266 print changes[4]
266 print changes[4]
267
267
268 def history(ui, repo):
268 def history(ui, repo):
269 """show the changelog history"""
269 """show the changelog history"""
270 for i in range(repo.changelog.count()):
270 for i in range(repo.changelog.count()):
271 n = repo.changelog.node(i)
271 n = repo.changelog.node(i)
272 changes = repo.changelog.read(n)
272 changes = repo.changelog.read(n)
273 (p1, p2) = repo.changelog.parents(n)
273 (p1, p2) = repo.changelog.parents(n)
274 (h, h1, h2) = map(hg.hex, (n, p1, p2))
274 (h, h1, h2) = map(hg.hex, (n, p1, p2))
275 (i1, i2) = map(repo.changelog.rev, (p1, p2))
275 (i1, i2) = map(repo.changelog.rev, (p1, p2))
276 print "rev: %4d:%s" % (i, h)
276 print "rev: %4d:%s" % (i, h)
277 print "parents: %4d:%s" % (i1, h1)
277 print "parents: %4d:%s" % (i1, h1)
278 if i2: print " %4d:%s" % (i2, h2)
278 if i2: print " %4d:%s" % (i2, h2)
279 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
279 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
280 hg.hex(changes[0]))
280 hg.hex(changes[0]))
281 print "user:", changes[1]
281 print "user:", changes[1]
282 print "date:", time.asctime(
282 print "date:", time.asctime(
283 time.localtime(float(changes[2].split(' ')[0])))
283 time.localtime(float(changes[2].split(' ')[0])))
284 if ui.verbose: print "files:", " ".join(changes[3])
284 if ui.verbose: print "files:", " ".join(changes[3])
285 print "description:"
285 print "description:"
286 print changes[4]
286 print changes[4]
287
287
288 def patch(ui, repo, patches, opts):
288 def patch(ui, repo, patches, opts):
289 """import an ordered set of patches"""
289 """import an ordered set of patches"""
290 try:
290 try:
291 import psyco
291 import psyco
292 psyco.full()
292 psyco.full()
293 except:
293 except:
294 pass
294 pass
295
295
296 d = opts["base"]
296 d = opts["base"]
297 strip = opts["strip"]
297 strip = opts["strip"]
298 quiet = opts["quiet"] and "> /dev/null" or ""
298 quiet = opts["quiet"] and "> /dev/null" or ""
299
299
300 for patch in patches:
300 for patch in patches:
301 ui.status("applying %s\n" % patch)
301 ui.status("applying %s\n" % patch)
302 pf = os.path.join(d, patch)
302 pf = os.path.join(d, patch)
303
303
304 text = ""
304 text = ""
305 for l in file(pf):
305 for l in file(pf):
306 if l[:4] == "--- ": break
306 if l[:4] == "--- ": break
307 text += l
307 text += l
308
308
309 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
309 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
310 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
310 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
311 f.close()
311 f.close()
312
312
313 if files:
313 if files:
314 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
314 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
315 raise "patch failed!"
315 raise "patch failed!"
316 repo.commit(files, text)
316 repo.commit(files, text)
317
317
318 def init(ui):
318 def init(ui):
319 """create a repository"""
319 """create a repository"""
320 hg.repository(ui, ".", create=1)
320 hg.repository(ui, ".", create=1)
321
321
322 def log(ui, repo, f):
322 def log(ui, repo, f):
323 f = relpath(repo, [f])[0]
323 f = relpath(repo, [f])[0]
324
324
325 r = repo.file(f)
325 r = repo.file(f)
326 for i in range(r.count()):
326 for i in range(r.count()):
327 n = r.node(i)
327 n = r.node(i)
328 (p1, p2) = r.parents(n)
328 (p1, p2) = r.parents(n)
329 (h, h1, h2) = map(hg.hex, (n, p1, p2))
329 (h, h1, h2) = map(hg.hex, (n, p1, p2))
330 (i1, i2) = map(r.rev, (p1, p2))
330 (i1, i2) = map(r.rev, (p1, p2))
331 cr = r.linkrev(n)
331 cr = r.linkrev(n)
332 cn = hg.hex(repo.changelog.node(cr))
332 cn = hg.hex(repo.changelog.node(cr))
333 print "rev: %4d:%s" % (i, h)
333 print "rev: %4d:%s" % (i, h)
334 print "changeset: %4d:%s" % (cr, cn)
334 print "changeset: %4d:%s" % (cr, cn)
335 print "parents: %4d:%s" % (i1, h1)
335 print "parents: %4d:%s" % (i1, h1)
336 if i2: print " %4d:%s" % (i2, h2)
336 if i2: print " %4d:%s" % (i2, h2)
337 changes = repo.changelog.read(repo.changelog.node(cr))
337 changes = repo.changelog.read(repo.changelog.node(cr))
338 print "user: %s" % changes[1]
338 print "user: %s" % changes[1]
339 print "date: %s" % time.asctime(
339 print "date: %s" % time.asctime(
340 time.localtime(float(changes[2].split(' ')[0])))
340 time.localtime(float(changes[2].split(' ')[0])))
341 print "description:"
341 print "description:"
342 print changes[4].rstrip()
342 print changes[4].rstrip()
343 print
343 print
344
344
345 def manifest(ui, repo, rev = []):
345 def manifest(ui, repo, rev = []):
346 n = repo.manifest.tip()
346 n = repo.manifest.tip()
347 if rev:
347 if rev:
348 n = repo.manifest.lookup(rev)
348 n = repo.manifest.lookup(rev)
349 m = repo.manifest.read(n)
349 m = repo.manifest.read(n)
350 files = m.keys()
350 files = m.keys()
351 files.sort()
351 files.sort()
352
352
353 for f in files:
353 for f in files:
354 print hg.hex(m[f]), f
354 print hg.hex(m[f]), f
355
355
356 def parents(ui, repo, node = None):
356 def parents(ui, repo, node = None):
357 '''show the parents of the current working dir'''
357 '''show the parents of the current working dir'''
358 if node:
358 if node:
359 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
359 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
360 else:
360 else:
361 p = repo.dirstate.parents()
361 p = repo.dirstate.parents()
362
362
363 for n in p:
363 for n in p:
364 if n != hg.nullid:
364 if n != hg.nullid:
365 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
365 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
366
366
367 def pull(ui, repo, source):
367 def pull(ui, repo, source):
368 """pull changes from the specified source"""
368 """pull changes from the specified source"""
369 paths = {}
369 paths = {}
370 try:
370 try:
371 pf = os.path.expanduser("~/.hgpaths")
371 pf = os.path.expanduser("~/.hgpaths")
372 for l in file(pf):
372 for l in file(pf):
373 name, path = l.split()
373 name, path = l.split()
374 paths[name] = path
374 paths[name] = path
375 except IOError:
375 except IOError:
376 pass
376 pass
377
377
378 if source in paths: source = paths[source]
378 if source in paths: source = paths[source]
379
379
380 other = hg.repository(ui, source)
380 other = hg.repository(ui, source)
381 cg = repo.getchangegroup(other)
381 cg = repo.getchangegroup(other)
382 repo.addchangegroup(cg)
382 repo.addchangegroup(cg)
383
383
384 def rawcommit(ui, repo, files, rc):
384 def rawcommit(ui, repo, files, rc):
385 "raw commit interface"
385 "raw commit interface"
386
386
387 text = rc['text']
387 text = rc['text']
388 if not text and rc['logfile']:
388 if not text and rc['logfile']:
389 try: text = open(rc['logfile']).read()
389 try: text = open(rc['logfile']).read()
390 except IOError: pass
390 except IOError: pass
391 if not text and not rc['logfile']:
391 if not text and not rc['logfile']:
392 print "missing commit text"
392 print "missing commit text"
393 return 1
393 return 1
394
394
395 files = relpath(repo, files)
395 files = relpath(repo, files)
396 if rc['files']:
396 if rc['files']:
397 files += open(rc['files']).read().splitlines()
397 files += open(rc['files']).read().splitlines()
398
398
399 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
399 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
400
400
401 def recover(ui, repo):
401 def recover(ui, repo):
402 repo.recover()
402 repo.recover()
403
403
404 def remove(ui, repo, file, *files):
404 def remove(ui, repo, file, *files):
405 """remove the specified files on the next commit"""
405 """remove the specified files on the next commit"""
406 repo.remove(relpath(repo, (file,) + files))
406 repo.remove(relpath(repo, (file,) + files))
407
407
408 def resolve(ui, repo, node=None):
408 def resolve(ui, repo, node=None):
409 '''merge a given node or the current tip into the working dir'''
409 '''merge a given node or the current tip into the working dir'''
410 if not node:
410 if not node:
411 node = repo.changelog.tip()
411 node = repo.changelog.tip()
412 else:
412 else:
413 node = repo.lookup(node)
413 node = repo.lookup(node)
414 repo.resolve(node)
414 repo.resolve(node)
415
415
416 def serve(ui, repo, **opts):
416 def serve(ui, repo, **opts):
417 from mercurial import hgweb
417 from mercurial import hgweb
418 hgweb.server(repo.root, opts["name"], opts["templates"],
418 hgweb.server(repo.root, opts["name"], opts["templates"],
419 opts["address"], opts["port"])
419 opts["address"], opts["port"])
420
420
421 def status(ui, repo):
421 def status(ui, repo):
422 '''show changed files in the working directory
422 '''show changed files in the working directory
423
423
424 C = changed
424 C = changed
425 A = added
425 A = added
426 R = removed
426 R = removed
427 ? = not tracked'''
427 ? = not tracked'''
428
428
429 (c, a, d, u) = repo.diffdir(repo.root)
429 (c, a, d, u) = repo.diffdir(repo.root)
430 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
430 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
431
431
432 for f in c: print "C", f
432 for f in c: print "C", f
433 for f in a: print "A", f
433 for f in a: print "A", f
434 for f in d: print "R", f
434 for f in d: print "R", f
435 for f in u: print "?", f
435 for f in u: print "?", f
436
436
437 def tags(ui, repo):
437 def tags(ui, repo):
438 repo.lookup(0) # prime the cache
438 repo.lookup(0) # prime the cache
439 i = repo.tags.items()
439 i = repo.tags.items()
440 i.sort()
440 i.sort()
441 for k, n in i:
441 for k, n in i:
442 try:
442 try:
443 r = repo.changelog.rev(n)
443 r = repo.changelog.rev(n)
444 except KeyError:
444 except KeyError:
445 r = "?"
445 r = "?"
446 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
446 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
447
447
448 def tip(ui, repo):
448 def tip(ui, repo):
449 n = repo.changelog.tip()
449 n = repo.changelog.tip()
450 t = repo.changelog.rev(n)
450 t = repo.changelog.rev(n)
451 ui.status("%d:%s\n" % (t, hg.hex(n)))
451 ui.status("%d:%s\n" % (t, hg.hex(n)))
452
452
453 def undo(ui, repo):
453 def undo(ui, repo):
454 repo.undo()
454 repo.undo()
455
455
456 def verify(ui, repo):
456 def verify(ui, repo):
457 """verify the integrity of the repository"""
457 """verify the integrity of the repository"""
458 return repo.verify()
458 return repo.verify()
459
459
460 table = {
460 table = {
461 "add": (add, [], "hg add [files]"),
461 "add": (add, [], "hg add [files]"),
462 "addremove": (addremove, [], "hg addremove"),
462 "addremove": (addremove, [], "hg addremove"),
463 "ann|annotate": (annotate,
463 "ann|annotate": (annotate,
464 [('r', 'revision', '', 'revision'),
464 [('r', 'revision', '', 'revision'),
465 ('u', 'user', None, 'show user'),
465 ('u', 'user', None, 'show user'),
466 ('n', 'number', None, 'show revision number'),
466 ('n', 'number', None, 'show revision number'),
467 ('c', 'changeset', None, 'show changeset')],
467 ('c', 'changeset', None, 'show changeset')],
468 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
468 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
469 "branch|clone": (branch, [], 'hg branch [path]'),
469 "branch|clone": (branch, [], 'hg branch [path]'),
470 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
470 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
471 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
471 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
472 "commit|ci": (commit, [], 'hg commit [files]'),
472 "commit|ci": (commit, [], 'hg commit [files]'),
473 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
473 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
474 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
474 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
475 "debugindex": (debugindex, [], 'debugindex <file>'),
475 "debugindex": (debugindex, [], 'debugindex <file>'),
476 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
476 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
477 "diff": (diff, [('r', 'rev', [], 'revision')],
477 "diff": (diff, [('r', 'rev', [], 'revision')],
478 'hg diff [-r A] [-r B] [files]'),
478 'hg diff [-r A] [-r B] [files]'),
479 "export": (export, [], "hg export <changeset>"),
479 "export": (export, [], "hg export <changeset>"),
480 "forget": (forget, [], "hg forget [files]"),
480 "forget": (forget, [], "hg forget [files]"),
481 "heads": (heads, [], 'hg heads'),
481 "heads": (heads, [], 'hg heads'),
482 "history": (history, [], 'hg history'),
482 "history": (history, [], 'hg history'),
483 "help": (help, [], 'hg help [command]'),
483 "help": (help, [], 'hg help [command]'),
484 "init": (init, [], 'hg init'),
484 "init": (init, [], 'hg init'),
485 "log": (log, [], 'hg log <file>'),
485 "log": (log, [], 'hg log <file>'),
486 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
486 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
487 "parents": (parents, [], 'hg parents [node]'),
487 "parents": (parents, [], 'hg parents [node]'),
488 "patch|import": (patch,
488 "patch|import": (patch,
489 [('p', 'strip', 1, 'path strip'),
489 [('p', 'strip', 1, 'path strip'),
490 ('b', 'base', "", 'base path'),
490 ('b', 'base', "", 'base path'),
491 ('q', 'quiet', "", 'silence diff')],
491 ('q', 'quiet', "", 'silence diff')],
492 "hg import [options] patches"),
492 "hg import [options] patches"),
493 "pull|merge": (pull, [], 'hg pull [source]'),
493 "pull|merge": (pull, [], 'hg pull [source]'),
494 "rawcommit": (rawcommit,
494 "rawcommit": (rawcommit,
495 [('p', 'parent', [], 'parent'),
495 [('p', 'parent', [], 'parent'),
496 ('d', 'date', "", 'data'),
496 ('d', 'date', "", 'data'),
497 ('u', 'user', "", 'user'),
497 ('u', 'user', "", 'user'),
498 ('F', 'files', "", 'file list'),
498 ('F', 'files', "", 'file list'),
499 ('t', 'text', "", 'commit text'),
499 ('t', 'text', "", 'commit text'),
500 ('l', 'logfile', "", 'commit text file')],
500 ('l', 'logfile', "", 'commit text file')],
501 'hg rawcommit [options] [files]'),
501 'hg rawcommit [options] [files]'),
502 "recover": (recover, [], "hg recover"),
502 "recover": (recover, [], "hg recover"),
503 "remove": (remove, [], "hg remove [files]"),
503 "remove": (remove, [], "hg remove [files]"),
504 "resolve": (resolve, [], 'hg resolve [node]'),
504 "resolve": (resolve, [], 'hg resolve [node]'),
505 "serve": (serve, [('p', 'port', 8000, 'listen port'),
505 "serve": (serve, [('p', 'port', 8000, 'listen port'),
506 ('a', 'address', '', 'interface address'),
506 ('a', 'address', '', 'interface address'),
507 ('n', 'name', os.getcwd(), 'repository name'),
507 ('n', 'name', os.getcwd(), 'repository name'),
508 ('t', 'templates', "", 'template map')],
508 ('t', 'templates', "", 'template map')],
509 "hg serve [options]"),
509 "hg serve [options]"),
510 "status": (status, [], 'hg status'),
510 "status": (status, [], 'hg status'),
511 "tags": (tags, [], 'hg tags'),
511 "tags": (tags, [], 'hg tags'),
512 "tip": (tip, [], 'hg tip'),
512 "tip": (tip, [], 'hg tip'),
513 "undo": (undo, [], 'hg undo'),
513 "undo": (undo, [], 'hg undo'),
514 "verify": (verify, [], 'hg verify'),
514 "verify": (verify, [], 'hg verify'),
515 }
515 }
516
516
517 norepo = "init branch help debugindex debugindexdot"
517 norepo = "init branch help debugindex debugindexdot"
518
518
519 def find(cmd):
519 def find(cmd):
520 i = None
520 i = None
521 for e in table.keys():
521 for e in table.keys():
522 if re.match(e + "$", cmd):
522 if re.match(e + "$", cmd):
523 return table[e]
523 return table[e]
524
524
525 raise UnknownCommand(cmd)
525 raise UnknownCommand(cmd)
526
526
527 class SignalInterrupt(Exception): pass
527 class SignalInterrupt(Exception): pass
528
528
529 def catchterm(*args):
529 def catchterm(*args):
530 raise SignalInterrupt
530 raise SignalInterrupt
531
531
532 def run():
532 def run():
533 sys.exit(dispatch(sys.argv[1:]))
533 sys.exit(dispatch(sys.argv[1:]))
534
534
535 def dispatch(args):
535 def dispatch(args):
536 options = {}
536 options = {}
537 opts = [('v', 'verbose', None, 'verbose'),
537 opts = [('v', 'verbose', None, 'verbose'),
538 ('d', 'debug', None, 'debug'),
538 ('d', 'debug', None, 'debug'),
539 ('q', 'quiet', None, 'quiet'),
539 ('q', 'quiet', None, 'quiet'),
540 ('y', 'noninteractive', None, 'run non-interactively'),
540 ('y', 'noninteractive', None, 'run non-interactively'),
541 ]
541 ]
542
542
543 args = fancyopts.fancyopts(args, opts, options,
543 args = fancyopts.fancyopts(args, opts, options,
544 'hg [options] <command> [options] [files]')
544 'hg [options] <command> [options] [files]')
545
545
546 if not args:
546 if not args:
547 cmd = "help"
547 cmd = "help"
548 else:
548 else:
549 cmd, args = args[0], args[1:]
549 cmd, args = args[0], args[1:]
550
550
551 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
551 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
552 not options["noninteractive"])
552 not options["noninteractive"])
553
553
554 # deal with unfound commands later
554 try:
555 i = find(cmd)
555 i = find(cmd)
556 except UnknownCommand:
557 u.warn("unknown command '%s'\n" % cmd)
558 help(u)
559 sys.exit(1)
556
560
557 signal.signal(signal.SIGTERM, catchterm)
561 signal.signal(signal.SIGTERM, catchterm)
558
562
559 cmdoptions = {}
563 cmdoptions = {}
560 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
564 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
561
565
562 if cmd not in norepo.split():
566 if cmd not in norepo.split():
563 repo = hg.repository(ui = u)
567 repo = hg.repository(ui = u)
564 d = lambda: i[0](u, repo, *args, **cmdoptions)
568 d = lambda: i[0](u, repo, *args, **cmdoptions)
565 else:
569 else:
566 d = lambda: i[0](u, *args, **cmdoptions)
570 d = lambda: i[0](u, *args, **cmdoptions)
567
571
568 try:
572 try:
569 return d()
573 return d()
570 except SignalInterrupt:
574 except SignalInterrupt:
571 u.warn("killed!\n")
575 u.warn("killed!\n")
572 except KeyboardInterrupt:
576 except KeyboardInterrupt:
573 u.warn("interrupted!\n")
577 u.warn("interrupted!\n")
574 except IOError, inst:
578 except IOError, inst:
575 if inst.errno == 32:
579 if inst.errno == 32:
576 u.warn("broken pipe\n")
580 u.warn("broken pipe\n")
577 else:
581 else:
578 raise
582 raise
579 except TypeError, inst:
583 except TypeError, inst:
580 import traceback
584 import traceback
581 # was this an argument error?
585 # was this an argument error?
582 tb = traceback.extract_tb(sys.exc_info()[2])
586 tb = traceback.extract_tb(sys.exc_info()[2])
583 if len(tb) > 2: # no
587 if len(tb) > 2: # no
584 raise
588 raise
585 u.warn("%s: invalid arguments\n" % i[0].__name__)
589 u.warn("%s: invalid arguments\n" % i[0].__name__)
586 u.warn("syntax: %s\n" % i[2])
590 u.warn("syntax: %s\n" % i[2])
587 sys.exit(-1)
591 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now