~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: aaron.bentley at utoronto
  • Date: 2005-08-27 04:42:41 UTC
  • mfrom: (1092.1.43)
  • mto: (1185.3.4)
  • mto: This revision was merged to the branch mainline in revision 1178.
  • Revision ID: aaron.bentley@utoronto.ca-20050827044241-23d676133b9fc981
Merge of robertc@robertcollins.net-20050826013321-52eee1f1da679ee9

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
459
474
    takes_options = ['verbose', 'no-recurse']
460
475
    
461
476
    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)
 
477
        from bzrlib.add import smart_add, _PrintAddCallback
 
478
        smart_add(file_list, verbose, not no_recurse,
 
479
                  callback=_PrintAddCallback)
464
480
 
465
481
 
466
482
 
604
620
        import tempfile
605
621
        from shutil import rmtree
606
622
        import errno
 
623
        from bzrlib.branch import pull_loc
607
624
        
608
625
        br_to = find_branch('.')
609
626
        stored_loc = None
656
673
    aliases = ['get', 'clone']
657
674
 
658
675
    def run(self, from_location, to_location=None, revision=None):
 
676
        from bzrlib.branch import copy_branch, find_cached_branch
 
677
        import tempfile
659
678
        import errno
660
 
        from bzrlib.merge import merge
661
 
        from bzrlib.branch import DivergedBranches, \
662
 
             find_cached_branch, Branch
663
679
        from shutil import rmtree
664
 
        from meta_store import CachedStore
665
 
        import tempfile
666
680
        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
681
        try:
 
682
            if revision is None:
 
683
                revision = [None]
 
684
            elif len(revision) > 1:
 
685
                raise BzrCommandError(
 
686
                    'bzr branch --revision takes exactly 1 revision value')
674
687
            try:
675
688
                br_from = find_cached_branch(from_location, cache_root)
676
689
            except OSError, e:
679
692
                                          ' exist.' % to_location)
680
693
                else:
681
694
                    raise
682
 
 
683
695
            if to_location is None:
684
696
                to_location = os.path.basename(from_location.rstrip("/\\"))
685
 
 
686
697
            try:
687
698
                os.mkdir(to_location)
688
699
            except OSError, e:
694
705
                                          to_location)
695
706
                else:
696
707
                    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")
 
708
            try:
 
709
                copy_branch(br_from, to_location, revision[0])
 
710
            except bzrlib.errors.NoSuchRevision:
 
711
                rmtree(to_location)
 
712
                msg = "The branch %s has no revision %d." % (from_location, revision[0])
 
713
                raise BzrCommandError(msg)
718
714
        finally:
719
715
            rmtree(cache_root)
720
716
 
721
717
 
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
718
class cmd_renames(Command):
733
719
    """Show list of renamed files.
734
720
 
1337
1323
 
1338
1324
    def run(self, dir='.'):
1339
1325
        from bzrlib.check import check
 
1326
 
1340
1327
        check(find_branch(dir))
1341
1328
 
1342
1329
 
1343
 
 
1344
1330
class cmd_scan_cache(Command):
1345
1331
    hidden = True
1346
1332
    def run(self):
1381
1367
    takes_options = ['email']
1382
1368
    
1383
1369
    def run(self, email=False):
 
1370
        try:
 
1371
            b = bzrlib.branch.find_branch('.')
 
1372
        except:
 
1373
            b = None
 
1374
        
1384
1375
        if email:
1385
 
            print bzrlib.osutils.user_email()
 
1376
            print bzrlib.osutils.user_email(b)
1386
1377
        else:
1387
 
            print bzrlib.osutils.username()
 
1378
            print bzrlib.osutils.username(b)
1388
1379
 
1389
1380
 
1390
1381
class cmd_selftest(Command):
1391
1382
    """Run internal test suite"""
1392
1383
    hidden = True
1393
 
    takes_options = ['verbose']
1394
 
    def run(self, verbose=False):
 
1384
    takes_options = ['verbose', 'pattern']
 
1385
    def run(self, verbose=False, pattern=".*"):
 
1386
        import bzrlib.ui
1395
1387
        from bzrlib.selftest import selftest
1396
 
        return int(not selftest(verbose=verbose))
 
1388
        # we don't want progress meters from the tests to go to the
 
1389
        # real output; and we don't want log messages cluttering up
 
1390
        # the real logs.
 
1391
        save_ui = bzrlib.ui.ui_factory
 
1392
        bzrlib.trace.info('running tests...')
 
1393
        bzrlib.trace.disable_default_logging()
 
1394
        try:
 
1395
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
1396
            result = selftest(verbose=verbose, pattern=pattern)
 
1397
            if result:
 
1398
                bzrlib.trace.info('tests passed')
 
1399
            else:
 
1400
                bzrlib.trace.info('tests failed')
 
1401
            return int(not result)
 
1402
        finally:
 
1403
            bzrlib.trace.enable_default_logging()
 
1404
            bzrlib.ui.ui_factory = save_ui
1397
1405
 
1398
1406
 
1399
1407
class cmd_version(Command):
1454
1462
 
1455
1463
 
1456
1464
 
 
1465
class cmd_find_merge_base(Command):
 
1466
    """Find and print a base revision for merging two branches.
 
