~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Martin Pool
  • Date: 2005-08-29 10:57:01 UTC
  • mfrom: (1092.1.41)
  • Revision ID: mbp@sourcefrog.net-20050829105701-7aaa81ecf1bfee05
- merge in merge improvements and additional tests 
  from aaron and lifeless

robertc@robertcollins.net-20050825131100-85772edabc817481

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
# TODO: probably should say which arguments are candidates for glob
21
21
# expansion on windows and do that at the command level.
22
22
 
 
23
# TODO: Help messages for options.
 
24
 
 
25
# TODO: Define arguments by objects, rather than just using names.
 
26
# Those objects can specify the expected type of the argument, which
 
27
# would help with validation and shell completion.
 
28
 
 
29
 
 
30
# TODO: Help messages for options.
 
31
 
 
32
# TODO: Define arguments by objects, rather than just using names.
 
33
# Those objects can specify the expected type of the argument, which
 
34
# would help with validation and shell completion.
 
35
 
 
36
 
23
37
import sys
24
38
import os
25
39
 
26
40
import bzrlib
 
41
import bzrlib.trace
27
42
from bzrlib.trace import mutter, note, log_error, warning
28
43
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
29
44
from bzrlib.branch import find_branch
43
58
        k_unsquished = k
44
59
    if not plugin_cmds.has_key(k_unsquished):
45
60
        plugin_cmds[k_unsquished] = cmd
 
61
        mutter('registered plugin command %s', k_unsquished)      
46
62
    else:
47
63
        log_error('Two plugins defined the same command: %r' % k)
48
64
        log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
184
200
 
185
201
    # first look up this command under the specified name
186
202
    cmds = _get_cmd_dict(plugins_override=plugins_override)
 
203
    mutter("all commands: %r", cmds.keys())
187
204
    try:
188
205
        return cmd, cmds[cmd]
189
206
    except KeyError:
459
476
    takes_options = ['verbose', 'no-recurse']
460
477
    
461
478
    def run(self, file_list, verbose=False, no_recurse=False):
462
 
        from bzrlib.add import smart_add
463
 
        smart_add(file_list, verbose, not no_recurse)
 
479
        from bzrlib.add import smart_add, _PrintAddCallback
 
480
        recurse = not no_recurse
 
481
        smart_add(file_list, verbose, not no_recurse,
 
482
                  callback=_PrintAddCallback)
464
483
 
465
484
 
466
485
 
478
497
            os.mkdir(d)
479
498
            if not b:
480
499
                b = find_branch(d)
481
 
            b.add([d], verbose=True)
 
500
            b.add([d])
 
501
            print 'added', d
482
502
 
483
503
 
484
504
class cmd_relpath(Command):
573
593
        
574
594
        if os.path.isdir(names_list[-1]):
575
595
            # move into existing directory
576
 
            b.move(rel_names[:-1], rel_names[-1])
 
596
            for pair in b.move(rel_names[:-1], rel_names[-1]):
 
597
                print "%s => %s" % pair
577
598
        else:
578
599
            if len(names_list) != 2:
579
600
                raise BzrCommandError('to mv multiple files the destination '
580
601
                                      'must be a versioned directory')
581
 
            b.move(rel_names[0], rel_names[1])
 
602
            for pair in b.move(rel_names[0], rel_names[1]):
 
603
                print "%s => %s" % pair
582
604
            
583
605
    
584
606
 
604
626
        import tempfile
605
627
        from shutil import rmtree
606
628
        import errno
 
629
        from bzrlib.branch import pull_loc
607
630
        
608
631
        br_to = find_branch('.')
609
632
        stored_loc = None
656
679
    aliases = ['get', 'clone']
657
680
 
658
681
    def run(self, from_location, to_location=None, revision=None):
 
682
        from bzrlib.branch import copy_branch, find_cached_branch
 
683
        import tempfile
659
684
        import errno
660
 
        from bzrlib.merge import merge
661
 
        from bzrlib.branch import DivergedBranches, \
662
 
             find_cached_branch, Branch
663
685
        from shutil import rmtree
664
 
        from meta_store import CachedStore
665
 
        import tempfile
666
686
        cache_root = tempfile.mkdtemp()
