~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

first cut at merge from integration.

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
149
145
            raise BzrCommandError('You must supply either --revision or a revision_id')
150
146
        b = WorkingTree.open_containing(u'.')[0].branch
151
147
        if revision_id is not None:
152
 
            sys.stdout.write(b.get_revision_xml(revision_id))
 
148
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
153
149
        elif revision is not None:
154
150
            for rev in revision:
155
151
                if rev is None:
156
152
                    raise BzrCommandError('You cannot specify a NULL revision.')
157
153
                revno, rev_id = rev.in_history(b)
158
 
                sys.stdout.write(b.get_revision_xml(rev_id))
 
154
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
159
155
    
160
156
 
161
157
class cmd_revno(Command):
299
295
            if len(revision) > 1:
300
296
                raise BzrCommandError('bzr inventory --revision takes'
301
297
                    ' exactly one revision identifier')
302
 
            inv = tree.branch.get_revision_inventory(
 
298
            inv = tree.branch.repository.get_revision_inventory(
303
299
                revision[0].in_history(tree.branch).rev_id)
304
300
 
305
301
        for path, entry in inv.entries():
400
396
    takes_args = ['location?']
401
397
 
402
398
    def run(self, location=None, remember=False, overwrite=False, verbose=False):
403
 
        from bzrlib.merge import merge
404
399
        from shutil import rmtree
405
400
        import errno
406
401
        # FIXME: too much stuff is in the command class        
552
547
    aliases = ['get', 'clone']
553
548
 
554
549
    def run(self, from_location, to_location=None, revision=None, basis=None):
555
 
        from bzrlib.clone import copy_branch
556
550
        import errno
557
551
        from shutil import rmtree
558
552
        if revision is None:
595
589
                else:
596
590
                    raise
597
591
            try:
598
 
                copy_branch(br_from, to_location, revision_id, basis_branch)
 
592
                br_from.clone(to_location, revision_id, basis_branch)
599
593
            except bzrlib.errors.NoSuchRevision:
600
594
                rmtree(to_location)
601
595
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
606
600
                raise BzrCommandError(msg)
607
601
            branch = Branch.open(to_location)
608
602
            if name:
609
 
                name = StringIO(name)
610
 
                branch.put_controlfile('branch-name', name)
 
603
                branch.control_files.put_utf8('branch-name', name)
 
604
 
611
605
            note('Branched %d revision(s).' % branch.revno())
612
606
        finally:
613
607
            br_from.unlock()
862
856
            if file_id in basis_inv:
863
857
                continue
864
858
            path = inv.id2path(file_id)
865
 
            if not os.access(b.abspath(path), os.F_OK):
 
859
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
866
860
                continue
867
861
            print path
868
862
                
931
925
            if tree is None:
932
926
                b, fp = Branch.open_containing(filename)
933
927
                if fp != '':
934
 
                    inv = b.get_inventory(b.last_revision())
 
928
                    inv = b.repository.get_inventory(b.last_revision())
935
929
            if fp != '':
936
930
                file_id = inv.path2id(fp)
937
931
            else:
1040
1034
        elif relpath:
1041
1035
            relpath += '/'
1042
1036
        if revision is not None:
1043
 
            tree = tree.branch.revision_tree(
 
1037
            tree = tree.branch.repository.revision_tree(
1044
1038
                revision[0].in_history(tree.branch).rev_id)
1045
1039
        for fp, fc, kind, fid, entry in tree.list_files():
1046
1040
            if fp.startswith(relpath):
1198
1192
            if len(revision) != 1:
1199
1193
                raise BzrError('bzr export --revision takes exactly 1 argument')
1200
1194
            rev_id = revision[0].in_history(b).rev_id
1201
 
        t = b.revision_tree(rev_id)
 
1195
        t = b.repository.revision_tree(rev_id)
1202
1196
        try:
1203
1197
            export(t, dest, format, root)
1204
1198
        except errors.NoSuchExportFormat, e:
1606
1600
 
1607
1601
    def run(self, branch=None, revision=None, force=False, merge_type=None,
1608
1602
            show_base=False, reprocess=False):
1609
 
        from bzrlib.merge import merge
1610
 
        from bzrlib.merge_core import ApplyMerge3
 
1603
        from bzrlib._merge_core import ApplyMerge3
1611
1604
        if merge_type is None:
1612
1605
            merge_type = ApplyMerge3
1613
1606
        if branch is None:
1664
1657
    def run(self, file_list=None, merge_type=None, show_base=False,
1665
1658
            reprocess=False):
1666
1659
        from bzrlib.merge import merge_inner, transform_tree
1667
 
        from bzrlib.merge_core import ApplyMerge3
 
1660
        from bzrlib._merge_core import ApplyMerge3
1668
1661
        if merge_type is None:
1669
1662
            merge_type = ApplyMerge3
1670
1663
        tree, file_list = tree_files(file_list)
1675
1668
                raise BzrCommandError("Sorry, remerge only works after normal"
1676
1669
                                      + " merges.  Not cherrypicking or"
1677
1670
                                      + "multi-merges.")
 
1671
            repository = tree.branch.repository
1678
1672
            base_revision = common_ancestor(tree.branch.last_revision(), 
1679
 
                                            pending_merges[0], tree.branch)
1680
 
            base_tree = tree.branch.revision_tree(base_revision)
1681
 
            other_tree = tree.branch.revision_tree(pending_merges[0])
 
1673
                                            pending_merges[0], repository)
 
1674
            base_tree = repository.revision_tree(base_revision)
 
1675
            other_tree = repository.revision_tree(pending_merges[0])
1682
1676
            interesting_ids = None
1683
1677
            if file_list is not None:
1684
1678
                interesting_ids = set()
1725
1719
    aliases = ['merge-revert']
1726
1720
 
1727
1721
    def run(self, revision=None, no_backup=False, file_list=None):
1728
 
        from bzrlib.merge import merge_inner
1729
1722
        from bzrlib.commands import parse_spec
1730
1723
        if file_list is not None:
1731
1724
            if len(file_list) == 0:
1732
1725
                raise BzrCommandError("No files specified")
1733
1726
        else:
1734
1727
            file_list = []
 
1728
        
 
1729
        tree, file_list = tree_files(file_list)
1735
1730
        if revision is None:
1736
 
            revno = -1
1737
 
            tree = WorkingTree.open_containing(u'.')[0]
1738
1731
            # FIXME should be tree.last_revision
1739
1732
            rev_id = tree.branch.last_revision()
1740
1733
        elif len(revision) != 1:
1741
1734
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1742
1735
        else:
1743
 
            tree, file_list = tree_files(file_list)
1744
1736
            rev_id = revision[0].in_history(tree.branch).rev_id
1745
 
        tree.revert(file_list, tree.branch.revision_tree(rev_id),
1746
 
                                not no_backup)
 
1737
        tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
 
1738
                    not no_backup)
