/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

merge from abently, take his fixes for merge in preference

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
141
156
        raise BzrCommandError(msg)
142
157
    
143
158
 
 
159
def get_merge_type(typestring):
 
160
    """Attempt to find the merge class/factory associated with a string."""
 
161
    from merge import merge_types
 
162
    try:
 
163
        return merge_types[typestring][0]
 
164
    except KeyError:
 
165
        templ = '%s%%7s: %%s' % (' '*12)
 
166
        lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
 
167
        type_list = '\n'.join(lines)
 
168
        msg = "No known merge type %s. Supported types are:\n%s" %\
 
169
            (typestring, type_list)
 
170
        raise BzrCommandError(msg)
 
171
    
 
172
 
144
173
 
145
174
def _get_cmd_dict(plugins_override=True):
146
175
    d = {}
445
474
    takes_options = ['verbose', 'no-recurse']
446
475
    
447
476
    def run(self, file_list, verbose=False, no_recurse=False):
448
 
        from bzrlib.add import smart_add
449
 
        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)
450
480
 
451
481
 
452
482
 
590
620
        import tempfile
591
621
        from shutil import rmtree
592
622
        import errno
 
623
        from bzrlib.branch import pull_loc
593
624
        
594
625
        br_to = find_branch('.')
595
626
        stored_loc = None
642
673
    aliases = ['get', 'clone']
643
674
 
644
675
    def run(self, from_location, to_location=None, revision=None):
 
676
        from bzrlib.branch import copy_branch, find_cached_branch
 
677
        import tempfile
645
678
        import errno
646
 
        from bzrlib.merge import merge
647
 
        from bzrlib.branch import DivergedBranches, \
648
 
             find_cached_branch, Branch
649
679
        from shutil import rmtree
650
 
        from meta_store import CachedStore
651
 
        import tempfile
652
680
        cache_root = tempfile.mkdtemp()
653
 
 
654
 
        if revision is None:
655
 
            revision = [None]
656
 
        elif len(revision) > 1:
657
 
            raise BzrCommandError('bzr branch --revision takes exactly 1 revision value')
658
 
 
659
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')
660
687
            try:
661
688
                br_from = find_cached_branch(from_location, cache_root)
662
689
            except OSError, e:
665
692
                                          ' exist.' % to_location)
666
693
                else:
667
694
                    raise
668
 
 
669
695
            if to_location is None:
670
696
                to_location = os.path.basename(from_location.rstrip("/\\"))
671
 
 
672
697
            try:
673
698
                os.mkdir(to_location)
674
699
            except OSError, e:
680
705
                                          to_location)
681
706
                else:
682
707
                    raise
683
 
            br_to = Branch(to_location, init=True)
684
 
 
685
 
            br_to.set_root_id(br_from.get_root_id())
686
 
 
687
 
            if revision:
688
 
                if revision[0] is None:
689
 
                    revno = br_from.revno()
690
 
                else:
691
 
                    revno, rev_id = br_from.get_revision_info(revision[0])
692
 
                try:
693
 
                    br_to.update_revisions(br_from, stop_revision=revno)
694
 
                except bzrlib.errors.NoSuchRevision:
695
 
                    rmtree(to_location)
696
 
                    msg = "The branch %s has no revision %d." % (from_location,
697
 
                                                                 revno)
698
 
                    raise BzrCommandError(msg)
699
 
            
700
 
            merge((to_location, -1), (to_location, 0), this_dir=to_location,
701
 
                  check_clean=False, ignore_zero=True)
702
 
            from_location = pull_loc(br_from)
703
 
            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)
704
714
        finally:
705
715
            rmtree(cache_root)
706
716
 
707
717
 
708
 
def pull_loc(branch):
709
 
    # TODO: Should perhaps just make attribute be 'base' in
710
 
    # RemoteBranch and Branch?
711
 
    if hasattr(branch, "baseurl"):
712
 
        return branch.baseurl
713
 
    else:
714
 
        return branch.base
715
 
 
716
 
 
717
 
 
718
718
class cmd_renames(Command):
719
719
    """Show list of renamed files.
720
720
 
837
837
    If files are listed, only the changes in those files are listed.
838
838
    Otherwise, all changes for the tree are listed.
839
839
 
840
 
    TODO: Given two revision arguments, show the difference between them.
841
 
 
842
840
    TODO: Allow diff across branches.
843
841
 
844
842
    TODO: Option to use external diff command; could be GNU diff, wdiff,
853
851
          deleted files.
854
852
 
855
853
    TODO: This probably handles non-Unix newlines poorly.
 
854
 
 
855
    examples:
 
856
        bzr diff
 
857
        bzr diff -r1
 
858
        bzr diff -r1:2
856
859
    """
