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