Mercurial > public > mercurial-scm > hg-stable
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]) |