comparison mercurial/commands.py @ 896:01215ad04283

Merge with BOS
author mpm@selenic.com
date Sat, 13 Aug 2005 19:43:42 -0800
parents 1df0983eb589 77b52b864249
children 3616c0d7ab88
comparison
equal deleted inserted replaced
867:0cd2ee61b10a 896:01215ad04283
12 demandload(globals(), "errno socket version struct atexit") 12 demandload(globals(), "errno socket version struct atexit")
13 13
14 class UnknownCommand(Exception): 14 class UnknownCommand(Exception):
15 """Exception raised if command is not in the command table.""" 15 """Exception raised if command is not in the command table."""
16 16
17 class Abort(Exception):
18 """Raised if a command needs to print an error and exit."""
19
20 def filterfiles(filters, files): 17 def filterfiles(filters, files):
21 l = [x for x in files if x in filters] 18 l = [x for x in files if x in filters]
22 19
23 for t in filters: 20 for t in filters:
24 if t and t[-1] != "/": 21 if t and t[-1] != "/":
33 return files 30 return files
34 31
35 def relpath(repo, args): 32 def relpath(repo, args):
36 cwd = repo.getcwd() 33 cwd = repo.getcwd()
37 if cwd: 34 if cwd:
38 return [util.pconvert(os.path.normpath(os.path.join(cwd, x))) 35 return [util.normpath(os.path.join(cwd, x)) for x in args]
39 for x in args]
40 return args 36 return args
41 37
42 def matchpats(cwd, pats = [], opts = {}, head = ''): 38 def matchpats(repo, cwd, pats = [], opts = {}, head = ''):
43 return util.matcher(cwd, pats or ['.'], opts.get('include'), 39 return util.matcher(repo, cwd, pats or ['.'], opts.get('include'),
44 opts.get('exclude'), head) 40 opts.get('exclude'), head)
45
46 def pathto(n1, n2):
47 '''return the relative path from one place to another'''
48 if not n1: return n2
49 a, b = n1.split(os.sep), n2.split(os.sep)
50 a.reverse(), b.reverse()
51 while a and b and a[-1] == b[-1]:
52 a.pop(), b.pop()
53 b.reverse()
54 return os.sep.join((['..'] * len(a)) + b)
55 41
56 def makewalk(repo, pats, opts, head = ''): 42 def makewalk(repo, pats, opts, head = ''):
57 cwd = repo.getcwd() 43 cwd = repo.getcwd()
58 files, matchfn = matchpats(cwd, pats, opts, head) 44 files, matchfn = matchpats(repo, cwd, pats, opts, head)
59 def walk(): 45 def walk():
60 for src, fn in repo.walk(files = files, match = matchfn): 46 for src, fn in repo.walk(files = files, match = matchfn):
61 yield src, fn, pathto(cwd, fn) 47 yield src, fn, util.pathto(cwd, fn)
62 return files, matchfn, walk() 48 return files, matchfn, walk()
63 49
64 def walk(repo, pats, opts, head = ''): 50 def walk(repo, pats, opts, head = ''):
65 files, matchfn, results = makewalk(repo, pats, opts, head) 51 files, matchfn, results = makewalk(repo, pats, opts, head)
66 for r in results: yield r 52 for r in results: yield r
87 num = repo.changelog.rev(repo.lookup(val)) 73 num = repo.changelog.rev(repo.lookup(val))
88 except KeyError: 74 except KeyError:
89 try: 75 try:
90 num = revlog.rev(revlog.lookup(val)) 76 num = revlog.rev(revlog.lookup(val))
91 except KeyError: 77 except KeyError:
92 raise Abort('invalid revision identifier %s', val) 78 raise util.Abort('invalid revision identifier %s', val)
93 return num 79 return num
94 for spec in revs: 80 for spec in revs:
95 if spec.find(revrangesep) >= 0: 81 if spec.find(revrangesep) >= 0:
96 start, end = spec.split(revrangesep, 1) 82 start, end = spec.split(revrangesep, 1)
97 start = fix(start, 0) 83 start = fix(start, 0)
142 c = expander[c]() 128 c = expander[c]()
143 newname.append(c) 129 newname.append(c)
144 i += 1 130 i += 1
145 return ''.join(newname) 131 return ''.join(newname)
146 except KeyError, inst: 132 except KeyError, inst:
147 raise Abort("invalid format spec '%%%s' in output file name", 133 raise util.Abort("invalid format spec '%%%s' in output file name",
148 inst.args[0]) 134 inst.args[0])
149 135
150 def make_file(repo, r, pat, node=None, 136 def make_file(repo, r, pat, node=None,
151 total=None, seqno=None, revwidth=None, mode='wb'): 137 total=None, seqno=None, revwidth=None, mode='wb'):
152 if not pat or pat == '-': 138 if not pat or pat == '-':
394 def addremove(ui, repo, *pats, **opts): 380 def addremove(ui, repo, *pats, **opts):
395 """add all new files, delete all missing files""" 381 """add all new files, delete all missing files"""
396 q = dict(zip(pats, pats)) 382 q = dict(zip(pats, pats))
397 add, remove = [], [] 383 add, remove = [], []
398 for src, abs, rel in walk(repo, pats, opts): 384 for src, abs, rel in walk(repo, pats, opts):
399 if src == 'f': 385 if src == 'f' and repo.dirstate.state(abs) == '?':
400 if repo.dirstate.state(abs) == '?': 386 add.append(abs)
401 add.append(abs) 387 if rel not in q: ui.status('adding ', rel, '\n')
402 if rel not in q: ui.status('adding ', rel, '\n') 388 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
403 elif repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
404 remove.append(abs) 389 remove.append(abs)
405 if rel not in q: ui.status('removing ', rel, '\n') 390 if rel not in q: ui.status('removing ', rel, '\n')
406 repo.add(add) 391 repo.add(add)
407 repo.remove(remove) 392 repo.remove(remove)
408 393
425 name = name[f+1:] 410 name = name[f+1:]
426 bcache[rev] = name 411 bcache[rev] = name
427 return name 412 return name
428 413
429 if not pats: 414 if not pats:
430 raise Abort('at least one file name or pattern required') 415 raise util.Abort('at least one file name or pattern required')
431 416
432 bcache = {} 417 bcache = {}
433 opmap = [['user', getname], ['number', str], ['changeset', getnode]] 418 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
434 if not opts['user'] and not opts['changeset']: 419 if not opts['user'] and not opts['changeset']:
435 opts['number'] = 1 420 opts['number'] = 1
475 dest = os.path.basename(os.path.normpath(source)) 460 dest = os.path.basename(os.path.normpath(source))
476 461
477 if os.path.exists(dest): 462 if os.path.exists(dest):
478 ui.warn("abort: destination '%s' already exists\n" % dest) 463 ui.warn("abort: destination '%s' already exists\n" % dest)
479 return 1 464 return 1
465
466 dest = os.path.realpath(dest)
480 467
481 class Dircleanup: 468 class Dircleanup:
482 def __init__(self, dir_): 469 def __init__(self, dir_):
483 self.rmtree = shutil.rmtree 470 self.rmtree = shutil.rmtree
484 self.dir_ = dir_ 471 self.dir_ = dir_
539 addremove(ui, repo, *pats, **opts) 526 addremove(ui, repo, *pats, **opts)
540 cwd = repo.getcwd() 527 cwd = repo.getcwd()
541 if not pats and cwd: 528 if not pats and cwd:
542 opts['include'] = [os.path.join(cwd, i) for i in opts['include']] 529 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
543 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']] 530 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
544 fns, match = matchpats((pats and repo.getcwd()) or '', pats, opts) 531 fns, match = matchpats(repo, (pats and repo.getcwd()) or '', pats, opts)
545 if pats: 532 if pats:
546 c, a, d, u = repo.changes(files = fns, match = match) 533 c, a, d, u = repo.changes(files = fns, match = match)
547 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r'] 534 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
548 else: 535 else:
549 files = [] 536 files = []
581 state = repo.dirstate.state(f) 568 state = repo.dirstate.state(f)
582 if state not in "nrm": 569 if state not in "nrm":
583 ui.warn("%s in manifest1, but listed as state %s" % (f, state)) 570 ui.warn("%s in manifest1, but listed as state %s" % (f, state))
584 errors += 1 571 errors += 1
585 if errors: 572 if errors:
586 raise Abort(".hg/dirstate inconsistent with current parent's manifest") 573 raise util.Abort(".hg/dirstate inconsistent with current parent's manifest")
587 574
588 def debugstate(ui, repo): 575 def debugstate(ui, repo):
589 """show the contents of the current dirstate""" 576 """show the contents of the current dirstate"""
590 repo.dirstate.read() 577 repo.dirstate.read()
591 dc = repo.dirstate.map 578 dc = repo.dirstate.map
619 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i)) 606 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
620 ui.write("}\n") 607 ui.write("}\n")
621 608
622 def debugwalk(ui, repo, *pats, **opts): 609 def debugwalk(ui, repo, *pats, **opts):
623 items = list(walk(repo, pats, opts)) 610 items = list(walk(repo, pats, opts))
611 if not items: return
624 fmt = '%%s %%-%ds %%s' % max([len(abs) for (src, abs, rel) in items]) 612 fmt = '%%s %%-%ds %%s' % max([len(abs) for (src, abs, rel) in items])
625 for i in items: print fmt % i 613 for i in items: print fmt % i
626 614
627 def diff(ui, repo, *pats, **opts): 615 def diff(ui, repo, *pats, **opts):
628 """diff working directory (or selected files)""" 616 """diff working directory (or selected files)"""
629 revs = [] 617 revs = []
630 if opts['rev']: 618 if opts['rev']:
631 revs = map(lambda x: repo.lookup(x), opts['rev']) 619 revs = map(lambda x: repo.lookup(x), opts['rev'])
632 620
633 if len(revs) > 2: 621 if len(revs) > 2:
634 raise Abort("too many revisions to diff") 622 raise util.Abort("too many revisions to diff")
635 623
636 files = [] 624 files = []
637 roots, match, results = makewalk(repo, pats, opts) 625 match = util.always
638 for src, abs, rel in results: 626 if pats:
639 files.append(abs) 627 roots, match, results = makewalk(repo, pats, opts)
628 for src, abs, rel in results:
629 files.append(abs)
640 dodiff(sys.stdout, ui, repo, files, *revs, **{'match': match}) 630 dodiff(sys.stdout, ui, repo, files, *revs, **{'match': match})
641 631
642 def doexport(ui, repo, changeset, seqno, total, revwidth, opts): 632 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
643 node = repo.lookup(changeset) 633 node = repo.lookup(changeset)
644 prev, other = repo.changelog.parents(node) 634 prev, other = repo.changelog.parents(node)
663 if fp != sys.stdout: fp.close() 653 if fp != sys.stdout: fp.close()
664 654
665 def export(ui, repo, *changesets, **opts): 655 def export(ui, repo, *changesets, **opts):
666 """dump the header and diffs for one or more changesets""" 656 """dump the header and diffs for one or more changesets"""
667 if not changesets: 657 if not changesets:
668 raise Abort("export requires at least one changeset") 658 raise util.Abort("export requires at least one changeset")
669 seqno = 0 659 seqno = 0
670 revs = list(revrange(ui, repo, changesets)) 660 revs = list(revrange(ui, repo, changesets))
671 total = len(revs) 661 total = len(revs)
672 revwidth = max(len(revs[0]), len(revs[-1])) 662 revwidth = max(len(revs[0]), len(revs[-1]))
673 ui.note(len(revs) > 1 and "Exporting patches:\n" or "Exporting patch:\n") 663 ui.note(len(revs) > 1 and "Exporting patches:\n" or "Exporting patch:\n")
760 pf = l[14:] 750 pf = l[14:]
761 if pf not in files: 751 if pf not in files:
762 files.append(pf) 752 files.append(pf)
763 patcherr = f.close() 753 patcherr = f.close()
764 if patcherr: 754 if patcherr:
765 raise Abort("patch failed") 755 raise util.Abort("patch failed")
766 756
767 if len(files) > 0: 757 if len(files) > 0:
768 addremove(ui, repo, *files) 758 addremove(ui, repo, *files)
769 repo.commit(files, message, user) 759 repo.commit(files, message, user)
770 760
771 def init(ui, source=None): 761 def init(ui, source=None):
772 """create a new repository in the current directory""" 762 """create a new repository in the current directory"""
773 763
774 if source: 764 if source:
775 raise Abort("no longer supported: use \"hg clone\" instead") 765 raise util.Abort("no longer supported: use \"hg clone\" instead")
776 hg.repository(ui, ".", create=1) 766 hg.repository(ui, ".", create=1)
777 767
778 def locate(ui, repo, *pats, **opts): 768 def locate(ui, repo, *pats, **opts):
779 """locate files matching specific patterns""" 769 """locate files matching specific patterns"""
780 end = '\n' 770 end = '\n'
1076 R = removed 1066 R = removed
1077 ? = not tracked 1067 ? = not tracked
1078 ''' 1068 '''
1079 1069
1080 cwd = repo.getcwd() 1070 cwd = repo.getcwd()
1081 files, matchfn = matchpats(cwd, pats, opts) 1071 files, matchfn = matchpats(repo, cwd, pats, opts)
1082 (c, a, d, u) = [[pathto(cwd, x) for x in n] 1072 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1083 for n in repo.changes(files=files, match=matchfn)] 1073 for n in repo.changes(files=files, match=matchfn)]
1084 1074
1085 changetypes = [('modified', 'M', c), 1075 changetypes = [('modified', 'M', c),
1086 ('added', 'A', a), 1076 ('added', 'A', a),
1087 ('removed', 'R', d), 1077 ('removed', 'R', d),
1469 return d() 1459 return d()
1470 except: 1460 except:
1471 if options['traceback']: 1461 if options['traceback']:
1472 traceback.print_exc() 1462 traceback.print_exc()
1473 raise 1463 raise
1474 except util.CommandError, inst:
1475 u.warn("abort: %s\n" % inst.args)
1476 except hg.RepoError, inst: 1464 except hg.RepoError, inst:
1477 u.warn("abort: ", inst, "!\n") 1465 u.warn("abort: ", inst, "!\n")
1478 except SignalInterrupt: 1466 except SignalInterrupt:
1479 u.warn("killed!\n") 1467 u.warn("killed!\n")
1480 except KeyboardInterrupt: 1468 except KeyboardInterrupt:
1498 except OSError, inst: 1486 except OSError, inst:
1499 if hasattr(inst, "filename"): 1487 if hasattr(inst, "filename"):
1500 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename)) 1488 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
1501 else: 1489 else:
1502 u.warn("abort: %s\n" % inst.strerror) 1490 u.warn("abort: %s\n" % inst.strerror)
1503 except Abort, inst: 1491 except util.Abort, inst:
1504 u.warn('abort: ', inst.args[0] % inst.args[1:], '\n') 1492 u.warn('abort: ', inst.args[0] % inst.args[1:], '\n')
1505 sys.exit(1) 1493 sys.exit(1)
1506 except TypeError, inst: 1494 except TypeError, inst:
1507 # was this an argument error? 1495 # was this an argument error?
1508 tb = traceback.extract_tb(sys.exc_info()[2]) 1496 tb = traceback.extract_tb(sys.exc_info()[2])