1747
1739
 
1748
1740
 
1749
1741
class cmd_assert_fail(Command):
1794
1786
        from bzrlib.branch import Branch
1795
1787
        from_b = Branch.open(from_branch)
1796
1788
        to_b = Branch.open(to_branch)
1797
 
        from_b.lock_read()
1798
 
        try:
1799
 
            to_b.lock_write()
1800
 
            try:
1801
 
                Fetcher(to_b, from_b)
1802
 
            finally:
1803
 
                to_b.unlock()
1804
 
        finally:
1805
 
            from_b.unlock()
 
1789
        Fetcher(to_b, from_b)
1806
1790
 
1807
1791
 
1808
1792
class cmd_missing(Command):
1845
1829
            remote_extra.reverse()
1846
1830
        if local_extra and not theirs_only:
1847
1831
            print "You have %d extra revision(s):" % len(local_extra)
1848
 
            for data in iter_log_data(local_extra, local_branch, verbose):
 
1832
            for data in iter_log_data(local_extra, local_branch.repository,
 
1833
                                      verbose):
1849
1834
                lf.show(*data)
1850
1835
            printed_local = True
1851
1836
        else:
1854
1839
            if printed_local is True:
1855
1840
                print "\n\n"
1856
1841
            print "You are missing %d revision(s):" % len(remote_extra)
1857
 
            for data in iter_log_data(remote_extra, remote_branch, verbose):
 
1842
            for data in iter_log_data(remote_extra, remote_branch.repository, 
 
1843
                                      verbose):
1858
1844
                lf.show(*data)
1859
1845
        if not remote_extra and not local_extra:
1860
1846
            status_code = 0
1900
1886
                rev_id = b.last_revision()
1901
1887
            else:
1902
1888
                rev_id = revision[0].in_history(b).rev_id
1903
 
            t = Testament.from_revision(b, rev_id)
 
1889
            t = Testament.from_revision(b.repository, rev_id)
1904
1890
            if long:
1905
1891
                sys.stdout.writelines(t.as_text_lines())
1906
1892
            else:
1936
1922
        branch.lock_read()
1937
1923
        try:
1938
1924
            file_id = tree.inventory.path2id(relpath)
1939
 
            tree = branch.revision_tree(branch.last_revision())
 
1925
            tree = branch.repository.revision_tree(branch.last_revision())
1940
1926
            file_version = tree.inventory[file_id].revision
1941
1927
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1942
1928
        finally:
1961
1947
        b = WorkingTree.open_containing(u'.')[0].branch
1962
1948
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1963
1949
        if revision_id is not None:
1964
 
            b.sign_revision(revision_id, gpg_strategy)
 
1950
            b.repository.sign_revision(revision_id, gpg_strategy)
1965
1951
        elif revision is not None:
1966
1952
            if len(revision) == 1:
1967
1953
                revno, rev_id = revision[0].in_history(b)
1968
 
                b.sign_revision(rev_id, gpg_strategy)
 
1954
                b.repository.sign_revision(rev_id, gpg_strategy)
1969
1955
            elif len(revision) == 2:
1970
1956
                # are they both on rh- if so we can walk between them
1971
1957
                # might be nice to have a range helper for arbitrary
1977
1963
                if from_revno is None or to_revno is None:
1978
1964
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
1979
1965
                for revno in range(from_revno, to_revno + 1):
1980
 
                    b.sign_revision(b.get_rev_id(revno), gpg_strategy)
 
1966
                    b.repository.sign_revision(b.get_rev_id(revno), 
 
1967
                                               gpg_strategy)
1981
1968
            else:
1982
1969
                raise BzrCommandError('Please supply either one revision, or a range.')
1983
1970
 
2030
2017
        for r in range(revno, b.revno()+1):
2031
2018
            rev_id = b.get_rev_id(r)
2032
2019
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2033
 
            lf.show(r, b.get_revision(rev_id), None)
 
2020
            lf.show(r, b.repository.get_revision(rev_id), None)
2034
2021
 
2035
2022
        if dry_run:
2036
2023
            print 'Dry-run, pretending to remove the above revisions.'
2048
2035
                revno=revno)
2049
2036
 
2050
2037
 
 
2038
def merge(other_revision, base_revision,
 
2039
          check_clean=True, ignore_zero=False,
 
2040
          this_dir=None, backup_files=False, merge_type=ApplyMerge3,
 
2041
          file_list=None, show_base=False, reprocess=False):
 
2042
    """Merge changes into a tree.
 
2043
 
 
2044
    base_revision
 
2045
        list(path, revno) Base for three-way merge.  
 
2046
        If [None, None] then a base will be automatically determined.
 
2047
    other_revision
 
2048
        list(path, revno) Other revision for three-way merge.
 
2049
    this_dir
 
2050
        Directory to merge changes into; '.' by default.
 
2051
    check_clean
 
2052
        If true, this_dir must have no uncommitted changes before the
 
2053
        merge begins.
 
2054
    ignore_zero - If true, suppress the "zero conflicts" message when 
 
2055
        there are no conflicts; should be set when doing something we expect
 
2056
        to complete perfectly.
 
2057
    file_list - If supplied, merge only changes to selected files.
 
2058
 
 
2059
    All available ancestors of other_revision and base_revision are
 
2060
    automatically pulled into the branch.
 
2061
 
 
2062
    The revno may be -1 to indicate the last revision on the branch, which is
 
2063
    the typical case.
 
2064
 
 
2065
    This function is intended for use from the command line; programmatic
 
2066
    clients might prefer to call merge.merge_inner(), which has less magic 
 
2067
    behavior.
 
2068
    """
 
2069
    from bzrlib.merge import Merger, _MergeConflictHandler
 
2070
    if this_dir is None:
 
2071
        this_dir = u'.'
 
2072
    this_tree = WorkingTree.open_containing(this_dir)[0]
 
2073
    if show_base and not merge_type is ApplyMerge3:
 
2074
        raise BzrCommandError("Show-base is not supported for this merge"
 
2075
                              " type. %s" % merge_type)
 
2076
    if reprocess and not merge_type is ApplyMerge3:
 
2077
        raise BzrCommandError("Reprocess is not supported for this merge"
 
2078
                              " type. %s" % merge_type)
 
2079
    if reprocess and show_base:
 
2080
        raise BzrCommandError("Cannot reprocess and show base.")
 
2081
    merger = Merger(this_tree.branch, this_tree=this_tree)
 
2082
    merger.check_basis(check_clean)
 
2083
    merger.set_other(other_revision)
 
2084
    merger.set_base(base_revision)
 
2085
    if merger.base_rev_id == merger.other_rev_id:
 
2086
        note('Nothing to do.')
 
2087
        return 0
 
2088
    merger.backup_files = backup_files
 
2089
    merger.merge_type = merge_type 
 
2090
    merger.set_interesting_files(file_list)
 
2091
    merger.show_base = show_base 
 
2092
    merger.reprocess = reprocess
 
2093
    merger.conflict_handler = _MergeConflictHandler(merger.this_tree, 
 
2094
                                                    merger.base_tree, 
 
2095
                                                    merger.other_tree,
 
2096
                                                    ignore_zero=ignore_zero)
 
2097
    conflicts = merger.do_merge()
 
2098
    merger.set_pending()
 
2099
    return conflicts
 
2100
 
 
2101
 
2051
2102
# these get imported and then picked up by the scan for cmd_*
2052
2103
# TODO: Some more consistent way to split command definitions across files;
2053
2104
# we do need to load at least some information about them to know of