857
860
    
858
861
    takes_args = ['file*']
871
874
        else:
872
875
            b = find_branch('.')
873
876
 
874
 
        # TODO: Make show_diff support taking 2 arguments
875
 
        base_rev = None
876
877
        if revision is not None:
877
 
            if len(revision) != 1:
878
 
                raise BzrCommandError('bzr diff --revision takes exactly one revision identifier')
879
 
            base_rev = revision[0]
880
 
    
881
 
        show_diff(b, base_rev, specific_files=file_list,
882
 
                  external_diff_options=diff_options)
883
 
 
 
878
            if len(revision) == 1:
 
879
                show_diff(b, revision[0], specific_files=file_list,
 
880
                          external_diff_options=diff_options)
 
881
            elif len(revision) == 2:
 
882
                show_diff(b, revision[0], specific_files=file_list,
 
883
                          external_diff_options=diff_options,
 
884
                          revision2=revision[1])
 
885
            else:
 
886
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
 
887
        else:
 
888
            show_diff(b, None, specific_files=file_list,
 
889
                      external_diff_options=diff_options)
884
890
 
885
891
        
886
892
 
967
973
    """
968
974
 
969
975
    takes_args = ['filename?']
970
 
    takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision','long', 'message']
 
976
    takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
 
977
                     'long', 'message', 'short',]
971
978
    
972
979
    def run(self, filename=None, timezone='original',
973
980
            verbose=False,
975
982
            forward=False,
976
983
            revision=None,
977
984
            message=None,
978
 
            long=False):
 
985
            long=False,
 
986
            short=False):
979
987
        from bzrlib.branch import find_branch
980
988
        from bzrlib.log import log_formatter, show_log
981
989
        import codecs
1015
1023
        # in e.g. the default C locale.
1016
1024
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1017
1025
 
1018
 
        if long:
 
1026
        if not short:
1019
1027
            log_format = 'long'
1020
1028
        else:
1021
1029
            log_format = 'short'
1315
1323
 
1316
1324
    def run(self, dir='.'):
1317
1325
        from bzrlib.check import check
 
1326
 
1318
1327
        check(find_branch(dir))
1319
1328
 
1320
1329
 
1321
 
 
1322
1330
class cmd_scan_cache(Command):
1323
1331
    hidden = True
1324
1332
    def run(self):
1359
1367
    takes_options = ['email']
1360
1368
    
1361
1369
    def run(self, email=False):
 
1370
        try:
 
1371
            b = bzrlib.branch.find_branch('.')
 
1372
        except:
 
1373
            b = None
 
1374
        
1362
1375
        if email:
1363
 
            print bzrlib.osutils.user_email()
 
1376
            print bzrlib.osutils.user_email(b)
1364
1377
        else:
1365
 
            print bzrlib.osutils.username()
 
1378
            print bzrlib.osutils.username(b)
1366
1379
 
1367
1380
 
1368
1381
class cmd_selftest(Command):
1369
1382
    """Run internal test suite"""
1370
1383
    hidden = True
1371
 
    takes_options = ['verbose']
1372
 
    def run(self, verbose=False):
 
1384
    takes_options = ['verbose', 'pattern']
 
1385
    def run(self, verbose=False, pattern=".*"):
 
1386
        import bzrlib.ui
1373
1387
        from bzrlib.selftest import selftest
1374
 
        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
1375
1405
 
1376
1406
 
1377
1407
class cmd_version(Command):
1432
1462
 
1433
1463
 
1434
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
 
1435
1492
class cmd_merge(Command):
1436
 
    """Perform a three-way merge of trees.
1437
 
    
1438
 
    The SPEC parameters are working tree or revision specifiers.  Working trees
1439
 
    are specified using standard paths or urls.  No component of a directory
1440
 
    path may begin with '@'.
1441
 
    
1442
 
    Working tree examples: '.', '..', 'foo@', but NOT 'foo/@bar'
1443
 
 
1444
 
    Revisions are specified using a dirname/@revno pair, where dirname is the
1445
 
    branch directory and revno is the revision within that branch.  If no revno
1446
 
    is specified, the latest revision is used.
1447
 
 
1448
 
    Revision examples: './@127', 'foo/@', '../@1'
1449
 
 
1450
 
    The OTHER_SPEC parameter is required.  If the BASE_SPEC parameter is