1467
 
 
1468
    TODO: Options to specify revisions on either side, as if
 
1469
          merging only part of the history.
 
1470
    """
 
1471
    takes_args = ['branch', 'other']
 
1472
    hidden = True
 
1473
    
 
1474
    def run(self, branch, other):
 
1475
        branch1 = find_branch(branch)
 
1476
        branch2 = find_branch(other)
 
1477
 
 
1478
        base_revno, base_revid = branch1.common_ancestor(branch2)
 
1479
 
 
1480
        if base_revno is None:
 
1481
            raise bzrlib.errors.UnrelatedBranches()
 
1482
 
 
1483
        print 'merge base is revision %s' % base_revid
 
1484
        print ' r%-6d in %s' % (base_revno, branch)
 
1485
 
 
1486
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1487
        
 
1488
        print ' r%-6d in %s' % (other_revno, other)
 
1489
 
 
1490
 
 
1491
 
1457
1492
class cmd_merge(Command):
1458
1493
    """Perform a three-way merge.
1459
1494
    
1546
1581
    """Show help on a command or other topic.
1547
1582
 
1548
1583
    For a list of all available commands, say 'bzr help commands'."""
 
1584
    takes_options = ['long']
1549
1585
    takes_args = ['topic?']
1550
1586
    aliases = ['?']
1551
1587
    
1552
 
    def run(self, topic=None):
 
1588
    def run(self, topic=None, long=False):
1553
1589
        import help
 
1590
        if topic is None and long:
 
1591
            topic = "commands"
1554
1592
        help.help(topic)
1555
1593
 
1556
1594
 
 
1595
class cmd_shell_complete(Command):
 
1596
    """Show appropriate completions for context.
 
1597
 
 
1598
    For a list of all available commands, say 'bzr shell-complete'."""
 
1599
    takes_args = ['context?']
 
1600
    aliases = ['s-c']
 
1601
    hidden = True
 
1602
    
 
1603
    def run(self, context=None):
 
1604
        import shellcomplete
 
1605
        shellcomplete.shellcomplete(context)
1557
1606
 
1558
1607
 
1559
1608
class cmd_missing(Command):
1590
1639
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1591
1640
 
1592
1641
 
 
1642
 
1593
1643
class cmd_plugins(Command):
1594
1644
    """List plugins"""
1595
1645
    hidden = True
1634
1684
    'root':                   str,
1635
1685
    'no-backup':              None,
1636
1686
    'merge-type':             get_merge_type,
 
1687
    'pattern':                str,
1637
1688
    }
1638
1689
 
