~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[merge] update from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
19
 
# DO NOT change this to cStringIO - it results in control files 
20
 
# written as UCS4
21
 
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
22
 
# RBC 20051018
23
19
 
24
 
from StringIO import StringIO
 
20
import os
25
21
import sys
26
 
import os
27
22
 
28
23
import bzrlib
29
24
from bzrlib import BZRDIR
 
25
from bzrlib._merge_core import ApplyMerge3
30
26
from bzrlib.commands import Command, display_command
31
27
from bzrlib.branch import Branch
32
28
from bzrlib.revision import common_ancestor
34
30
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
35
31
                           NotBranchError, DivergedBranches, NotConflicted,
36
32
                           NoSuchFile, NoWorkingTree, FileInWrongBranch)
 
33
from bzrlib.log import show_one_log
37
34
from bzrlib.option import Option
38
35
from bzrlib.revisionspec import RevisionSpec
39
36
import bzrlib.trace
40
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
 
38
from bzrlib.transport.local import LocalTransport
41
39
from bzrlib.workingtree import WorkingTree
42
 
from bzrlib.log import show_one_log
43
40
 
44
41
 
45
42
def tree_files(file_list, default_branch=u'.'):
148
145
            raise BzrCommandError('You must supply either --revision or a revision_id')
149
146
        b = WorkingTree.open_containing(u'.')[0].branch
150
147
        if revision_id is not None:
151
 
            sys.stdout.write(b.get_revision_xml(revision_id))
 
148
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
152
149
        elif revision is not None:
153
150
            for rev in revision:
154
151
                if rev is None:
155
152
                    raise BzrCommandError('You cannot specify a NULL revision.')
156
153
                revno, rev_id = rev.in_history(b)
157
 
                sys.stdout.write(b.get_revision_xml(rev_id))
 
154
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
158
155
    
159
156
 
160
157
class cmd_revno(Command):
298
295
            if len(revision) > 1:
299
296
                raise BzrCommandError('bzr inventory --revision takes'
300
297
                    ' exactly one revision identifier')