667
 
 
668
 
        if revision is None:
669
 
            revision = [None]
670
 
        elif len(revision) > 1:
671
 
            raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
672
 
 
673
687
        try:
 
688
            if revision is None:
 
689
                revision = [None]
 
690
            elif len(revision) > 1:
 
691
                raise BzrCommandError(
 
692
                    'bzr branch --revision takes exactly 1 revision value')
674
693
            try:
675
694
                br_from = find_cached_branch(from_location, cache_root)
676
695
            except OSError, e:
679
698
                                          ' exist.' % to_location)
680
699
                else:
681
700
                    raise
682
 
 
683
701
            if to_location is None:
684
702
                to_location = os.path.basename(from_location.rstrip("/\\"))
685
 
 
686
703
            try:
687
704
                os.mkdir(to_location)
688
705
            except OSError, e:
694
711
                                          to_location)
695
712
                else:
696
713
                    raise
697
 
            br_to = Branch(to_location, init=True)
698
 
 
699
 
            br_to.set_root_id(br_from.get_root_id())
700
 
 
701
 
            if revision:
702
 
                if revision[0] is None:
703
 
                    revno = br_from.revno()
704
 
                else:
705
 
                    revno, rev_id = br_from.get_revision_info(revision[0])
706
 
                try:
707
 
                    br_to.update_revisions(br_from, stop_revision=revno)
708
 
                except bzrlib.errors.NoSuchRevision:
709
 
                    rmtree(to_location)
710
 
                    msg = "The branch %s has no revision %d." % (from_location,
711
 
                                                                 revno)
712
 
                    raise BzrCommandError(msg)
713
 
            
714
 
            merge((to_location, -1), (to_location, 0), this_dir=to_location,
715
 
                  check_clean=False, ignore_zero=True)
716
 
            from_location = pull_loc(br_from)
717
 
            br_to.controlfile("x-pull", "wb").write(from_location + "\n")
 
714
            try:
 
715
                copy_branch(br_from, to_location, revision[0])
 
716
            except bzrlib.errors.NoSuchRevision:
 
717
                rmtree(to_location)
 
718
                msg = "The branch %s has no revision %d." % (from_location, revision[0])
 
719
                raise BzrCommandError(msg)
718
720
        finally:
719
721
            rmtree(cache_root)
720
722
 
721
723
 
722
 
def pull_loc(branch):
723
 
    # TODO: Should perhaps just make attribute be 'base' in
724
 
    # RemoteBranch and Branch?
725
 
    if hasattr(branch, "baseurl"):
726
 
        return branch.baseurl
727
 
    else:
728
 
        return branch.base
729
 
 
730
 
 
731
 
 
732
724
class cmd_renames(Command):
733
725
    """Show list of renamed files.
734
726
 
1337
1329
 
1338
1330
    def run(self, dir='.'):
1339
1331
        from bzrlib.check import check
 
1332
 
1340
1333
        check(find_branch(dir))
1341
1334
 
1342
1335
 
1343
 
 
1344
1336
class cmd_scan_cache(Command):
1345
1337
    hidden = True
1346
1338
    def run(self):
1365
1357
class cmd_upgrade(Command):
1366
1358
    """Upgrade branch storage to current format.
1367
1359
 
1368
 
    This should normally be used only after the check command tells
1369
 
    you to run it.
 
1360
    The check command or bzr developers may sometimes advise you to run
 
1361
    this command.
1370
1362
    """
1371
1363
    takes_args = ['dir?']
1372
1364
 
1395
1387
class cmd_selftest(Command):
1396
1388
    """Run internal test suite"""
1397
1389
    hidden = True
1398
 
    takes_options = ['verbose']
1399
 
    def run(self, verbose=False):
 
1390
    takes_options = ['verbose', 'pattern']
 
1391
    def run(self, verbose=False, pattern=".*"):
 
1392
        import bzrlib.ui
1400
1393
        from bzrlib.selftest import selftest
1401
 
        return int(not selftest(verbose=verbose))
 
1394
        # we don't want progress meters from the tests to go to the
 
1395
        # real output; and we don't want log messages cluttering up
 
1396
        # the real logs.
 
1397
        save_ui = bzrlib.ui.ui_factory
 
1398
        bzrlib.trace.info('running tests...')
 
1399
        try:
 
1400
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
1401
            result = selftest(verbose=verbose, pattern=pattern)
 
1402
            if result:
 
1403
                bzrlib.trace.info('tests passed')
 
1404
            else:
 
1405
                bzrlib.trace.info('tests failed')
 
1406
            return int(not result)
 
1407
        finally:
 
1408
            bzrlib.ui.ui_factory = save_ui
1402
1409
 
1403
1410
 
1404
1411
class cmd_version(Command):
1459
1466
 
1460
1467
 
1461
1468
 
 
1469
class cmd_find_merge_base(Command):
 
1470
    """Find and print a base revision for merging two branches.
 