1639
1690
SHORT_OPTIONS = {
1853
1904
        return 0
1854
1905
    
1855
1906
    if not args:
1856
 
        print >>sys.stderr, "please try 'bzr help' for help"
1857
 
        return 1
 
1907
        from bzrlib.help import help
 
1908
        help(None)
 
1909
        return 0
1858
1910
    
1859
1911
    cmd = str(args.pop(0))
1860
1912
 
1899
1951
        return cmd_class(cmdopts, cmdargs).status 
1900
1952
 
1901
1953
 
1902
 
def _report_exception(summary, quiet=False):
1903
 
    import traceback
1904
 
    
1905
 
    log_error('bzr: ' + summary)
1906
 
    bzrlib.trace.log_exception()
1907
 
 
1908
 
    if os.environ.get('BZR_DEBUG'):
1909
 
        traceback.print_exc()
1910
 
 
1911
 
    if not quiet:
1912
 
        sys.stderr.write('\n')
1913
 
        tb = sys.exc_info()[2]
1914
 
        exinfo = traceback.extract_tb(tb)
1915
 
        if exinfo:
1916
 
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1917
 
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
1918
 
 
1919
 
 
1920
 
 
1921
1954
def main(argv):
1922
 
    
1923
 
    bzrlib.trace.open_tracefile(argv)
 
1955
    import bzrlib.ui
 
1956
    bzrlib.trace.log_startup(argv)
 
1957
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1924
1958
 
1925
1959
    try:
1926
1960
        try:
1927
 
            try:
1928
 
                return run_bzr(argv[1:])
1929
 
            finally:
1930
 
                # do this here inside the exception wrappers to catch EPIPE
1931
 
                sys.stdout.flush()
1932
 
        except BzrError, e:
1933
 
            quiet = isinstance(e, (BzrCommandError))
1934
 
            _report_exception('error: ' + str(e), quiet=quiet)
1935
 
            if len(e.args) > 1:
1936
 
                for h in e.args[1]:
1937
 
                    # some explanation or hints
1938
 
                    log_error('  ' + h)
1939
 
            return 1
1940
 
        except AssertionError, e:
1941
 
            msg = 'assertion failed'
1942
 
            if str(e):
1943
 
                msg += ': ' + str(e)
1944
 
            _report_exception(msg)
1945
 
            return 2
1946
 
        except KeyboardInterrupt, e:
1947
 
            _report_exception('interrupted', quiet=True)
1948
 
            return 2
1949
 
        except Exception, e:
1950
 
            import errno
1951
 
            quiet = False
1952
 
            if (isinstance(e, IOError) 
1953
 
                and hasattr(e, 'errno')
1954
 
                and e.errno == errno.EPIPE):
1955
 
                quiet = True
1956
 
                msg = 'broken pipe'
1957
 
            else:
1958
 
                msg = str(e).rstrip('\n')
1959
 
            _report_exception(msg, quiet)
1960
 
            return 2
1961
 
    finally:
1962
 
        bzrlib.trace.close_trace()
 
1961
            return run_bzr(argv[1:])
 
1962
        finally:
 
1963
            # do this here inside the exception wrappers to catch EPIPE
 
1964
            sys.stdout.flush()
 
1965
    except BzrCommandError, e:
 
1966
        # command line syntax error, etc
 
1967
        log_error(str(e))
 
1968
        return 1
 
1969
    except BzrError, e:
 
1970
        bzrlib.trace.log_exception()
 
1971
        return 1
 
1972
    except AssertionError, e:
 
1973
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
 
1974
        return 3
 
1975
    except KeyboardInterrupt, e:
 
1976
        bzrlib.trace.note('interrupted')
 
1977
        return 2
 
1978
    except Exception, e:
 
1979
        import errno
 
1980
        if (isinstance(e, IOError) 
 
1981
            and hasattr(e, 'errno')
 
1982
            and e.errno == errno.EPIPE):
 
1983
            bzrlib.trace.note('broken pipe')
 
1984
            return 2
 
1985
        else:
 
1986
            bzrlib.trace.log_exception()
 
1987
            return 2
1963
1988
 
1964
1989
 
1965
1990
if __name__ == '__main__':