1451
 
    not supplied, the common ancestor of OTHER_SPEC the current branch is used
1452
 
    as the BASE.
1453
 
 
 
1493
    """Perform a three-way merge.
 
1494
    
 
1495
    The branch is the branch you will merge from.  By default, it will merge
 
1496
    the latest revision.  If you specify a revision, that revision will be
 
1497
    merged.  If you specify two revisions, the first will be used as a BASE, 
 
1498
    and the second one as OTHER.  Revision numbers are always relative to the
 
1499
    specified branch.
 
1500
    
 
1501
    Examples:
 
1502
 
 
1503
    To merge the latest revision from bzr.dev
 
1504
    bzr merge ../bzr.dev
 
1505
 
 
1506
    To merge changes up to and including revision 82 from bzr.dev
 
1507
    bzr merge -r 82 ../bzr.dev
 
1508
 
 
1509
    To merge the changes introduced by 82, without previous changes:
 
1510
    bzr merge -r 81..82 ../bzr.dev
 
1511
    
1454
1512
    merge refuses to run if there are any uncommitted changes, unless
1455
1513
    --force is given.
1456
1514
    """
1457
 
    takes_args = ['other_spec', 'base_spec?']
1458
 
    takes_options = ['force', 'merge-type']
 
1515
    takes_args = ['branch?']
 
1516
    takes_options = ['revision', 'force', 'merge-type']
1459
1517
 
1460
 
    def run(self, other_spec, base_spec=None, force=False, merge_type=None):
 
1518
    def run(self, branch='.', revision=None, force=False, 
 
1519
            merge_type=None):
1461
1520
        from bzrlib.merge import merge
1462
1521
        from bzrlib.merge_core import ApplyMerge3
1463
1522
        if merge_type is None:
1464
1523
            merge_type = ApplyMerge3
1465
 
        merge(parse_spec(other_spec), parse_spec(base_spec),
1466
 
              check_clean=(not force), merge_type=merge_type)
 
1524
 
 
1525
        if revision is None or len(revision) < 1:
 
1526
            base = [None, None]
 
1527
            other = (branch, -1)
 
1528
        else:
 
1529
            if len(revision) == 1:
 
1530
                other = (branch, revision[0])
 
1531
                base = (None, None)
 
1532
            else:
 
1533
                assert len(revision) == 2
 
1534
                if None in revision:
 
1535
                    raise BzrCommandError(
 
1536
                        "Merge doesn't permit that revision specifier.")
 
1537
                base = (branch, revision[0])
 
1538
                other = (branch, revision[1])
 
1539
            
 
1540
        merge(other, base, check_clean=(not force), merge_type=merge_type)
1467
1541
 
1468
1542
 
1469
1543
class cmd_revert(Command):
1479
1553
 
1480
1554
    def run(self, revision=None, no_backup=False, file_list=None):
1481
1555
        from bzrlib.merge import merge
 
1556
        from bzrlib.branch import Branch
1482
1557
        if file_list is not None:
1483
1558
            if len(file_list) == 0:
1484
1559
                raise BzrCommandError("No files specified")
1491
1566
              ignore_zero=True,
1492
1567
              backup_files=not no_backup,
1493
1568
              file_list=file_list)
 
1569
        if not file_list:
 
1570
            Branch('.').set_pending_merges([])
1494
1571
 
1495
1572
 
1496
1573
class cmd_assert_fail(Command):
1504
1581
    """Show help on a command or other topic.
1505
1582
 
1506
1583
    For a list of all available commands, say 'bzr help commands'."""
 
1584
    takes_options = ['long']
1507
1585
    takes_args = ['topic?']
1508
1586
    aliases = ['?']
1509
1587
    
1510
 
    def run(self, topic=None):
 
1588
    def run(self, topic=None, long=False):
1511
1589
        import help
 
1590
        if topic is None and long:
 
1591
            topic = "commands"
1512
1592
        help.help(topic)
1513
1593
 
1514
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)
 
1606
 
 
1607
 
 
1608
class cmd_missing(Command):
 
1609
    """What is missing in this branch relative to other branch.
 
1610
    """
 
1611
    takes_args = ['remote?']
 
1612
    aliases = ['mis', 'miss']
 
1613
    # We don't have to add quiet to the list, because 
 
1614
    # unknown options are parsed as booleans
 
1615
    takes_options = ['verbose', 'quiet']
 
1616
 
 
1617
    def run(self, remote=None, verbose=False, quiet=False):
 
1618
        from bzrlib.branch import find_branch, DivergedBranches
 
1619
        from bzrlib.errors import BzrCommandError
 
