Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/commands.py @ 293:11d64332a1cb
hg help improvements
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
hg help improvements
Handle showing option help in commands.py rather than fancyopts
Show getopt exception string if argument parsing fails and call help
Show help for invalid arguments
Show exception string for invalid arguments with -d
manifest hash: 9bd3e908cc080c21bb5e85822f675c35a8396fef
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCp8GNywK+sNU5EO8RAoJfAJ4pB0I4xH4CTuGmAwArfBzIsT9plACeImkm
4ml9x78fmPgKpDYIr/qhfVY=
=YeZv
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Wed, 08 Jun 2005 20:11:57 -0800 |
parents | 07c6cb9fd1c5 |
children | f8d56da6ac8f |
rev | line source |
---|---|
249 | 1 # commands.py - command processing for mercurial |
2 # | |
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
262 | 8 import os, re, sys, signal |
9 import fancyopts, ui, hg | |
10 from demandload import * | |
11 demandload(globals(), "mdiff time hgweb traceback") | |
209 | 12 |
13 class UnknownCommand(Exception): pass | |
14 | |
245 | 15 def filterfiles(filters, files): |
16 l = [ x for x in files if x in filters ] | |
213 | 17 |
245 | 18 for t in filters: |
19 if t and t[-1] != os.sep: t += os.sep | |
20 l += [ x for x in files if x.startswith(t) ] | |
213 | 21 return l |
22 | |
245 | 23 def relfilter(repo, files): |
213 | 24 if os.getcwd() != repo.root: |
25 p = os.getcwd()[len(repo.root) + 1: ] | |
281 | 26 return filterfiles([p], files) |
245 | 27 return files |
213 | 28 |
209 | 29 def relpath(repo, args): |
30 if os.getcwd() != repo.root: | |
31 p = os.getcwd()[len(repo.root) + 1: ] | |
245 | 32 return [ os.path.normpath(os.path.join(p, x)) for x in args ] |
209 | 33 return args |
245 | 34 |
35 def dodiff(repo, files = None, node1 = None, node2 = None): | |
36 def date(c): | |
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) | |
38 | |
39 if node2: | |
40 change = repo.changelog.read(node2) | |
41 mmap2 = repo.manifest.read(change[0]) | |
42 (c, a, d) = repo.diffrevs(node1, node2) | |
43 def read(f): return repo.file(f).read(mmap2[f]) | |
44 date2 = date(change) | |
45 else: | |
46 date2 = time.asctime() | |
47 (c, a, d, u) = repo.diffdir(repo.root, node1) | |
48 if not node1: | |
49 node1 = repo.dirstate.parents()[0] | |
50 def read(f): return file(os.path.join(repo.root, f)).read() | |
51 | |
52 change = repo.changelog.read(node1) | |
53 mmap = repo.manifest.read(change[0]) | |
54 date1 = date(change) | |
55 | |
56 if files: | |
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d)) | |
58 | |
59 for f in c: | |
275 | 60 to = None |
61 if f in mmap: | |
62 to = repo.file(f).read(mmap[f]) | |
245 | 63 tn = read(f) |
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) | |
65 for f in a: | |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
262
diff
changeset
|
66 to = None |
245 | 67 tn = read(f) |
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) | |
69 for f in d: | |
70 to = repo.file(f).read(mmap[f]) | |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
262
diff
changeset
|
71 tn = None |
245 | 72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) |
209 | 73 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
74 def help(ui, cmd=None): |
255 | 75 '''show help for a given command or all commands''' |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
76 if cmd: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
77 try: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
78 i = find(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
79 ui.write("%s\n\n" % i[2]) |
293 | 80 |
81 if i[1]: | |
82 for s, l, d, c in i[1]: | |
83 opt=' ' | |
84 if s: opt = opt + '-' + s + ' ' | |
85 if l: opt = opt + '--' + l + ' ' | |
86 if d: opt = opt + '(' + str(d) + ')' | |
87 ui.write(opt, "\n") | |
88 if c: ui.write(' %s\n' % c) | |
89 ui.write("\n") | |
90 | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
91 ui.write(i[0].__doc__, "\n") |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
92 except UnknownCommand: |
268 | 93 ui.warn("hg: unknown command %s\n" % cmd) |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
94 sys.exit(0) |
255 | 95 else: |
96 ui.status('hg commands:\n\n') | |
209 | 97 |
255 | 98 h = {} |
99 for e in table.values(): | |
100 f = e[0] | |
101 if f.__name__.startswith("debug"): continue | |
102 d = "" | |
103 if f.__doc__: | |
104 d = f.__doc__.splitlines(0)[0].rstrip() | |
105 h[f.__name__] = d | |
106 | |
107 fns = h.keys() | |
108 fns.sort() | |
109 m = max(map(len, fns)) | |
110 for f in fns: | |
111 ui.status(' %-*s %s\n' % (m, f, h[f])) | |
112 | |
113 # Commands start here, listed alphabetically | |
209 | 114 |
245 | 115 def add(ui, repo, file, *files): |
116 '''add the specified files on the next commit''' | |
117 repo.add(relpath(repo, (file,) + files)) | |
213 | 118 |
245 | 119 def addremove(ui, repo): |
255 | 120 """add all new files, delete all missing files""" |
230 | 121 (c, a, d, u) = repo.diffdir(repo.root) |
259 | 122 repo.add(u) |
245 | 123 repo.remove(d) |
219
8ff4532376a4
hg checkout: refuse to checkout if there are outstanding changes
mpm@selenic.com
parents:
214
diff
changeset
|
124 |
245 | 125 def annotate(u, repo, file, *files, **ops): |
255 | 126 """show changeset information per file line""" |
209 | 127 def getnode(rev): |
128 return hg.short(repo.changelog.node(rev)) | |
129 | |
130 def getname(rev): | |
131 try: | |
132 return bcache[rev] | |
133 except KeyError: | |
134 cl = repo.changelog.read(repo.changelog.node(rev)) | |
135 name = cl[1] | |
136 f = name.find('@') | |
137 if f >= 0: | |
138 name = name[:f] | |
139 bcache[rev] = name | |
140 return name | |
141 | |
142 bcache = {} | |
143 opmap = [['user', getname], ['number', str], ['changeset', getnode]] | |
144 if not ops['user'] and not ops['changeset']: | |
145 ops['number'] = 1 | |
146 | |
227 | 147 node = repo.dirstate.parents()[0] |
209 | 148 if ops['revision']: |
149 node = repo.changelog.lookup(ops['revision']) | |
150 change = repo.changelog.read(node) | |
151 mmap = repo.manifest.read(change[0]) | |
152 maxuserlen = 0 | |
153 maxchangelen = 0 | |
245 | 154 for f in relpath(repo, (file,) + files): |
209 | 155 lines = repo.file(f).annotate(mmap[f]) |
156 pieces = [] | |
157 | |
158 for o, f in opmap: | |
159 if ops[o]: | |
160 l = [ f(n) for n,t in lines ] | |
161 m = max(map(len, l)) | |
162 pieces.append([ "%*s" % (m, x) for x in l]) | |
163 | |
164 for p,l in zip(zip(*pieces), lines): | |
165 u.write(" ".join(p) + ": " + l[1]) | |
166 | |
248 | 167 def cat(ui, repo, file, rev = []): |
255 | 168 """output the latest or given revision of a file""" |
281 | 169 r = repo.file(relpath(repo, [file])[0]) |
248 | 170 n = r.tip() |
171 if rev: n = r.lookup(rev) | |
172 sys.stdout.write(r.read(n)) | |
173 | |
289 | 174 def commit(ui, repo, *files, **opts): |
245 | 175 """commit the specified files or all outstanding changes""" |
289 | 176 text = opts['text'] |
177 if not text and opts['logfile']: | |
178 try: text = open(opts['logfile']).read() | |
179 except IOError: pass | |
180 | |
181 repo.commit(relpath(repo, files), text) | |
245 | 182 |
248 | 183 def debugaddchangegroup(ui, repo): |
184 data = sys.stdin.read() | |
185 repo.addchangegroup(data) | |
186 | |
187 def debugchangegroup(ui, repo, roots): | |
188 newer = repo.newer(map(repo.lookup, roots)) | |
189 for chunk in repo.changegroup(newer): | |
190 sys.stdout.write(chunk) | |
191 | |
192 def debugindex(ui, file): | |
193 r = hg.revlog(open, file, "") | |
194 print " rev offset length base linkrev"+\ | |
195 " p1 p2 nodeid" | |
196 for i in range(r.count()): | |
197 e = r.index[i] | |
198 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % ( | |
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])) | |
201 | |
202 def debugindexdot(ui, file): | |
203 r = hg.revlog(open, file, "") | |
204 print "digraph G {" | |
205 for i in range(r.count()): | |
206 e = r.index[i] | |
207 print "\t%d -> %d" % (r.rev(e[4]), i) | |
208 if e[5] != hg.nullid: | |
209 print "\t%d -> %d" % (r.rev(e[5]), i) | |
210 print "}" | |
211 | |
245 | 212 def diff(ui, repo, *files, **opts): |
255 | 213 """diff working directory (or selected files)""" |
245 | 214 revs = [] |
215 if opts['rev']: | |
216 revs = map(lambda x: repo.lookup(x), opts['rev']) | |
217 | |
218 if len(revs) > 2: | |
219 self.ui.warn("too many revisions to diff\n") | |
220 sys.exit(1) | |
221 | |
222 if files: | |
223 files = relpath(repo, files) | |
224 else: | |
225 files = relpath(repo, [""]) | |
226 | |
227 dodiff(repo, files, *revs) | |
228 | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
229 def export(ui, repo, changeset): |
255 | 230 """dump the changeset header and diffs for a revision""" |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
231 node = repo.lookup(changeset) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
232 prev, other = repo.changelog.parents(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
233 change = repo.changelog.read(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
234 print "# HG changeset patch" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
235 print "# User %s" % change[1] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
236 print "# Node ID %s" % hg.hex(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
237 print "# Parent %s" % hg.hex(prev) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
238 print |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
239 if other != hg.nullid: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
240 print "# Parent %s" % hg.hex(other) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
241 print change[4].rstrip() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
242 print |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
243 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
244 dodiff(repo, None, prev, node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
245 |
245 | 246 def forget(ui, repo, file, *files): |
247 """don't add the specified files on the next commit""" | |
248 repo.forget(relpath(repo, (file,) + files)) | |
249 | |
221 | 250 def heads(ui, repo): |
251 '''show current repository heads''' | |
252 for n in repo.changelog.heads(): | |
253 i = repo.changelog.rev(n) | |
254 changes = repo.changelog.read(n) | |
255 (p1, p2) = repo.changelog.parents(n) | |
256 (h, h1, h2) = map(hg.hex, (n, p1, p2)) | |
257 (i1, i2) = map(repo.changelog.rev, (p1, p2)) | |
258 print "rev: %4d:%s" % (i, h) | |
259 print "parents: %4d:%s" % (i1, h1) | |
260 if i2: print " %4d:%s" % (i2, h2) | |
261 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]), | |
262 hg.hex(changes[0])) | |
263 print "user:", changes[1] | |
264 print "date:", time.asctime( | |
265 time.localtime(float(changes[2].split(' ')[0]))) | |
266 if ui.verbose: print "files:", " ".join(changes[3]) | |
267 print "description:" | |
268 print changes[4] | |
269 | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
270 def history(ui, repo): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
271 """show the changelog history""" |
270
5a80ed2158c8
Reverse order of hg log and hg history lists
mpm@selenic.com
parents:
268
diff
changeset
|
272 for i in range(repo.changelog.count() - 1, -1, -1): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
273 n = repo.changelog.node(i) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
274 changes = repo.changelog.read(n) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
275 (p1, p2) = repo.changelog.parents(n) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
276 (h, h1, h2) = map(hg.hex, (n, p1, p2)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
277 (i1, i2) = map(repo.changelog.rev, (p1, p2)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
278 print "rev: %4d:%s" % (i, h) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
279 print "parents: %4d:%s" % (i1, h1) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
280 if i2: print " %4d:%s" % (i2, h2) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
281 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
282 hg.hex(changes[0])) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
283 print "user:", changes[1] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
284 print "date:", time.asctime( |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
285 time.localtime(float(changes[2].split(' ')[0]))) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
286 if ui.verbose: print "files:", " ".join(changes[3]) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
287 print "description:" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
288 print changes[4] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
289 |
290 | 290 def init(ui, source=None): |
291 """create a new repository or copy an existing one""" | |
292 | |
293 if source: | |
294 paths = {} | |
295 for name, path in ui.configitems("paths"): | |
296 paths[name] = path | |
297 | |
298 if source in paths: source = paths[source] | |
255 | 299 |
290 | 300 link = 0 |
301 if not source.startswith("http://"): | |
302 d1 = os.stat(os.getcwd()).st_dev | |
303 d2 = os.stat(source).st_dev | |
304 if d1 == d2: link = 1 | |
305 | |
306 if link: | |
307 ui.debug("copying by hardlink\n") | |
308 os.system("cp -al %s/.hg .hg" % source) | |
309 else: | |
310 repo = hg.repository(ui, ".", create=1) | |
311 other = hg.repository(ui, source) | |
312 cg = repo.getchangegroup(other) | |
313 repo.addchangegroup(cg) | |
314 else: | |
315 hg.repository(ui, ".", create=1) | |
316 | |
255 | 317 def log(ui, repo, f): |
318 """show the revision history of a single file""" | |
319 f = relpath(repo, [f])[0] | |
320 | |
321 r = repo.file(f) | |
270
5a80ed2158c8
Reverse order of hg log and hg history lists
mpm@selenic.com
parents:
268
diff
changeset
|
322 for i in range(r.count() - 1, -1, -1): |
255 | 323 n = r.node(i) |
324 (p1, p2) = r.parents(n) | |
325 (h, h1, h2) = map(hg.hex, (n, p1, p2)) | |
326 (i1, i2) = map(r.rev, (p1, p2)) | |
327 cr = r.linkrev(n) | |
328 cn = hg.hex(repo.changelog.node(cr)) | |
329 print "rev: %4d:%s" % (i, h) | |
330 print "changeset: %4d:%s" % (cr, cn) | |
331 print "parents: %4d:%s" % (i1, h1) | |
332 if i2: print " %4d:%s" % (i2, h2) | |
333 changes = repo.changelog.read(repo.changelog.node(cr)) | |
334 print "user: %s" % changes[1] | |
335 print "date: %s" % time.asctime( | |
336 time.localtime(float(changes[2].split(' ')[0]))) | |
337 print "description:" | |
338 print changes[4].rstrip() | |
339 print | |
340 | |
341 def manifest(ui, repo, rev = []): | |
342 """output the latest or given revision of the project manifest""" | |
343 n = repo.manifest.tip() | |
344 if rev: | |
345 n = repo.manifest.lookup(rev) | |
346 m = repo.manifest.read(n) | |
276 | 347 mf = repo.manifest.readflags(n) |
255 | 348 files = m.keys() |
349 files.sort() | |
350 | |
351 for f in files: | |
276 | 352 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f)) |
255 | 353 |
354 def parents(ui, repo, node = None): | |
355 '''show the parents of the current working dir''' | |
356 if node: | |
357 p = repo.changelog.parents(repo.lookup(hg.bin(node))) | |
358 else: | |
359 p = repo.dirstate.parents() | |
360 | |
361 for n in p: | |
362 if n != hg.nullid: | |
363 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n))) | |
364 | |
266
4af7677de4a9
Fix argument processing for patch and rawcommit
mpm@selenic.com
parents:
264
diff
changeset
|
365 def patch(ui, repo, patches, **opts): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
366 """import an ordered set of patches""" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
367 try: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
368 import psyco |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
369 psyco.full() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
370 except: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
371 pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
372 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
373 d = opts["base"] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
374 strip = opts["strip"] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
375 quiet = opts["quiet"] and "> /dev/null" or "" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
376 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
377 for patch in patches: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
378 ui.status("applying %s\n" % patch) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
379 pf = os.path.join(d, patch) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
380 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
381 text = "" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
382 for l in file(pf): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
383 if l[:4] == "--- ": break |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
384 text += l |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
385 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
386 f = os.popen("lsdiff --strip %d %s" % (strip, pf)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
387 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines())) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
388 f.close() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
389 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
390 if files: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
391 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
392 raise "patch failed!" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
393 repo.commit(files, text) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
394 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
395 def pull(ui, repo, source): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
396 """pull changes from the specified source""" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
397 paths = {} |
286 | 398 for name, path in ui.configitems("paths"): |
290 | 399 paths[name] = path |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
400 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
401 if source in paths: source = paths[source] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
402 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
403 other = hg.repository(ui, source) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
404 cg = repo.getchangegroup(other) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
405 repo.addchangegroup(cg) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
406 |
266
4af7677de4a9
Fix argument processing for patch and rawcommit
mpm@selenic.com
parents:
264
diff
changeset
|
407 def rawcommit(ui, repo, files, **rc): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
408 "raw commit interface" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
409 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
410 text = rc['text'] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
411 if not text and rc['logfile']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
412 try: text = open(rc['logfile']).read() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
413 except IOError: pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
414 if not text and not rc['logfile']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
415 print "missing commit text" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
416 return 1 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
417 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
418 files = relpath(repo, files) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
419 if rc['files']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
420 files += open(rc['files']).read().splitlines() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
421 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
422 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent']) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
423 |
245 | 424 def recover(ui, repo): |
255 | 425 """roll back an interrupted transaction""" |
245 | 426 repo.recover() |
427 | |
428 def remove(ui, repo, file, *files): | |
429 """remove the specified files on the next commit""" | |
430 repo.remove(relpath(repo, (file,) + files)) | |
431 | |
432 def serve(ui, repo, **opts): | |
255 | 433 """export the repository via HTTP""" |
245 | 434 hgweb.server(repo.root, opts["name"], opts["templates"], |
435 opts["address"], opts["port"]) | |
436 | |
213 | 437 def status(ui, repo): |
438 '''show changed files in the working directory | |
439 | |
245 | 440 C = changed |
441 A = added | |
442 R = removed | |
443 ? = not tracked''' | |
444 | |
230 | 445 (c, a, d, u) = repo.diffdir(repo.root) |
220 | 446 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) |
213 | 447 |
448 for f in c: print "C", f | |
220 | 449 for f in a: print "A", f |
213 | 450 for f in d: print "R", f |
220 | 451 for f in u: print "?", f |
213 | 452 |
248 | 453 def tags(ui, repo): |
255 | 454 """list repository tags""" |
248 | 455 repo.lookup(0) # prime the cache |
456 i = repo.tags.items() | |
257 | 457 n = [] |
458 for e in i: | |
459 try: | |
460 l = repo.changelog.rev(e[1]) | |
461 except KeyError: | |
462 l = -2 | |
463 n.append((l, e)) | |
464 | |
465 n.sort() | |
466 n.reverse() | |
467 i = [ e[1] for e in n ] | |
248 | 468 for k, n in i: |
469 try: | |
470 r = repo.changelog.rev(n) | |
471 except KeyError: | |
472 r = "?" | |
473 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n)) | |
474 | |
245 | 475 def tip(ui, repo): |
255 | 476 """show the tip revision""" |
245 | 477 n = repo.changelog.tip() |
478 t = repo.changelog.rev(n) | |
479 ui.status("%d:%s\n" % (t, hg.hex(n))) | |
480 | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
481 def undo(ui, repo): |
255 | 482 """undo the last transaction""" |
210 | 483 repo.undo() |
484 | |
275 | 485 def update(ui, repo, node=None, merge=False, clean=False): |
254 | 486 '''update or merge working directory |
487 | |
488 If there are no outstanding changes in the working directory and | |
489 there is a linear relationship between the current version and the | |
490 requested version, the result is the requested version. | |
491 | |
492 Otherwise the result is a merge between the contents of the | |
493 current working directory and the requested version. Files that | |
494 changed between either parent are marked as changed for the next | |
495 commit and a commit must be performed before any further updates | |
496 are allowed. | |
497 ''' | |
498 node = node and repo.lookup(node) or repo.changelog.tip() | |
275 | 499 return repo.update(node, allow=merge, force=clean) |
254 | 500 |
247 | 501 def verify(ui, repo): |
502 """verify the integrity of the repository""" | |
503 return repo.verify() | |
504 | |
255 | 505 # Command options and aliases are listed here, alphabetically |
506 | |
209 | 507 table = { |
245 | 508 "add": (add, [], "hg add [files]"), |
509 "addremove": (addremove, [], "hg addremove"), | |
209 | 510 "ann|annotate": (annotate, |
511 [('r', 'revision', '', 'revision'), | |
512 ('u', 'user', None, 'show user'), | |
513 ('n', 'number', None, 'show revision number'), | |
514 ('c', 'changeset', None, 'show changeset')], | |
515 'hg annotate [-u] [-c] [-n] [-r id] [files]'), | |
248 | 516 "cat|dump": (cat, [], 'hg cat <file> [rev]'), |
289 | 517 "commit|ci": (commit, |
518 [('t', 'text', "", 'commit text'), | |
519 ('l', 'logfile', "", 'commit text file')], | |
520 'hg commit [files]'), | |
248 | 521 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'), |
522 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'), | |
523 "debugindex": (debugindex, [], 'debugindex <file>'), | |
524 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), | |
245 | 525 "diff": (diff, [('r', 'rev', [], 'revision')], |
526 'hg diff [-r A] [-r B] [files]'), | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
527 "export": (export, [], "hg export <changeset>"), |
245 | 528 "forget": (forget, [], "hg forget [files]"), |
529 "heads": (heads, [], 'hg heads'), | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
530 "history": (history, [], 'hg history'), |
245 | 531 "help": (help, [], 'hg help [command]'), |
290 | 532 "init": (init, [], 'hg init [url]'), |
245 | 533 "log": (log, [], 'hg log <file>'), |
248 | 534 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'), |
227 | 535 "parents": (parents, [], 'hg parents [node]'), |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
536 "patch|import": (patch, |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
537 [('p', 'strip', 1, 'path strip'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
538 ('b', 'base', "", 'base path'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
539 ('q', 'quiet', "", 'silence diff')], |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
540 "hg import [options] patches"), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
541 "pull|merge": (pull, [], 'hg pull [source]'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
542 "rawcommit": (rawcommit, |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
543 [('p', 'parent', [], 'parent'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
544 ('d', 'date', "", 'data'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
545 ('u', 'user', "", 'user'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
546 ('F', 'files', "", 'file list'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
547 ('t', 'text', "", 'commit text'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
548 ('l', 'logfile', "", 'commit text file')], |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
549 'hg rawcommit [options] [files]'), |
245 | 550 "recover": (recover, [], "hg recover"), |
551 "remove": (remove, [], "hg remove [files]"), | |
552 "serve": (serve, [('p', 'port', 8000, 'listen port'), | |
553 ('a', 'address', '', 'interface address'), | |
554 ('n', 'name', os.getcwd(), 'repository name'), | |
555 ('t', 'templates', "", 'template map')], | |
556 "hg serve [options]"), | |
213 | 557 "status": (status, [], 'hg status'), |
248 | 558 "tags": (tags, [], 'hg tags'), |
245 | 559 "tip": (tip, [], 'hg tip'), |
210 | 560 "undo": (undo, [], 'hg undo'), |
275 | 561 "update|up|checkout|co|resolve": (update, |
562 [('m', 'merge', None, | |
563 'allow merging of conflicts'), | |
564 ('C', 'clean', None, | |
565 'overwrite locally modified files')], | |
566 'hg update [options] [node]'), | |
247 | 567 "verify": (verify, [], 'hg verify'), |
209 | 568 } |
569 | |
248 | 570 norepo = "init branch help debugindex debugindexdot" |
209 | 571 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
572 def find(cmd): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
573 i = None |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
574 for e in table.keys(): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
575 if re.match(e + "$", cmd): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
576 return table[e] |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
577 |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
578 raise UnknownCommand(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
579 |
214 | 580 class SignalInterrupt(Exception): pass |
581 | |
582 def catchterm(*args): | |
583 raise SignalInterrupt | |
584 | |
249 | 585 def run(): |
586 sys.exit(dispatch(sys.argv[1:])) | |
587 | |
209 | 588 def dispatch(args): |
589 options = {} | |
590 opts = [('v', 'verbose', None, 'verbose'), | |
591 ('d', 'debug', None, 'debug'), | |
592 ('q', 'quiet', None, 'quiet'), | |
593 ('y', 'noninteractive', None, 'run non-interactively'), | |
594 ] | |
595 | |
596 args = fancyopts.fancyopts(args, opts, options, | |
597 'hg [options] <command> [options] [files]') | |
598 | |
599 if not args: | |
600 cmd = "help" | |
601 else: | |
602 cmd, args = args[0], args[1:] | |
603 | |
604 u = ui.ui(options["verbose"], options["debug"], options["quiet"], | |
605 not options["noninteractive"]) | |
606 | |
252 | 607 try: |
608 i = find(cmd) | |
609 except UnknownCommand: | |
268 | 610 u.warn("hg: unknown command '%s'\n" % cmd) |
252 | 611 help(u) |
612 sys.exit(1) | |
209 | 613 |
214 | 614 signal.signal(signal.SIGTERM, catchterm) |
615 | |
209 | 616 cmdoptions = {} |
293 | 617 try: |
618 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2]) | |
619 except fancyopts.getopt.GetoptError, inst: | |
620 u.warn("hg %s: %s\n" % (cmd, inst)) | |
621 help(u, cmd) | |
622 sys.exit(-1) | |
209 | 623 |
624 if cmd not in norepo.split(): | |
625 repo = hg.repository(ui = u) | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
626 d = lambda: i[0](u, repo, *args, **cmdoptions) |
209 | 627 else: |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
628 d = lambda: i[0](u, *args, **cmdoptions) |
209 | 629 |
630 try: | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
631 return d() |
214 | 632 except SignalInterrupt: |
633 u.warn("killed!\n") | |
209 | 634 except KeyboardInterrupt: |
635 u.warn("interrupted!\n") | |
250 | 636 except IOError, inst: |
637 if inst.errno == 32: | |
638 u.warn("broken pipe\n") | |
639 else: | |
640 raise | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
641 except TypeError, inst: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
642 # was this an argument error? |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
643 tb = traceback.extract_tb(sys.exc_info()[2]) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
644 if len(tb) > 2: # no |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
645 raise |
293 | 646 u.debug(inst, "\n") |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
647 u.warn("%s: invalid arguments\n" % i[0].__name__) |
293 | 648 help(u, cmd) |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
649 sys.exit(-1) |
293 | 650 |