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