1620
        from bzrlib.missing import get_parent, show_missing
 
1621
 
 
1622
        if verbose and quiet:
 
1623
            raise BzrCommandError('Cannot pass both quiet and verbose')
 
1624
 
 
1625
        b = find_branch('.')
 
1626
        parent = get_parent(b)
 
1627
        if remote is None:
 
1628
            if parent is None:
 
1629
                raise BzrCommandError("No missing location known or specified.")
 
1630
            else:
 
1631
                if not quiet:
 
1632
                    print "Using last location: %s" % parent
 
1633
                remote = parent
 
1634
        elif parent is None:
 
1635
            # We only update x-pull if it did not exist, missing should not change the parent
 
1636
            b.controlfile('x-pull', 'wb').write(remote + '\n')
 
1637
        br_remote = find_branch(remote)
 
1638
 
 
1639
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
 
1640
 
1515
1641
 
1516
1642
 
1517
1643
class cmd_plugins(Command):
1546
1672
    'no-recurse':             None,
1547
1673
    'profile':                None,
1548
1674
    'revision':               _parse_revision_str,
 
1675
    'short':                  None,
1549
1676
    'show-ids':               None,
1550
1677
    'timezone':               str,
1551
1678
    'verbose':                None,
1557
1684
    'root':                   str,
1558
1685
    'no-backup':              None,
1559
1686
    'merge-type':             get_merge_type,
 
1687
    'pattern':                str,
1560
1688
    }
1561
1689
 
1562
1690
SHORT_OPTIONS = {
1776
1904
        return 0
1777
1905
    
1778
1906
    if not args:
1779
 
        print >>sys.stderr, "please try 'bzr help' for help"
1780
 
        return 1
 
1907
        from bzrlib.help import help
 
1908
        help(None)
 
1909
        return 0
1781
1910
    
1782
1911
    cmd = str(args.pop(0))
1783
1912
 
1822
1951
        return cmd_class(cmdopts, cmdargs).status 
1823
1952
 
1824
1953
 
1825
 
def _report_exception(summary, quiet=False):
1826
 
    import traceback
1827
 
    
1828
 
    log_error('bzr: ' + summary)
1829
 
    bzrlib.trace.log_exception()
1830
 
 
1831
 
    if os.environ.get('BZR_DEBUG'):
1832
 
        traceback.print_exc()
1833
 
 
1834
 
    if not quiet:
1835
 
        sys.stderr.write('\n')
1836
 
        tb = sys.exc_info()[2]
1837
 
        exinfo = traceback.extract_tb(tb)
1838
 
        if exinfo:
1839
 
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1840
 
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
1841
 
 
1842
 
 
1843
 
 
1844
1954
def main(argv):
1845
 
    
1846
 
    bzrlib.trace.open_tracefile(argv)
 
1955
    import bzrlib.ui
 
1956
    bzrlib.trace.log_startup(argv)
 
1957
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
1847
1958
 
1848
1959
    try:
1849
1960
        try:
1850
 
            try:
1851
 
                return run_bzr(argv[1:])
1852
 
            finally:
1853
 
                # do this here inside the exception wrappers to catch EPIPE
1854
 
                sys.stdout.flush()
1855
 
        except BzrError, e:
1856
 
            quiet = isinstance(e, (BzrCommandError))
1857
 
            _report_exception('error: ' + str(e), quiet=quiet)
1858
 
            if len(e.args) > 1:
1859
 
                for h in e.args[1]:
1860
 
                    # some explanation or hints
1861
 
                    log_error('  ' + h)
1862
 
            return 1
1863
 
        except AssertionError, e:
1864
 
            msg = 'assertion failed'
1865
 
            if str(e):
1866
 
                msg += ': ' + str(e)
1867
 
            _report_exception(msg)
1868
 
            return 2
1869
 
        except KeyboardInterrupt, e:
1870
 
            _report_exception('interrupted', quiet=True)
1871
 
            return 2
1872
 
        except Exception, e:
1873
 
            import errno
1874
 
            quiet = False
1875
 
            if (isinstance(e, IOError) 
1876
 
                and hasattr(e, 'errno')
1877
 
                and e.errno == errno.EPIPE):
1878
 
                quiet = True
1879
 
                msg = 'broken pipe'
1880
 
            else:
1881
 
                msg = str(e).rstrip('\n')
1882
 
            _report_exception(msg, quiet)
1883
 
            return 2
1884
 
    finally:
1885
 
        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
1886
1988
 
1887
1989
 
1888
1990
if __name__ == '__main__':