301
 
            inv = tree.branch.get_revision_inventory(
 
298
            inv = tree.branch.repository.get_revision_inventory(
302
299
                revision[0].in_history(tree.branch).rev_id)
303
300
 
304
301
        for path, entry in inv.entries():
399
396
    takes_args = ['location?']
400
397
 
401
398
    def run(self, location=None, remember=False, overwrite=False, verbose=False):
402
 
        from bzrlib.merge import merge
403
399
        from shutil import rmtree
404
400
        import errno
405
401
        # FIXME: too much stuff is in the command class        
502
498
                        if new_transport.base == transport.base:
503
499
                            raise BzrCommandError("Could not creeate "
504
500
                                                  "path prefix.")
505
 
            br_to = Branch.initialize(location)
 
501
            if isinstance(transport, LocalTransport):
 
502
                br_to = WorkingTree.create_standalone(location).branch
 
503
            else:
 
504
                br_to = Branch.create(location)
506
505
        old_rh = br_to.revision_history()
507
506
        try:
508
507
            try:
548
547
    aliases = ['get', 'clone']
549
548
 
550
549
    def run(self, from_location, to_location=None, revision=None, basis=None):
551
 
        from bzrlib.clone import copy_branch
552
550
        import errno
553
551
        from shutil import rmtree
554
552
        if revision is None:
591
589
                else:
592
590
                    raise
593
591
            try:
594
 
                copy_branch(br_from, to_location, revision_id, basis_branch)
 
592
                br_from.clone(to_location, revision_id, basis_branch)
595
593
            except bzrlib.errors.NoSuchRevision:
596
594
                rmtree(to_location)
597
595
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
602
600
                raise BzrCommandError(msg)
603
601
            branch = Branch.open(to_location)
604
602
            if name:
605
 
                name = StringIO(name)
606
 
                branch.put_controlfile('branch-name', name)
 
603
                branch.control_files.put_utf8('branch-name', name)
 
604
 
607
605
            note('Branched %d revision(s).' % branch.revno())
608
606
        finally:
609
607
            br_from.unlock()
710
708
        tree = WorkingTree.open_containing(u'.')[0]
711
709
        b = tree.branch
712
710
        # FIXME. should be tree.last_revision
713
 
        for revision_id in b.get_ancestry(b.last_revision()):
 
711
        for revision_id in b.repository.get_ancestry(b.last_revision()):
714
712
            print revision_id
715
713
 
716
714
 
740
738
            # locations if the user supplies an extended path
741
739
            if not os.path.exists(location):
742
740
                os.mkdir(location)
743
 
        Branch.initialize(location)
 
741
        WorkingTree.create_standalone(location)
744
742
 
745
743
 
746
744
class cmd_diff(Command):
792
790
        if revision is not None:
793
791
            if b2 is not None:
794
792
                raise BzrCommandError("Can't specify -r with two branches")
795
 
            if len(revision) == 1:
 
793
            if (len(revision) == 1) or (revision[1].spec is None):
796
794
                return show_diff(tree.branch, revision[0], specific_files=file_list,
797
795
                                 external_diff_options=diff_options)
798
796
            elif len(revision) == 2:
858
856
            if file_id in basis_inv:
859
857
                continue
860
858
            path = inv.id2path(file_id)
861
 
            if not os.access(b.abspath(path), os.F_OK):
 
859
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
862
860
                continue
863
861
            print path
864
862
                
927
925
            if tree is None:
928
926
                b, fp = Branch.open_containing(filename)
929
927
                if fp != '':
930
 
                    inv = b.get_inventory(b.last_revision())
 
928
                    inv = b.repository.get_inventory(b.last_revision())
931
929
            if fp != '':
932
930
                file_id = inv.path2id(fp)
933
931
            else:
1036
1034
        elif relpath:
1037
1035
            relpath += '/'
1038
1036
        if revision is not None:
1039
 
            tree = tree.branch.revision_tree(
 
1037
            tree = tree.branch.repository.revision_tree(
1040
1038
                revision[0].in_history(tree.branch).rev_id)
1041
1039
        for fp, fc, kind, fid, entry in tree.list_files():
1042
1040
            if fp.startswith(relpath):
1172
1170
 
1173
1171
    Note: export of tree with non-ascii filenames to zip is not supported.
1174
1172
 
1175
 
    Supported formats       Autodetected by extension
1176
 
    -----------------       -------------------------
 
1173
     Supported formats       Autodetected by extension
 
1174
     -----------------       -------------------------
1177
1175
         dir                            -
1178
1176
         tar                          .tar
1179
1177
         tbz2                    .tar.bz2, .tbz2
1194
1192
            if len(revision) != 1:
1195
1193
                raise BzrError('bzr export --revision takes exactly 1 argument')
1196
1194
            rev_id = revision[0].in_history(b).rev_id
1197
 
        t = b.revision_tree(rev_id)
 
1195
        t = b.repository.revision_tree(rev_id)
1198
1196
        try:
1199
1197
            export(t, dest, format, root)
1200
1198
        except errors.NoSuchExportFormat, e:
1366
1364
    """Upgrade branch storage to current format.
1367
1365
 
1368
1366
    The check command or bzr developers may sometimes advise you to run
1369
 
    this command.
1370
 
 
1371
 
    This version of this command upgrades from the full-text storage
1372
 
    used by bzr 0.0.8 and earlier to the weave format (v5).
 
1367
    this command. When the default format has changed you may also be warned
 
1368
    during other operations to upgrade.
1373
1369
    """
1374
 
    takes_args = ['dir?']
 
1370
    takes_args = ['url?']
1375
1371
 
1376
 
    def run(self, dir=u'.'):
 
1372
    def run(self, url='.'):
1377
1373
        from bzrlib.upgrade import upgrade
1378
 
        upgrade(dir)
 
1374
        upgrade(url)
1379
1375
 
1380
1376
 
1381
1377
class cmd_whoami(Command):
1395
1391
        else:
1396
1392
            print config.username()
1397
1393
 
 
1394
 
1398
1395
class cmd_nick(Command):
1399
 
    """\
1400
 
    Print or set the branch nickname.  
 
1396
    """Print or set the branch nickname.  
 
1397
 
1401
1398
    If unset, the tree root directory name is used as the nickname
1402
1399
    To print the current nickname, execute with no argument.  
1403
1400
    """
1413
1410
    def printme(self, branch):
1414
1411
        print branch.nick 
1415
1412
 
 
1413
 
1416
1414
class cmd_selftest(Command):
1417
1415
    """Run internal test suite.
1418
1416
    
1423
1421
    
1424
1422
    If arguments are given, they are regular expressions that say
1425
1423
    which tests should run.
 
1424
 
 
1425
    If the global option '--no-plugins' is given, plugins are not loaded
 
1426
    before running the selftests.  This has two effects: features provided or
 
1427
    modified by plugins will not be tested, and tests provided by plugins will
 
1428
    not be run.
 
1429
 
 
1430
    examples:
 
1431
        bzr selftest ignore
 
1432
        bzr --no-plugins selftest -v
1426
1433
    """
1427
1434
    # TODO: --list should give a list of all available tests
 
1435
 
 
1436
    # NB: this is used from the class without creating an instance, which is
 
1437
    # why it does not have a self parameter.
 
1438
    def get_transport_type(typestring):
 
1439
        """Parse and return a transport specifier."""
 
1440
        if typestring == "sftp":
 
1441
            from bzrlib.transport.sftp import SFTPAbsoluteServer
 
1442
            return SFTPAbsoluteServer
 
1443
        if typestring == "memory":
 
1444
            from bzrlib.transport.memory import MemoryServer
 
1445
            return MemoryServer
 
1446
        msg = "No known transport type %s. Supported types are: sftp\n" %\
 
1447
            (typestring)
 
1448
        raise BzrCommandError(msg)
 
1449
 
1428
1450
    hidden = True
1429
1451
    takes_args = ['testspecs*']
1430
 
    takes_options = ['verbose', 
 
1452
    takes_options = ['verbose',
1431
1453
                     Option('one', help='stop when one test fails'),
1432
1454
                     Option('keep-output', 
1433
 
                            help='keep output directories when tests fail')
 
1455
                            help='keep output directories when tests fail'),
 
1456
                     Option('transport', 
 
1457
                            help='Use a different transport by default '
 
1458
                                 'throughout the test suite.',
 
1459
                            type=get_transport_type),
1434
1460
                    ]
1435
1461
 
1436
1462
    def run(self, testspecs_list=None, verbose=False, one=False,
1437
 
            keep_output=False):
 
1463
            keep_output=False, transport=None):
1438
1464
        import bzrlib.ui
1439
1465
        from bzrlib.tests import selftest
1440
1466
        # we don't want progress meters from the tests to go to the
1451
1477
            result = selftest(verbose=verbose, 
1452
1478
                              pattern=pattern,
1453
1479
                              stop_on_failure=one, 
1454
 
                              keep_output=keep_output)
 
1480
                              keep_output=keep_output,
 
1481
                              transport=transport)
1455
1482
            if result:
1456
1483
                bzrlib.trace.info('tests passed')
1457
1484
            else:
1529
1556
        last1 = branch1.last_revision()
1530
1557
        last2 = branch2.last_revision()
1531
1558
 
1532
 
        source = MultipleRevisionSources(branch1, branch2)
 
1559
        source = MultipleRevisionSources(branch1.repository, 
 
1560
                                         branch2.repository)
1533
1561
        
1534
1562
        base_rev_id = common_ancestor(last1, last2, source)
1535
1563
 
1582
1610
 
1583
1611
    def run(self, branch=None, revision=None, force=False, merge_type=None,
1584
1612
            show_base=False, reprocess=False):
1585
 
        from bzrlib.merge import merge
1586
 
        from bzrlib.merge_core import ApplyMerge3
 
1613
        from bzrlib._merge_core import ApplyMerge3
1587
1614
        if merge_type is None:
1588
1615
            merge_type = ApplyMerge3
1589
1616
        if branch is None:
1640
1667
    def run(self, file_list=None, merge_type=None, show_base=False,
1641
1668
            reprocess=False):
1642
1669
        from bzrlib.merge import merge_inner, transform_tree
1643
 
        from bzrlib.merge_core import ApplyMerge3
 
1670
        from bzrlib._merge_core import ApplyMerge3
1644
1671
        if merge_type is None:
1645
1672
            merge_type = ApplyMerge3
1646
1673
        tree, file_list = tree_files(file_list)
1651
1678
                raise BzrCommandError("Sorry, remerge only works after normal"
1652
1679
                                      + " merges.  Not cherrypicking or"
1653
1680
                                      + "multi-merges.")
 
1681
            repository = tree.branch.repository
1654
1682
            base_revision = common_ancestor(tree.branch.last_revision(), 
1655
 
                                            pending_merges[0], tree.branch)
1656
 
            base_tree = tree.branch.revision_tree(base_revision)
1657
 
            other_tree = tree.branch.revision_tree(pending_merges[0])
 
1683
                                            pending_merges[0], repository)
 
1684
            base_tree = repository.revision_tree(base_revision)
 
1685
            other_tree = repository.revision_tree(pending_merges[0])
1658
1686
            interesting_ids = None
1659
1687
            if file_list is not None:
1660
1688
                interesting_ids = set()
1701
1729
    aliases = ['merge-revert']
1702
1730
 
1703
1731
    def run(self, revision=None, no_backup=False, file_list=None):
1704
 
        from bzrlib.merge import merge_inner
1705
1732
        from bzrlib.commands import parse_spec
1706
1733
        if file_list is not None:
1707
1734
            if len(file_list) == 0:
1708
1735
                raise BzrCommandError("No files specified")
1709
1736
        else:
1710
1737
            file_list = []
 
1738
        
 
1739
        tree, file_list = tree_files(file_list)
1711
1740
        if revision is None:
1712
 
            revno = -1
1713
 
            tree = WorkingTree.open_containing(u'.')[0]
1714
1741
            # FIXME should be tree.last_revision
1715
1742
            rev_id = tree.branch.last_revision()
1716
1743
        elif len(revision) != 1:
1717
1744
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1718
1745
        else:
1719
 
            tree, file_list = tree_files(file_list)
1720
1746
            rev_id = revision[0].in_history(tree.branch).rev_id
1721
 
        tree.revert(file_list, tree.branch.revision_tree(rev_id),
1722
 
                                not no_backup)
 
1747
        tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
 
1748
                    not no_backup)
1723
1749
 
1724
1750
 
1725
1751
class cmd_assert_fail(Command):
1770
1796
        from bzrlib.branch import Branch
1771
1797
        from_b = Branch.open(from_branch)
1772
1798
        to_b = Branch.open(to_branch)
1773
 
        from_b.lock_read()
1774
 
        try:
1775
 
            to_b.lock_write()
1776
 
            try:
1777
 
                Fetcher(to_b, from_b)
1778
 
            finally:
1779
 
                to_b.unlock()
1780
 
        finally:
1781
 
            from_b.unlock()
 
1799
        Fetcher(to_b, from_b)
1782
1800
 
1783
1801
 
1784
1802
class cmd_missing(Command):
1821
1839
            remote_extra.reverse()
1822
1840
        if local_extra and not theirs_only:
1823
1841
            print "You have %d extra revision(s):" % len(local_extra)
1824
 
            for data in iter_log_data(local_extra, local_branch, verbose):
 
1842
            for data in iter_log_data(local_extra, local_branch.repository,
 
1843
                                      verbose):
1825
1844
                lf.show(*data)
1826
1845
            printed_local = True
1827
1846
        else:
1830
1849
            if printed_local is True:
1831
1850
                print "\n\n"
1832
1851
            print "You are missing %d revision(s):" % len(remote_extra)
1833
 
            for data in iter_log_data(remote_extra, remote_branch, verbose):
 
1852
            for data in iter_log_data(remote_extra, remote_branch.repository, 
 
1853
                                      verbose):
1834
1854
                lf.show(*data)
1835
1855
        if not remote_extra and not local_extra:
1836
1856
            status_code = 0
1876
1896
                rev_id = b.last_revision()
1877
1897
            else:
1878
1898
                rev_id = revision[0].in_history(b).rev_id
1879
 
            t = Testament.from_revision(b, rev_id)
 
1899
            t = Testament.from_revision(b.repository, rev_id)
1880
1900
            if long:
1881
1901
                sys.stdout.writelines(t.as_text_lines())
1882
1902
            else:
1912
1932
        branch.lock_read()
1913
1933
        try:
1914
1934
            file_id = tree.inventory.path2id(relpath)
1915
 
            tree = branch.revision_tree(branch.last_revision())
 
1935
            tree = branch.repository.revision_tree(branch.last_revision())
1916
1936
            file_version = tree.inventory[file_id].revision
1917
1937
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1918
1938
        finally:
1937
1957
        b = WorkingTree.open_containing(u'.')[0].branch
1938
1958
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1939
1959
        if revision_id is not None:
1940
 
            b.sign_revision(revision_id, gpg_strategy)
 
1960
            b.repository.sign_revision(revision_id, gpg_strategy)
1941
1961
        elif revision is not None:
1942
1962
            if len(revision) == 1:
1943
1963
                revno, rev_id = revision[0].in_history(b)
1944
 
                b.sign_revision(rev_id, gpg_strategy)
 
1964
                b.repository.sign_revision(rev_id, gpg_strategy)
1945
1965
            elif len(revision) == 2:
1946
1966
                # are they both on rh- if so we can walk between them
1947
1967
                # might be nice to have a range helper for arbitrary
1953
1973
                if from_revno is None or to_revno is None:
1954
1974
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
1955
1975
                for revno in range(from_revno, to_revno + 1):
1956
 
                    b.sign_revision(b.get_rev_id(revno), gpg_strategy)
 
1976
                    b.repository.sign_revision(b.get_rev_id(revno), 
 
1977
                                               gpg_strategy)
1957
1978
            else:
1958
1979
                raise BzrCommandError('Please supply either one revision, or a range.')
1959
1980
 
1971
1992
    
1972
1993
    In the future, uncommit will create a changeset, which can then
1973
1994
    be re-applied.
 
1995
 
 
1996
    TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
 
1997
              information in 'branch-as-repostory' branches.
 
1998
    TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
 
1999
              information in shared branches as well.
1974
2000
    """
1975
 
    takes_options = ['all', 'verbose', 'revision',
 
2001
    takes_options = ['verbose', 'revision',
1976
2002
                    Option('dry-run', help='Don\'t actually make changes'),
1977
2003
                    Option('force', help='Say yes to all questions.')]
1978
2004
    takes_args = ['location?']
1979
2005
    aliases = []
1980
2006
 
1981
 
    def run(self, location=None, all=False,
 
2007
    def run(self, location=None, 
1982
2008
            dry_run=False, verbose=False,
1983
2009
            revision=None, force=False):
1984
2010
        from bzrlib.branch import Branch
2001
2027
        for r in range(revno, b.revno()+1):
2002
2028
            rev_id = b.get_rev_id(r)
2003
2029
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2004
 
            lf.show(r, b.get_revision(rev_id), None)
 
2030
            lf.show(r, b.repository.get_revision(rev_id), None)
2005
2031
 
2006
2032
        if dry_run:
2007
2033
            print 'Dry-run, pretending to remove the above revisions.'
2015
2041
                    print 'Canceled'
2016
2042
                    return 0
2017
2043
 
2018
 
        uncommit(b, remove_files=all,
2019
 
                dry_run=dry_run, verbose=verbose,
 
2044
        uncommit(b, dry_run=dry_run, verbose=verbose,
2020
2045
                revno=revno)
2021
2046
 
2022
2047
 
 
2048
def merge(other_revision, base_revision,
 
2049
          check_clean=True, ignore_zero=False,
 
2050
          this_dir=None, backup_files=False, merge_type=ApplyMerge3,
 
2051
          file_list=None, show_base=False, reprocess=False):
 
2052
    """Merge changes into a tree.
 
2053
 
 
2054
    base_revision
 
2055
        list(path, revno) Base for three-way merge.  
 
2056
        If [None, None] then a base will be automatically determined.
 
2057
    other_revision
 
2058
        list(path, revno) Other revision for three-way merge.
 
2059
    this_dir
 
2060
        Directory to merge changes into; '.' by default.
 
2061
    check_clean
 
2062
        If true, this_dir must have no uncommitted changes before the
 
2063
        merge begins.
 
2064
    ignore_zero - If true, suppress the "zero conflicts" message when 
 
2065
        there are no conflicts; should be set when doing something we expect
 
2066
        to complete perfectly.
 
2067
    file_list - If supplied, merge only changes to selected files.
 
2068
 
 
2069
    All available ancestors of other_revision and base_revision are
 
2070
    automatically pulled into the branch.
 
2071
 
 
2072
    The revno may be -1 to indicate the last revision on the branch, which is
 
2073
    the typical case.
 
2074
 
 
2075
    This function is intended for use from the command line; programmatic
 
2076
    clients might prefer to call merge.merge_inner(), which has less magic 
 
2077
    behavior.
 
2078
    """
 
2079
    from bzrlib.merge import Merger, _MergeConflictHandler
 
2080
    if this_dir is None:
 
2081
        this_dir = u'.'
 
2082
    this_tree = WorkingTree.open_containing(this_dir)[0]
 
2083
    if show_base and not merge_type is ApplyMerge3:
 
2084
        raise BzrCommandError("Show-base is not supported for this merge"
 
2085
                              " type. %s" % merge_type)
 
2086
    if reprocess and not merge_type is ApplyMerge3:
 
2087
        raise BzrCommandError("Reprocess is not supported for this merge"
 
2088
                              " type. %s" % merge_type)
 
2089
    if reprocess and show_base:
 
2090
        raise BzrCommandError("Cannot reprocess and show base.")
 
2091
    merger = Merger(this_tree.branch, this_tree=this_tree)
 
2092
    merger.check_basis(check_clean)
 
2093
    merger.set_other(other_revision)
 
2094
    merger.set_base(base_revision)
 
2095
    if merger.base_rev_id == merger.other_rev_id:
 
2096
        note('Nothing to do.')
 
2097
        return 0
 
2098
    merger.backup_files = backup_files
 
2099
    merger.merge_type = merge_type 
 
2100
    merger.set_interesting_files(file_list)
 
2101
    merger.show_base = show_base 
 
2102
    merger.reprocess = reprocess
 
2103
    merger.conflict_handler = _MergeConflictHandler(merger.this_tree, 
 
2104
                                                    merger.base_tree, 
 
2105
                                                    merger.other_tree,
 
2106
                                                    ignore_zero=ignore_zero)
 
2107
    conflicts = merger.do_merge()
 
2108
    merger.set_pending()
 
2109
    return conflicts
 
2110
 
 
2111
 
2023
2112
# these get imported and then picked up by the scan for cmd_*
2024
2113
# TODO: Some more consistent way to split command definitions across files;
2025
2114
# we do need to load at least some information about them to know of