1471
 
 
1472
    TODO: Options to specify revisions on either side, as if
 
1473
          merging only part of the history.
 
1474
    """
 
1475
    takes_args = ['branch', 'other']
 
1476
    hidden = True
 
1477
    
 
1478
    def run(self, branch, other):
 
1479
        branch1 = find_branch(branch)
 
1480
        branch2 = find_branch(other)
 
1481
 
 
1482
        base_revno, base_revid = branch1.common_ancestor(branch2)
 
1483
 
 
1484
        if base_revno is None:
 
1485
            raise bzrlib.errors.UnrelatedBranches()
 
1486
 
 
1487
        print 'merge base is revision %s' % base_revid
 
1488
        print ' r%-6d in %s' % (base_revno, branch)
 
1489
 
 
1490
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1491
        
 
1492
        print ' r%-6d in %s' % (other_revno, other)
 
1493
 
 
1494
 
 
1495
 
1462
1496
class cmd_merge(Command):
1463
1497
    """Perform a three-way merge.
1464
1498
    
1493
1527
            merge_type = ApplyMerge3
1494
1528
 
1495
1529
        if revision is None or len(revision) < 1:
1496
 
            base = (None, None)
 
1530
            base = [None, None]
1497
1531
            other = (branch, -1)
1498
1532
        else:
1499
1533
            if len(revision) == 1:
1523
1557
 
1524
1558
    def run(self, revision=None, no_backup=False, file_list=None):
1525
1559
        from bzrlib.merge import merge
 
1560
        from bzrlib.branch import Branch
1526
1561
        if file_list is not None:
1527
1562
            if len(file_list) == 0:
1528
1563
                raise BzrCommandError("No files specified")
1535
1570
              ignore_zero=True,
1536
1571
              backup_files=not no_backup,
1537
1572
              file_list=file_list)
 
1573
        if not file_list:
 
1574
            Branch('.').set_pending_merges([])
1538
1575
 
1539
1576
 
1540
1577
class cmd_assert_fail(Command):
1548
1585
    """Show help on a command or other topic.
1549
1586
 
1550
1587
    For a list of all available commands, say 'bzr help commands'."""
 
1588
    takes_options = ['long']
1551
1589
    takes_args = ['topic?']
1552
1590
    aliases = ['?']
1553
1591
    
1554
 
    def run(self, topic=None):
 
1592
    def run(self, topic=None, long=False):
1555
1593
        import help
 
1594
        if topic is None and long:
 
1595
            topic = "commands"
1556
1596
        help.help(topic)
1557
1597
 
1558
1598
 
1603
1643
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1604
1644
 
1605
1645
 
 
1646
 
1606
1647
class cmd_plugins(Command):
1607
1648
    """List plugins"""
1608
1649
    hidden = True
1611
1652
        from inspect import getdoc
1612
1653
        from pprint import pprint
1613
1654
        for plugin in bzrlib.plugin.all_plugins:
1614
 
            print plugin.__path__[0]
 
1655
            if hasattr(plugin, '__path__'):
 
1656
                print plugin.__path__[0]
 
1657
            else:
 
1658
                print `plugin`
1615
1659
            d = getdoc(plugin)
1616
1660
            if d:
1617
1661
                print '\t', d.split('\n')[0]
1647
1691
    'root':                   str,
1648
1692
    'no-backup':              None,
1649
1693
    'merge-type':             get_merge_type,
 
1694
    'pattern':                str,
1650
1695
    }
