comparison mercurial/commands.py @ 705:574869103985

Merge with TAH manifest hash: 197e0d1a0d7376a9eb72381330462f06490ab821
author mpm@selenic.com
date Thu, 14 Jul 2005 22:56:55 -0800
parents 10c0264751da 80ed193efff7
children 5107a7b6b14a 9e0f3ba4a9c2
comparison
equal deleted inserted replaced
694:51eb248d3348 705:574869103985
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 from demandload import * 8 from demandload import demandload
9 demandload(globals(), "os re sys signal") 9 demandload(globals(), "os re sys signal shutil")
10 demandload(globals(), "fancyopts ui hg util") 10 demandload(globals(), "fancyopts ui hg util")
11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback") 11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
12 demandload(globals(), "errno socket version struct") 12 demandload(globals(), "errno socket version struct")
13 13
14 class UnknownCommand(Exception): pass 14 class UnknownCommand(Exception):
15 """Exception raised if command is not in the command table."""
15 16
16 def filterfiles(filters, files): 17 def filterfiles(filters, files):
17 l = [ x for x in files if x in filters ] 18 l = [x for x in files if x in filters]
18 19
19 for t in filters: 20 for t in filters:
20 if t and t[-1] != "/": t += "/" 21 if t and t[-1] != "/":
21 l += [ x for x in files if x.startswith(t) ] 22 t += "/"
23 l += [x for x in files if x.startswith(t)]
22 return l 24 return l
23 25
24 def relfilter(repo, files): 26 def relfilter(repo, files):
25 cwd = repo.getcwd() 27 cwd = repo.getcwd()
26 if cwd: 28 if cwd:
28 return files 30 return files
29 31
30 def relpath(repo, args): 32 def relpath(repo, args):
31 cwd = repo.getcwd() 33 cwd = repo.getcwd()
32 if cwd: 34 if cwd:
33 return [ util.pconvert(os.path.normpath(os.path.join(cwd, x))) for x in args ] 35 return [util.pconvert(os.path.normpath(os.path.join(cwd, x)))
36 for x in args]
34 return args 37 return args
35 38
36 revrangesep = ':' 39 revrangesep = ':'
37 40
38 def revrange(ui, repo, revs = [], revlog = None): 41 def revrange(ui, repo, revs, revlog=None):
39 if revlog is None: 42 if revlog is None:
40 revlog = repo.changelog 43 revlog = repo.changelog
41 revcount = revlog.count() 44 revcount = revlog.count()
42 def fix(val, defval): 45 def fix(val, defval):
43 if not val: return defval 46 if not val:
47 return defval
44 try: 48 try:
45 num = int(val) 49 num = int(val)
46 if str(num) != val: raise ValueError 50 if str(num) != val:
47 if num < 0: num += revcount 51 raise ValueError
52 if num < 0:
53 num += revcount
48 if not (0 <= num < revcount): 54 if not (0 <= num < revcount):
49 raise ValueError 55 raise ValueError
50 except ValueError: 56 except ValueError:
51 try: 57 try:
52 num = repo.changelog.rev(repo.lookup(val)) 58 num = repo.changelog.rev(repo.lookup(val))
83 expander = { 89 expander = {
84 '%': lambda: '%', 90 '%': lambda: '%',
85 'b': lambda: os.path.basename(repo.root), 91 'b': lambda: os.path.basename(repo.root),
86 } 92 }
87 93
88 if node: expander.update(node_expander) 94 if node:
95 expander.update(node_expander)
89 if node and revwidth is not None: 96 if node and revwidth is not None:
90 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth) 97 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
91 if total is not None: expander['N'] = lambda: str(total) 98 if total is not None:
92 if seqno is not None: expander['n'] = lambda: str(seqno) 99 expander['N'] = lambda: str(total)
100 if seqno is not None:
101 expander['n'] = lambda: str(seqno)
93 if total is not None and seqno is not None: 102 if total is not None and seqno is not None:
94 expander['n'] = lambda:str(seqno).zfill(len(str(total))) 103 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
95 104
96 newname = [] 105 newname = []
97 patlen = len(pat) 106 patlen = len(pat)
104 c = expander[c]() 113 c = expander[c]()
105 newname.append(c) 114 newname.append(c)
106 i += 1 115 i += 1
107 return ''.join(newname) 116 return ''.join(newname)
108 117
109 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None): 118 def dodiff(fp, ui, repo, files=None, node1=None, node2=None):
110 def date(c): 119 def date(c):
111 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) 120 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
112 121
113 (c, a, d, u) = repo.changes(node1, node2, files) 122 (c, a, d, u) = repo.changes(node1, node2, files)
114 if files: 123 if files:
118 return 127 return
119 128
120 if node2: 129 if node2:
121 change = repo.changelog.read(node2) 130 change = repo.changelog.read(node2)
122 mmap2 = repo.manifest.read(change[0]) 131 mmap2 = repo.manifest.read(change[0])
123 def read(f): return repo.file(f).read(mmap2[f])
124 date2 = date(change) 132 date2 = date(change)
133 def read(f):
134 return repo.file(f).read(mmap2[f])
125 else: 135 else:
126 date2 = time.asctime() 136 date2 = time.asctime()
127 if not node1: 137 if not node1:
128 node1 = repo.dirstate.parents()[0] 138 node1 = repo.dirstate.parents()[0]
129 def read(f): return repo.wfile(f).read() 139 def read(f):
140 return repo.wfile(f).read()
130 141
131 if ui.quiet: 142 if ui.quiet:
132 r = None 143 r = None
133 else: 144 else:
134 hexfunc = ui.verbose and hg.hex or hg.short 145 hexfunc = ui.verbose and hg.hex or hg.short
220 "This is free software; see the source for copying conditions. " 231 "This is free software; see the source for copying conditions. "
221 "There is NO\nwarranty; " 232 "There is NO\nwarranty; "
222 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" 233 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
223 ) 234 )
224 235
225 def help(ui, cmd=None): 236 def help_(ui, cmd=None):
226 '''show help for a given command or all commands''' 237 """show help for a given command or all commands"""
227 if cmd: 238 if cmd:
228 try: 239 try:
229 i = find(cmd) 240 i = find(cmd)
230 ui.write("%s\n\n" % i[2]) 241 ui.write("%s\n\n" % i[2])
231 242
232 if i[1]: 243 if i[1]:
233 for s, l, d, c in i[1]: 244 for s, l, d, c in i[1]:
234 opt=' ' 245 opt = ' '
235 if s: opt = opt + '-' + s + ' ' 246 if s:
236 if l: opt = opt + '--' + l + ' ' 247 opt = opt + '-' + s + ' '
237 if d: opt = opt + '(' + str(d) + ')' 248 if l:
249 opt = opt + '--' + l + ' '
250 if d:
251 opt = opt + '(' + str(d) + ')'
238 ui.write(opt, "\n") 252 ui.write(opt, "\n")
239 if c: ui.write(' %s\n' % c) 253 if c:
254 ui.write(' %s\n' % c)
240 ui.write("\n") 255 ui.write("\n")
241 256
242 ui.write(i[0].__doc__, "\n") 257 ui.write(i[0].__doc__, "\n")
243 except UnknownCommand: 258 except UnknownCommand:
244 ui.warn("hg: unknown command %s\n" % cmd) 259 ui.warn("hg: unknown command %s\n" % cmd)
271 for f in fns: 286 for f in fns:
272 ui.write(' %-*s %s\n' % (m, f, h[f])) 287 ui.write(' %-*s %s\n' % (m, f, h[f]))
273 288
274 # Commands start here, listed alphabetically 289 # Commands start here, listed alphabetically
275 290
276 def add(ui, repo, file, *files): 291 def add(ui, repo, file1, *files):
277 '''add the specified files on the next commit''' 292 '''add the specified files on the next commit'''
278 repo.add(relpath(repo, (file,) + files)) 293 repo.add(relpath(repo, (file1,) + files))
279 294
280 def addremove(ui, repo, *files): 295 def addremove(ui, repo, *files):
281 """add all new files, delete all missing files""" 296 """add all new files, delete all missing files"""
282 if files: 297 if files:
283 files = relpath(repo, files) 298 files = relpath(repo, files)
294 else: 309 else:
295 (c, a, d, u) = repo.changes(None, None) 310 (c, a, d, u) = repo.changes(None, None)
296 repo.add(u) 311 repo.add(u)
297 repo.remove(d) 312 repo.remove(d)
298 313
299 def annotate(u, repo, file, *files, **ops): 314 def annotate(u, repo, file1, *files, **ops):
300 """show changeset information per file line""" 315 """show changeset information per file line"""
301 def getnode(rev): 316 def getnode(rev):
302 return hg.short(repo.changelog.node(rev)) 317 return hg.short(repo.changelog.node(rev))
303 318
304 def getname(rev): 319 def getname(rev):
324 node = repo.dirstate.parents()[0] 339 node = repo.dirstate.parents()[0]
325 if ops['revision']: 340 if ops['revision']:
326 node = repo.changelog.lookup(ops['revision']) 341 node = repo.changelog.lookup(ops['revision'])
327 change = repo.changelog.read(node) 342 change = repo.changelog.read(node)
328 mmap = repo.manifest.read(change[0]) 343 mmap = repo.manifest.read(change[0])
329 for f in relpath(repo, (file,) + files): 344 for f in relpath(repo, (file1,) + files):
330 lines = repo.file(f).annotate(mmap[f]) 345 lines = repo.file(f).annotate(mmap[f])
331 pieces = [] 346 pieces = []
332 347
333 for o, f in opmap: 348 for o, f in opmap:
334 if ops[o]: 349 if ops[o]:
335 l = [ f(n) for n,t in lines ] 350 l = [f(n) for n, dummy in lines]
336 m = max(map(len, l)) 351 m = max(map(len, l))
337 pieces.append([ "%*s" % (m, x) for x in l]) 352 pieces.append(["%*s" % (m, x) for x in l])
338 353
339 for p,l in zip(zip(*pieces), lines): 354 for p, l in zip(zip(*pieces), lines):
340 u.write(" ".join(p) + ": " + l[1]) 355 u.write(" ".join(p) + ": " + l[1])
341 356
342 def cat(ui, repo, file, rev = [], **opts): 357 def cat(ui, repo, file1, rev=None, **opts):
343 """output the latest or given revision of a file""" 358 """output the latest or given revision of a file"""
344 r = repo.file(relpath(repo, [file])[0]) 359 r = repo.file(relpath(repo, [file1])[0])
345 n = r.tip() 360 if rev:
346 if rev: n = r.lookup(rev) 361 n = r.lookup(rev)
362 else:
363 n = r.tip()
347 if opts['output'] and opts['output'] != '-': 364 if opts['output'] and opts['output'] != '-':
348 try: 365 try:
349 outname = make_filename(repo, r, opts['output'], node=n) 366 outname = make_filename(repo, r, opts['output'], node=n)
350 fp = open(outname, 'wb') 367 fp = open(outname, 'wb')
351 except KeyError, inst: 368 except KeyError, inst:
354 sys.exit(1); 371 sys.exit(1);
355 else: 372 else:
356 fp = sys.stdout 373 fp = sys.stdout
357 fp.write(r.read(n)) 374 fp.write(r.read(n))
358 375
359 def clone(ui, source, dest = None, **opts): 376 def clone(ui, source, dest=None, **opts):
360 """make a copy of an existing repository""" 377 """make a copy of an existing repository"""
361 if dest is None: 378 if dest is None:
362 dest = os.path.basename(os.path.normpath(source)) 379 dest = os.path.basename(os.path.normpath(source))
363 380
364 if os.path.exists(dest): 381 if os.path.exists(dest):
365 ui.warn("abort: destination '%s' already exists\n" % dest) 382 ui.warn("abort: destination '%s' already exists\n" % dest)
366 return 1 383 return 1
367 384
368 class dircleanup: 385 class Dircleanup:
369 def __init__(self, dir): 386 def __init__(self, dir_):
370 import shutil
371 self.rmtree = shutil.rmtree 387 self.rmtree = shutil.rmtree
372 self.dir = dir 388 self.dir_ = dir_
373 os.mkdir(dir) 389 os.mkdir(dir_)
374 def close(self): 390 def close(self):
375 self.dir = None 391 self.dir_ = None
376 def __del__(self): 392 def __del__(self):
377 if self.dir: 393 if self.dir_:
378 self.rmtree(self.dir, True) 394 self.rmtree(self.dir_, True)
379 395
380 d = dircleanup(dest) 396 d = Dircleanup(dest)
381 link = 0
382 abspath = source 397 abspath = source
383 source = ui.expandpath(source) 398 source = ui.expandpath(source)
384 other = hg.repository(ui, source) 399 other = hg.repository(ui, source)
385 400
386 if other.dev() != -1: 401 if other.dev() != -1:
387 abspath = os.path.abspath(source) 402 abspath = os.path.abspath(source)
388 403 copyfile = (os.stat(dest).st_dev == other.dev()
389 if other.dev() != -1 and os.stat(dest).st_dev == other.dev(): 404 and getattr(os, 'link', None) or shutil.copy2)
390 ui.note("cloning by hardlink\n") 405 if copyfile is not shutil.copy2:
391 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) 406 ui.note("cloning by hardlink\n")
407 util.copytree(os.path.join(source, ".hg"), os.path.join(dest, ".hg"),
408 copyfile)
392 try: 409 try:
393 os.remove(os.path.join(dest, ".hg", "dirstate")) 410 os.unlink(os.path.join(dest, ".hg", "dirstate"))
394 except: pass 411 except IOError:
412 pass
395 413
396 repo = hg.repository(ui, dest) 414 repo = hg.repository(ui, dest)
397 415
398 else: 416 else:
399 repo = hg.repository(ui, dest, create=1) 417 repo = hg.repository(ui, dest, create=1)
409 d.close() 427 d.close()
410 428
411 def commit(ui, repo, *files, **opts): 429 def commit(ui, repo, *files, **opts):
412 """commit the specified files or all outstanding changes""" 430 """commit the specified files or all outstanding changes"""
413 text = opts['text'] 431 text = opts['text']
414 if not text and opts['logfile']: 432 logfile = opts['logfile']
415 try: text = open(opts['logfile']).read() 433 if not text and logfile:
416 except IOError: pass 434 try:
435 text = open(logfile).read()
436 except IOError, why:
437 ui.warn("Can't read commit text %s: %s\n" % (logfile, why))
417 438
418 if opts['addremove']: 439 if opts['addremove']:
419 addremove(ui, repo, *files) 440 addremove(ui, repo, *files)
420 repo.commit(relpath(repo, files), text, opts['user'], opts['date']) 441 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
421 442
460 """show the contents of the current dirstate""" 481 """show the contents of the current dirstate"""
461 repo.dirstate.read() 482 repo.dirstate.read()
462 dc = repo.dirstate.map 483 dc = repo.dirstate.map
463 keys = dc.keys() 484 keys = dc.keys()
464 keys.sort() 485 keys.sort()
465 for file in keys: 486 for file_ in keys:
466 ui.write("%c %s\n" % (dc[file][0], file)) 487 ui.write("%c %s\n" % (dc[file_][0], file_))
467 488
468 def debugindex(ui, file): 489 def debugindex(ui, file_):
469 """dump the contents of an index file""" 490 """dump the contents of an index file"""
470 r = hg.revlog(hg.opener(""), file, "") 491 r = hg.revlog(hg.opener(""), file_, "")
471 ui.write(" rev offset length base linkrev" + 492 ui.write(" rev offset length base linkrev" +
472 " p1 p2 nodeid\n") 493 " p1 p2 nodeid\n")
473 for i in range(r.count()): 494 for i in range(r.count()):
474 e = r.index[i] 495 e = r.index[i]
475 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % ( 496 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % (
476 i, e[0], e[1], e[2], e[3], 497 i, e[0], e[1], e[2], e[3],
477 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))) 498 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])))
478 499
479 def debugindexdot(ui, file): 500 def debugindexdot(ui, file_):
480 """dump an index DAG as a .dot file""" 501 """dump an index DAG as a .dot file"""
481 r = hg.revlog(hg.opener(""), file, "") 502 r = hg.revlog(hg.opener(""), file_, "")
482 ui.write("digraph G {\n") 503 ui.write("digraph G {\n")
483 for i in range(r.count()): 504 for i in range(r.count()):
484 e = r.index[i] 505 e = r.index[i]
485 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i)) 506 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
486 if e[5] != hg.nullid: 507 if e[5] != hg.nullid:
544 revwidth = max(len(revs[0]), len(revs[-1])) 565 revwidth = max(len(revs[0]), len(revs[-1]))
545 for cset in revs: 566 for cset in revs:
546 seqno += 1 567 seqno += 1
547 doexport(ui, repo, cset, seqno, total, revwidth, opts) 568 doexport(ui, repo, cset, seqno, total, revwidth, opts)
548 569
549 def forget(ui, repo, file, *files): 570 def forget(ui, repo, file1, *files):
550 """don't add the specified files on the next commit""" 571 """don't add the specified files on the next commit"""
551 repo.forget(relpath(repo, (file,) + files)) 572 repo.forget(relpath(repo, (file1,) + files))
552 573
553 def heads(ui, repo): 574 def heads(ui, repo):
554 """show current repository heads""" 575 """show current repository heads"""
555 for n in repo.changelog.heads(): 576 for n in repo.changelog.heads():
556 show_changeset(ui, repo, changenode=n) 577 show_changeset(ui, repo, changenode=n)
579 def import_(ui, repo, patch1, *patches, **opts): 600 def import_(ui, repo, patch1, *patches, **opts):
580 """import an ordered set of patches""" 601 """import an ordered set of patches"""
581 try: 602 try:
582 import psyco 603 import psyco
583 psyco.full() 604 psyco.full()
584 except: 605 except ImportError:
585 pass 606 pass
586 607
587 patches = (patch1,) + patches 608 patches = (patch1,) + patches
588 609
589 d = opts["base"] 610 d = opts["base"]
591 612
592 for patch in patches: 613 for patch in patches:
593 ui.status("applying %s\n" % patch) 614 ui.status("applying %s\n" % patch)
594 pf = os.path.join(d, patch) 615 pf = os.path.join(d, patch)
595 616
596 text = "" 617 text = []
597 for l in file(pf): 618 user = None
598 if l.startswith("--- ") or l.startswith("diff -r"): break 619 hgpatch = False
599 text += l 620 for line in file(pf):
600 621 line = line.rstrip()
601 # parse values that exist when importing the result of an hg export 622 if line.startswith("--- ") or line.startswith("diff -r"):
602 hgpatch = user = snippet = None 623 break
603 ui.debug('text:\n') 624 elif hgpatch:
604 for t in text.splitlines(): 625 # parse values when importing the result of an hg export
605 ui.debug(t,'\n') 626 if line.startswith("# User "):
606 if t == '# HG changeset patch' or hgpatch == True: 627 user = line[7:]
628 ui.debug('User: %s\n' % user)
629 elif not line.startswith("# ") and line:
630 text.append(line)
631 hgpatch = False
632 elif line == '# HG changeset patch':
607 hgpatch = True 633 hgpatch = True
608 if t.startswith("# User "): 634 else:
609 user = t[7:] 635 text.append(line)
610 ui.debug('User: %s\n' % user) 636
611 if not t.startswith("# ") and t.strip() and not snippet: snippet = t 637 # make sure text isn't empty
612 if snippet: text = snippet + '\n' + text 638 if not text:
639 text = "imported patch %s\n" % patch
640 else:
641 text = "%s\n" % '\n'.join(text)
613 ui.debug('text:\n%s\n' % text) 642 ui.debug('text:\n%s\n' % text)
614
615 # make sure text isn't empty
616 if not text: text = "imported patch %s\n" % patch
617 643
618 f = os.popen("patch -p%d < %s" % (strip, pf)) 644 f = os.popen("patch -p%d < %s" % (strip, pf))
619 files = [] 645 files = []
620 for l in f.read().splitlines(): 646 for l in f.read().splitlines():
621 l.rstrip('\r\n'); 647 l.rstrip('\r\n');
637 """create a new repository in the current directory""" 663 """create a new repository in the current directory"""
638 664
639 if source: 665 if source:
640 ui.warn("no longer supported: use \"hg clone\" instead\n") 666 ui.warn("no longer supported: use \"hg clone\" instead\n")
641 sys.exit(1) 667 sys.exit(1)
642 repo = hg.repository(ui, ".", create=1) 668 hg.repository(ui, ".", create=1)
643 669
644 def locate(ui, repo, *pats, **opts): 670 def locate(ui, repo, *pats, **opts):
645 """locate files matching specific patterns""" 671 """locate files matching specific patterns"""
646 if [p for p in pats if os.sep in p]: 672 if [p for p in pats if os.sep in p]:
647 ui.warn("error: patterns may not contain '%s'\n" % os.sep) 673 ui.warn("error: patterns may not contain '%s'\n" % os.sep)
648 ui.warn("use '-i <dir>' instead\n") 674 ui.warn("use '-i <dir>' instead\n")
649 sys.exit(1) 675 sys.exit(1)
650 def compile(pats, head = '^', tail = os.sep, on_empty = True): 676 def compile(pats, head='^', tail=os.sep, on_empty=True):
651 if not pats: 677 if not pats:
652 class c: 678 class c:
653 def match(self, x): return on_empty 679 def match(self, x):
680 return on_empty
654 return c() 681 return c()
655 regexp = r'%s(?:%s)%s' % ( 682 fnpats = [fnmatch.translate(os.path.normpath(os.path.normcase(p)))[:-1]
656 head, 683 for p in pats]
657 '|'.join([fnmatch.translate(os.path.normpath(os.path.normcase(p)))[:-1] 684 regexp = r'%s(?:%s)%s' % (head, '|'.join(fnpats), tail)
658 for p in pats]),
659 tail)
660 return re.compile(regexp) 685 return re.compile(regexp)
661 exclude = compile(opts['exclude'], on_empty = False) 686 exclude = compile(opts['exclude'], on_empty=False)
662 include = compile(opts['include']) 687 include = compile(opts['include'])
663 pat = compile([os.path.normcase(p) for p in pats], head = '', tail = '$') 688 pat = compile(pats, head='', tail='$')
664 end = '\n' 689 end = opts['print0'] and '\0' or '\n'
665 if opts['print0']: end = '\0' 690 if opts['rev']:
666 if opts['rev']: node = repo.manifest.lookup(opts['rev']) 691 node = repo.manifest.lookup(opts['rev'])
667 else: node = repo.manifest.tip() 692 else:
693 node = repo.manifest.tip()
668 manifest = repo.manifest.read(node) 694 manifest = repo.manifest.read(node)
669 cwd = repo.getcwd() 695 cwd = repo.getcwd()
670 cwd_plus = cwd and (cwd + os.sep) 696 cwd_plus = cwd and (cwd + os.sep)
671 found = [] 697 found = []
672 for f in manifest: 698 for f in manifest:
673 f = os.path.normcase(f) 699 f = os.path.normcase(f)
674 if exclude.match(f) or not(include.match(f) and 700 if exclude.match(f) or not(include.match(f) and
675 f.startswith(cwd_plus) and 701 f.startswith(cwd_plus) and
676 pat.match(os.path.basename(f))): continue 702 pat.match(os.path.basename(f))):
677 if opts['fullpath']: f = os.path.join(repo.root, f) 703 continue
678 elif cwd: f = f[len(cwd_plus):] 704 if opts['fullpath']:
705 f = os.path.join(repo.root, f)
706 elif cwd:
707 f = f[len(cwd_plus):]
679 found.append(f) 708 found.append(f)
680 found.sort() 709 found.sort()
681 for f in found: ui.write(f, end) 710 for f in found:
711 ui.write(f, end)
682 712
683 def log(ui, repo, f=None, **opts): 713 def log(ui, repo, f=None, **opts):
684 """show the revision history of the repository or a single file""" 714 """show the revision history of the repository or a single file"""
685 if f: 715 if f:
686 files = relpath(repo, [f]) 716 files = relpath(repo, [f])
710 filenode = filelog.node(i) 740 filenode = filelog.node(i)
711 i = filelog.linkrev(filenode) 741 i = filelog.linkrev(filenode)
712 changenode = repo.changelog.node(i) 742 changenode = repo.changelog.node(i)
713 prev, other = repo.changelog.parents(changenode) 743 prev, other = repo.changelog.parents(changenode)
714 dodiff(sys.stdout, ui, repo, files, prev, changenode) 744 dodiff(sys.stdout, ui, repo, files, prev, changenode)
715 ui.write("\n") 745 ui.write("\n\n")
716 ui.write("\n") 746
717 747 def manifest(ui, repo, rev=None):
718 def manifest(ui, repo, rev = []):
719 """output the latest or given revision of the project manifest""" 748 """output the latest or given revision of the project manifest"""
720 n = repo.manifest.tip()
721 if rev: 749 if rev:
722 try: 750 try:
723 # assume all revision numbers are for changesets 751 # assume all revision numbers are for changesets
724 n = repo.lookup(rev) 752 n = repo.lookup(rev)
725 change = repo.changelog.read(n) 753 change = repo.changelog.read(n)
726 n = change[0] 754 n = change[0]
727 except: 755 except hg.RepoError:
728 n = repo.manifest.lookup(rev) 756 n = repo.manifest.lookup(rev)
729 757 else:
758 n = repo.manifest.tip()
730 m = repo.manifest.read(n) 759 m = repo.manifest.read(n)
731 mf = repo.manifest.readflags(n) 760 mf = repo.manifest.readflags(n)
732 files = m.keys() 761 files = m.keys()
733 files.sort() 762 files.sort()
734 763
735 for f in files: 764 for f in files:
736 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f)) 765 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
737 766
738 def parents(ui, repo, node = None): 767 def parents(ui, repo, node=None):
739 '''show the parents of the current working dir''' 768 '''show the parents of the current working dir'''
740 if node: 769 if node:
741 p = repo.changelog.parents(repo.lookup(hg.bin(node))) 770 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
742 else: 771 else:
743 p = repo.dirstate.parents() 772 p = repo.dirstate.parents()
773 def rawcommit(ui, repo, *flist, **rc): 802 def rawcommit(ui, repo, *flist, **rc):
774 "raw commit interface" 803 "raw commit interface"
775 804
776 text = rc['text'] 805 text = rc['text']
777 if not text and rc['logfile']: 806 if not text and rc['logfile']:
778 try: text = open(rc['logfile']).read() 807 try:
779 except IOError: pass 808 text = open(rc['logfile']).read()
809 except IOError:
810 pass
780 if not text and not rc['logfile']: 811 if not text and not rc['logfile']:
781 ui.warn("abort: missing commit text\n") 812 ui.warn("abort: missing commit text\n")
782 return 1 813 return 1
783 814
784 files = relpath(repo, list(flist)) 815 files = relpath(repo, list(flist))
791 822
792 def recover(ui, repo): 823 def recover(ui, repo):
793 """roll back an interrupted transaction""" 824 """roll back an interrupted transaction"""
794 repo.recover() 825 repo.recover()
795 826
796 def remove(ui, repo, file, *files): 827 def remove(ui, repo, file1, *files):
797 """remove the specified files on the next commit""" 828 """remove the specified files on the next commit"""
798 repo.remove(relpath(repo, (file,) + files)) 829 repo.remove(relpath(repo, (file1,) + files))
799 830
800 def revert(ui, repo, *names, **opts): 831 def revert(ui, repo, *names, **opts):
801 """revert modified files or dirs back to their unmodified states""" 832 """revert modified files or dirs back to their unmodified states"""
802 node = opts['rev'] and repo.lookup(opts['rev']) or \ 833 node = opts['rev'] and repo.lookup(opts['rev']) or \
803 repo.dirstate.parents()[0] 834 repo.dirstate.parents()[0]
817 chosen = {} 848 chosen = {}
818 849
819 def choose(name): 850 def choose(name):
820 def body(name): 851 def body(name):
821 for r in relnames: 852 for r in relnames:
822 if not name.startswith(r): continue 853 if not name.startswith(r):
854 continue
823 rest = name[len(r):] 855 rest = name[len(r):]
824 if not rest: return r, True 856 if not rest:
857 return r, True
825 depth = rest.count(os.sep) 858 depth = rest.count(os.sep)
826 if not r: 859 if not r:
827 if depth == 0 or not opts['nonrecursive']: return r, True 860 if depth == 0 or not opts['nonrecursive']:
861 return r, True
828 elif rest[0] == os.sep: 862 elif rest[0] == os.sep:
829 if depth == 1 or not opts['nonrecursive']: return r, True 863 if depth == 1 or not opts['nonrecursive']:
864 return r, True
830 return None, False 865 return None, False
831 relname, ret = body(name) 866 relname, ret = body(name)
832 if ret: 867 if ret:
833 chosen[relname] = 1 868 chosen[relname] = 1
834 return ret 869 return ret
873 respond(" ".join(map(hg.hex, h)) + "\n") 908 respond(" ".join(map(hg.hex, h)) + "\n")
874 if cmd == "lock": 909 if cmd == "lock":
875 lock = repo.lock() 910 lock = repo.lock()
876 respond("") 911 respond("")
877 if cmd == "unlock": 912 if cmd == "unlock":
878 if lock: lock.release() 913 if lock:
914 lock.release()
879 lock = None 915 lock = None
880 respond("") 916 respond("")
881 elif cmd == "branches": 917 elif cmd == "branches":
882 arg, nodes = getarg() 918 arg, nodes = getarg()
883 nodes = map(hg.bin, nodes.split(" ")) 919 nodes = map(hg.bin, nodes.split(" "))
885 for b in repo.branches(nodes): 921 for b in repo.branches(nodes):
886 r.append(" ".join(map(hg.hex, b)) + "\n") 922 r.append(" ".join(map(hg.hex, b)) + "\n")
887 respond("".join(r)) 923 respond("".join(r))
888 elif cmd == "between": 924 elif cmd == "between":
889 arg, pairs = getarg() 925 arg, pairs = getarg()
890 pairs = [ map(hg.bin, p.split("-")) for p in pairs.split(" ") ] 926 pairs = [map(hg.bin, p.split("-")) for p in pairs.split(" ")]
891 r = [] 927 r = []
892 for b in repo.between(pairs): 928 for b in repo.between(pairs):
893 r.append(" ".join(map(hg.hex, b)) + "\n") 929 r.append(" ".join(map(hg.hex, b)) + "\n")
894 respond("".join(r)) 930 respond("".join(r))
895 elif cmd == "changegroup": 931 elif cmd == "changegroup":
898 nodes = map(hg.bin, roots.split(" ")) 934 nodes = map(hg.bin, roots.split(" "))
899 935
900 cg = repo.changegroup(nodes) 936 cg = repo.changegroup(nodes)
901 while 1: 937 while 1:
902 d = cg.read(4096) 938 d = cg.read(4096)
903 if not d: break 939 if not d:
940 break
904 fout.write(d) 941 fout.write(d)
905 942
906 fout.flush() 943 fout.flush()
907 944
908 elif cmd == "addchangegroup": 945 elif cmd == "addchangegroup":
913 950
914 r = repo.addchangegroup(fin) 951 r = repo.addchangegroup(fin)
915 respond("") 952 respond("")
916 953
917 def openlog(opt, default): 954 def openlog(opt, default):
918 if opts[opt] and opts[opt] != '-': return open(opts[opt], 'w') 955 if opts[opt] and opts[opt] != '-':
919 else: return default 956 return open(opts[opt], 'w')
957 else:
958 return default
920 959
921 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"], 960 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
922 opts["address"], opts["port"], 961 opts["address"], opts["port"],
923 openlog('accesslog', sys.stdout), 962 openlog('accesslog', sys.stdout),
924 openlog('errorlog', sys.stderr)) 963 openlog('errorlog', sys.stderr))
927 if addr == '0.0.0.0': 966 if addr == '0.0.0.0':
928 addr = socket.gethostname() 967 addr = socket.gethostname()
929 else: 968 else:
930 try: 969 try:
931 addr = socket.gethostbyaddr(addr)[0] 970 addr = socket.gethostbyaddr(addr)[0]
932 except: pass 971 except socket.error:
972 pass
933 if port != 80: 973 if port != 80:
934 ui.status('listening at http://%s:%d/\n' % (addr, port)) 974 ui.status('listening at http://%s:%d/\n' % (addr, port))
935 else: 975 else:
936 ui.status('listening at http://%s/\n' % addr) 976 ui.status('listening at http://%s/\n' % addr)
937 httpd.serve_forever() 977 httpd.serve_forever()
945 ? = not tracked''' 985 ? = not tracked'''
946 986
947 (c, a, d, u) = repo.changes(None, None) 987 (c, a, d, u) = repo.changes(None, None)
948 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) 988 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
949 989
950 for f in c: ui.write("C ", f, "\n") 990 for f in c:
951 for f in a: ui.write("A ", f, "\n") 991 ui.write("C ", f, "\n")
952 for f in d: ui.write("R ", f, "\n") 992 for f in a:
953 for f in u: ui.write("? ", f, "\n") 993 ui.write("A ", f, "\n")
954 994 for f in d:
955 def tag(ui, repo, name, rev = None, **opts): 995 ui.write("R ", f, "\n")
996 for f in u:
997 ui.write("? ", f, "\n")
998
999 def tag(ui, repo, name, rev=None, **opts):
956 """add a tag for the current tip or a given revision""" 1000 """add a tag for the current tip or a given revision"""
957 1001
958 if name == "tip": 1002 if name == "tip":
959 ui.warn("abort: 'tip' is a reserved name!\n") 1003 ui.warn("abort: 'tip' is a reserved name!\n")
960 return -1 1004 return -1
976 if ".hgtags" in x: 1020 if ".hgtags" in x:
977 ui.warn("abort: working copy of .hgtags is changed!\n") 1021 ui.warn("abort: working copy of .hgtags is changed!\n")
978 ui.status("(please commit .hgtags manually)\n") 1022 ui.status("(please commit .hgtags manually)\n")
979 return -1 1023 return -1
980 1024
981 add = 0 1025 add = not os.path.exists(repo.wjoin(".hgtags"))
982 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
983 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name)) 1026 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
984 if add: repo.add([".hgtags"]) 1027 if add:
1028 repo.add([".hgtags"])
985 1029
986 if not opts['text']: 1030 if not opts['text']:
987 opts['text'] = "Added tag %s for changeset %s" % (name, r) 1031 opts['text'] = "Added tag %s for changeset %s" % (name, r)
988 1032
989 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date']) 1033 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
1043 # Command options and aliases are listed here, alphabetically 1087 # Command options and aliases are listed here, alphabetically
1044 1088
1045 table = { 1089 table = {
1046 "^add": (add, [], "hg add [files]"), 1090 "^add": (add, [], "hg add [files]"),
1047 "addremove": (addremove, [], "hg addremove [files]"), 1091 "addremove": (addremove, [], "hg addremove [files]"),
1048 "^annotate": (annotate, 1092 "^annotate":
1049 [('r', 'revision', '', 'revision'), 1093 (annotate,
1050 ('u', 'user', None, 'show user'), 1094 [('r', 'revision', '', 'revision'),
1051 ('n', 'number', None, 'show revision number'), 1095 ('u', 'user', None, 'show user'),
1052 ('c', 'changeset', None, 'show changeset')], 1096 ('n', 'number', None, 'show revision number'),
1053 'hg annotate [-u] [-c] [-n] [-r id] [files]'), 1097 ('c', 'changeset', None, 'show changeset')],
1054 "cat": (cat, [('o', 'output', "", 'output to file')], 'hg cat [-o outfile] <file> [rev]'), 1098 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
1055 "^clone": (clone, [('U', 'noupdate', None, 'skip update after cloning')], 1099 "cat":
1056 'hg clone [options] <source> [dest]'), 1100 (cat,
1057 "^commit|ci": (commit, 1101 [('o', 'output', "", 'output to file')],
1058 [('t', 'text', "", 'commit text'), 1102 'hg cat [-o outfile] <file> [rev]'),
1059 ('A', 'addremove', None, 'run add/remove during commit'), 1103 "^clone":
1060 ('l', 'logfile', "", 'commit text file'), 1104 (clone,
1061 ('d', 'date', "", 'date code'), 1105 [('U', 'noupdate', None, 'skip update after cloning')],
1062 ('u', 'user', "", 'user')], 1106 'hg clone [options] <source> [dest]'),
1063 'hg commit [files]'), 1107 "^commit|ci":
1108 (commit,
1109 [('t', 'text', "", 'commit text'),
1110 ('A', 'addremove', None, 'run add/remove during commit'),
1111 ('l', 'logfile', "", 'commit text file'),
1112 ('d', 'date', "", 'date code'),
1113 ('u', 'user', "", 'user')],
1114 'hg commit [files]'),
1064 "copy": (copy, [], 'hg copy <source> <dest>'), 1115 "copy": (copy, [], 'hg copy <source> <dest>'),
1065 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'), 1116 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'),
1066 "debugstate": (debugstate, [], 'debugstate'), 1117 "debugstate": (debugstate, [], 'debugstate'),
1067 "debugindex": (debugindex, [], 'debugindex <file>'), 1118 "debugindex": (debugindex, [], 'debugindex <file>'),
1068 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), 1119 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
1069 "^diff": (diff, [('r', 'rev', [], 'revision')], 1120 "^diff":
1070 'hg diff [-r A] [-r B] [files]'), 1121 (diff,
1071 "^export": (export, [('o', 'output', "", 'output to file')], 1122 [('r', 'rev', [], 'revision')],
1072 "hg export [-o file] <changeset> ..."), 1123 'hg diff [-r A] [-r B] [files]'),
1124 "^export":
1125 (export,
1126 [('o', 'output', "", 'output to file')],
1127 "hg export [-o file] <changeset> ..."),
1073 "forget": (forget, [], "hg forget [files]"), 1128 "forget": (forget, [], "hg forget [files]"),
1074 "heads": (heads, [], 'hg heads'), 1129 "heads": (heads, [], 'hg heads'),
1075 "help": (help, [], 'hg help [command]'), 1130 "help": (help_, [], 'hg help [command]'),
1076 "identify|id": (identify, [], 'hg identify'), 1131 "identify|id": (identify, [], 'hg identify'),
1077 "import|patch": (import_, 1132 "import|patch":
1078 [('p', 'strip', 1, 'path strip'), 1133 (import_,
1079 ('b', 'base', "", 'base path')], 1134 [('p', 'strip', 1, 'path strip'),
1080 "hg import [options] <patches>"), 1135 ('b', 'base', "", 'base path')],
1136 "hg import [options] <patches>"),
1081 "^init": (init, [], 'hg init'), 1137 "^init": (init, [], 'hg init'),
1082 "locate": (locate, 1138 "locate":
1083 [('0', 'print0', None, 'end records with NUL'), 1139 (locate,
1084 ('f', 'fullpath', None, 'print complete paths'), 1140 [('0', 'print0', None, 'end records with NUL'),
1085 ('i', 'include', [], 'include path in search'), 1141 ('f', 'fullpath', None, 'print complete paths'),
1086 ('r', 'rev', '', 'revision'), 1142 ('i', 'include', [], 'include path in search'),
1087 ('x', 'exclude', [], 'exclude path from search')], 1143 ('r', 'rev', '', 'revision'),
1088 'hg locate [options] [files]'), 1144 ('x', 'exclude', [], 'exclude path from search')],
1089 "^log|history": (log, 1145 'hg locate [options] [files]'),
1090 [('r', 'rev', [], 'revision'), 1146 "^log|history":
1091 ('p', 'patch', None, 'show patch')], 1147 (log,
1092 'hg log [-r A] [-r B] [-p] [file]'), 1148 [('r', 'rev', [], 'revision'),
1149 ('p', 'patch', None, 'show patch')],
1150 'hg log [-r A] [-r B] [-p] [file]'),
1093 "manifest": (manifest, [], 'hg manifest [rev]'), 1151 "manifest": (manifest, [], 'hg manifest [rev]'),
1094 "parents": (parents, [], 'hg parents [node]'), 1152 "parents": (parents, [], 'hg parents [node]'),
1095 "^pull": (pull, 1153 "^pull":
1096 [('u', 'update', None, 'update working directory')], 1154 (pull,
1097 'hg pull [options] [source]'), 1155 [('u', 'update', None, 'update working directory')],
1156 'hg pull [options] [source]'),
1098 "^push": (push, [], 'hg push <destination>'), 1157 "^push": (push, [], 'hg push <destination>'),
1099 "rawcommit": (rawcommit, 1158 "rawcommit":
1100 [('p', 'parent', [], 'parent'), 1159 (rawcommit,
1101 ('d', 'date', "", 'date code'), 1160 [('p', 'parent', [], 'parent'),
1102 ('u', 'user', "", 'user'), 1161 ('d', 'date', "", 'date code'),
1103 ('F', 'files', "", 'file list'), 1162 ('u', 'user', "", 'user'),
1104 ('t', 'text', "", 'commit text'), 1163 ('F', 'files', "", 'file list'),
1105 ('l', 'logfile', "", 'commit text file')], 1164 ('t', 'text', "", 'commit text'),
1106 'hg rawcommit [options] [files]'), 1165 ('l', 'logfile', "", 'commit text file')],
1166 'hg rawcommit [options] [files]'),
1107 "recover": (recover, [], "hg recover"), 1167 "recover": (recover, [], "hg recover"),
1108 "^remove|rm": (remove, [], "hg remove [files]"), 1168 "^remove|rm": (remove, [], "hg remove [files]"),
1109 "^revert": (revert, 1169 "^revert":
1110 [("n", "nonrecursive", None, "don't recurse into subdirs"), 1170 (revert,
1111 ("r", "rev", "", "revision")], 1171 [("n", "nonrecursive", None, "don't recurse into subdirs"),
1112 "hg revert [files|dirs]"), 1172 ("r", "rev", "", "revision")],
1173 "hg revert [files|dirs]"),
1113 "root": (root, [], "hg root"), 1174 "root": (root, [], "hg root"),
1114 "^serve": (serve, [('A', 'accesslog', '', 'access log file'), 1175 "^serve":
1115 ('E', 'errorlog', '', 'error log file'), 1176 (serve,
1116 ('p', 'port', 8000, 'listen port'), 1177 [('A', 'accesslog', '', 'access log file'),
1117 ('a', 'address', '', 'interface address'), 1178 ('E', 'errorlog', '', 'error log file'),
1118 ('n', 'name', os.getcwd(), 'repository name'), 1179 ('p', 'port', 8000, 'listen port'),
1119 ('', 'stdio', None, 'for remote clients'), 1180 ('a', 'address', '', 'interface address'),
1120 ('t', 'templates', "", 'template map')], 1181 ('n', 'name', os.getcwd(), 'repository name'),
1121 "hg serve [options]"), 1182 ('', 'stdio', None, 'for remote clients'),
1183 ('t', 'templates', "", 'template map')],
1184 "hg serve [options]"),
1122 "^status": (status, [], 'hg status'), 1185 "^status": (status, [], 'hg status'),
1123 "tag": (tag, [('l', 'local', None, 'make the tag local'), 1186 "tag":
1124 ('t', 'text', "", 'commit text'), 1187 (tag,
1125 ('d', 'date', "", 'date code'), 1188 [('l', 'local', None, 'make the tag local'),
1126 ('u', 'user', "", 'user')], 1189 ('t', 'text', "", 'commit text'),
1127 'hg tag [options] <name> [rev]'), 1190 ('d', 'date', "", 'date code'),
1191 ('u', 'user', "", 'user')],
1192 'hg tag [options] <name> [rev]'),
1128 "tags": (tags, [], 'hg tags'), 1193 "tags": (tags, [], 'hg tags'),
1129 "tip": (tip, [], 'hg tip'), 1194 "tip": (tip, [], 'hg tip'),
1130 "undo": (undo, [], 'hg undo'), 1195 "undo": (undo, [], 'hg undo'),
1131 "^update|up|checkout|co": 1196 "^update|up|checkout|co":
1132 (update, 1197 (update,
1133 [('m', 'merge', None, 'allow merging of conflicts'), 1198 [('m', 'merge', None, 'allow merging of conflicts'),
1134 ('C', 'clean', None, 'overwrite locally modified files')], 1199 ('C', 'clean', None, 'overwrite locally modified files')],
1135 'hg update [options] [node]'), 1200 'hg update [options] [node]'),
1136 "verify": (verify, [], 'hg verify'), 1201 "verify": (verify, [], 'hg verify'),
1137 "version": (show_version, [], 'hg version'), 1202 "version": (show_version, [], 'hg version'),
1138 } 1203 }
1139 1204
1140 globalopts = [('v', 'verbose', None, 'verbose'), 1205 globalopts = [('v', 'verbose', None, 'verbose'),
1143 ('', 'profile', None, 'profile'), 1208 ('', 'profile', None, 'profile'),
1144 ('R', 'repository', "", 'repository root directory'), 1209 ('R', 'repository', "", 'repository root directory'),
1145 ('', 'traceback', None, 'print traceback on exception'), 1210 ('', 'traceback', None, 'print traceback on exception'),
1146 ('y', 'noninteractive', None, 'run non-interactively'), 1211 ('y', 'noninteractive', None, 'run non-interactively'),
1147 ('', 'version', None, 'output version information and exit'), 1212 ('', 'version', None, 'output version information and exit'),
1148 ] 1213 ]
1149 1214
1150 norepo = "clone init version help debugindex debugindexdot" 1215 norepo = "clone init version help debugindex debugindexdot"
1151 1216
1152 def find(cmd): 1217 def find(cmd):
1153 for e in table.keys(): 1218 for e in table.keys():
1154 if re.match("(%s)$" % e, cmd): 1219 if re.match("(%s)$" % e, cmd):
1155 return table[e] 1220 return table[e]
1156 1221
1157 raise UnknownCommand(cmd) 1222 raise UnknownCommand(cmd)
1158 1223
1159 class SignalInterrupt(Exception): pass 1224 class SignalInterrupt(Exception):
1225 """Exception raised on SIGTERM and SIGHUP."""
1160 1226
1161 def catchterm(*args): 1227 def catchterm(*args):
1162 raise SignalInterrupt 1228 raise SignalInterrupt
1163 1229
1164 def run(): 1230 def run():
1165 sys.exit(dispatch(sys.argv[1:])) 1231 sys.exit(dispatch(sys.argv[1:]))
1166 1232
1167 class ParseError(Exception): pass 1233 class ParseError(Exception):
1234 """Exception raised on errors in parsing the command line."""
1168 1235
1169 def parse(args): 1236 def parse(args):
1170 options = {} 1237 options = {}
1171 cmdoptions = {} 1238 cmdoptions = {}
1172 1239
1176 raise ParseError(None, inst) 1243 raise ParseError(None, inst)
1177 1244
1178 if options["version"]: 1245 if options["version"]:
1179 return ("version", show_version, [], options, cmdoptions) 1246 return ("version", show_version, [], options, cmdoptions)
1180 elif not args: 1247 elif not args:
1181 return ("help", help, [], options, cmdoptions) 1248 return ("help", help_, [], options, cmdoptions)
1182 else: 1249 else:
1183 cmd, args = args[0], args[1:] 1250 cmd, args = args[0], args[1:]
1184 1251
1185 i = find(cmd) 1252 i = find(cmd)
1186 1253
1187 # combine global options into local 1254 # combine global options into local
1188 c = list(i[1]) 1255 c = list(i[1])
1189 l = len(c)
1190 for o in globalopts: 1256 for o in globalopts:
1191 c.append((o[0], o[1], options[o[1]], o[3])) 1257 c.append((o[0], o[1], options[o[1]], o[3]))
1192 1258
1193 try: 1259 try:
1194 args = fancyopts.fancyopts(args, c, cmdoptions) 1260 args = fancyopts.fancyopts(args, c, cmdoptions)
1203 1269
1204 return (cmd, i[0], args, options, cmdoptions) 1270 return (cmd, i[0], args, options, cmdoptions)
1205 1271
1206 def dispatch(args): 1272 def dispatch(args):
1207 signal.signal(signal.SIGTERM, catchterm) 1273 signal.signal(signal.SIGTERM, catchterm)
1208 try: signal.signal(signal.SIGHUP, catchterm) 1274 try:
1209 except: pass 1275 signal.signal(signal.SIGHUP, catchterm)
1276 except AttributeError:
1277 pass
1210 1278
1211 try: 1279 try:
1212 cmd, func, args, options, cmdoptions = parse(args) 1280 cmd, func, args, options, cmdoptions = parse(args)
1213 except ParseError, inst: 1281 except ParseError, inst:
1214 u = ui.ui() 1282 u = ui.ui()
1215 if inst.args[0]: 1283 if inst.args[0]:
1216 u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1])) 1284 u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1]))
1217 help(u, inst.args[0]) 1285 help_(u, inst.args[0])
1218 else: 1286 else:
1219 u.warn("hg: %s\n" % inst.args[1]) 1287 u.warn("hg: %s\n" % inst.args[1])
1220 help(u) 1288 help_(u)
1221 sys.exit(-1) 1289 sys.exit(-1)
1222 except UnknownCommand, inst: 1290 except UnknownCommand, inst:
1223 u = ui.ui() 1291 u = ui.ui()
1224 u.warn("hg: unknown command '%s'\n" % inst.args[0]) 1292 u.warn("hg: unknown command '%s'\n" % inst.args[0])
1225 help(u) 1293 help_(u)
1226 sys.exit(1) 1294 sys.exit(1)
1227 1295
1228 u = ui.ui(options["verbose"], options["debug"], options["quiet"], 1296 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
1229 not options["noninteractive"]) 1297 not options["noninteractive"])
1230 1298
1231 try: 1299 try:
1232 try: 1300 try:
1233 if cmd not in norepo.split(): 1301 if cmd not in norepo.split():
1234 path = options["repository"] or "" 1302 path = options["repository"] or ""
1280 tb = traceback.extract_tb(sys.exc_info()[2]) 1348 tb = traceback.extract_tb(sys.exc_info()[2])
1281 if len(tb) > 2: # no 1349 if len(tb) > 2: # no
1282 raise 1350 raise
1283 u.debug(inst, "\n") 1351 u.debug(inst, "\n")
1284 u.warn("%s: invalid arguments\n" % cmd) 1352 u.warn("%s: invalid arguments\n" % cmd)
1285 help(u, cmd) 1353 help_(u, cmd)
1286 1354
1287 sys.exit(-1) 1355 sys.exit(-1)