1651
1696
 
1652
1697
SHORT_OPTIONS = {
1866
1911
        return 0
1867
1912
    
1868
1913
    if not args:
1869
 
        print >>sys.stderr, "please try 'bzr help' for help"
1870
 
        return 1
 
1914
        from bzrlib.help import help
 
1915
        help(None)
 
1916
        return 0
1871
1917
    
1872
1918
    cmd = str(args.pop(0))
1873
1919
 
1912
1958
        return cmd_class(cmdopts, cmdargs).status 
1913
1959
 
1914
1960
 
1915
 
def _report_exception(summary, quiet=False):
1916
 
    import traceback
1917
 
    
1918
 
    log_error('bzr: ' + summary)
1919
 
    bzrlib.trace.log_exception()
1920
 
 
1921
 
    if os.environ.get('BZR_DEBUG'):
1922
 
        traceback.print_exc()
1923
 
 
1924
 
    if not quiet:
1925
 
        sys.stderr.write('\n')
1926
 
        tb = sys.exc_info()[2]
1927
 
        exinfo = traceback.extract_tb(tb)
1928
 
        if exinfo:
1929
 
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1930
 
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
1931
 
 
1932
 
 
1933
 
 
1934
1961
def main(argv):
1935
 
    
1936
 
    bzrlib.trace.open_tracefile(argv)
 
1962
    import bzrlib.ui
 
1963
    bzrlib.trace.log_startup(argv)
 
1964
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1937
1965
 
1938
1966
    try:
1939
1967
        try:
1940
 
            try:
1941
 
                return run_bzr(argv[1:])
1942
 
            finally:
1943
 
                # do this here inside the exception wrappers to catch EPIPE
1944
 
                sys.stdout.flush()
1945
 
        except BzrError, e:
1946
 
            quiet = isinstance(e, (BzrCommandError))
1947
 
            _report_exception('error: ' + str(e), quiet=quiet)
1948
 
            if len(e.args) > 1:
1949
 
                for h in e.args[1]:
1950
 
                    # some explanation or hints
1951
 
                    log_error('  ' + h)
1952
 
            return 1
1953
 
        except AssertionError, e:
1954
 
            msg = 'assertion failed'
1955
 
            if str(e):
1956
 
                msg += ': ' + str(e)
1957
 
            _report_exception(msg)
1958
 
            return 2
1959
 
        except KeyboardInterrupt, e:
1960
 
            _report_exception('interrupted', quiet=True)
1961
 
            return 2
1962
 
        except Exception, e:
1963
 
            import errno
1964
 
            quiet = False
1965
 
            if (isinstance(e, IOError) 
1966
 
                and hasattr(e, 'errno')
1967
 
                and e.errno == errno.EPIPE):
1968
 
                quiet = True
1969
 
                msg = 'broken pipe'
1970
 
            else:
1971
 
                msg = str(e).rstrip('\n')
1972
 
            _report_exception(msg, quiet)
1973
 
            return 2
1974
 
    finally:
1975
 
        bzrlib.trace.close_trace()
 
1968
            return run_bzr(argv[1:])
 
1969
        finally:
 
1970
            # do this here inside the exception wrappers to catch EPIPE
 
1971
            sys.stdout.flush()
 
1972
    except BzrCommandError, e:
 
1973
        # command line syntax error, etc
 
1974
        log_error(str(e))
 
1975
        return 1
 
1976
    except BzrError, e:
 
1977
        bzrlib.trace.log_exception()
 
1978
        return 1
 
1979
    except AssertionError, e:
 
1980
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
 
1981
        return 3
 
1982
    except KeyboardInterrupt, e:
 
1983
        bzrlib.trace.note('interrupted')
 
1984
        return 2
 
1985
    except Exception, e:
 
1986
        import errno
 
1987
        if (isinstance(e, IOError) 
 
1988
            and hasattr(e, 'errno')
 
1989
            and e.errno == errno.EPIPE):
 
1990
            bzrlib.trace.note('broken pipe')
 
1991
            return 2
 
1992
        else:
 
1993
            bzrlib.trace.log_exception()
 
1994
            return 2
1976
1995
 
1977
1996
 
1978
1997
if __name__ == '__main__':