~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Andrew Bennetts
  • Date: 2011-02-14 12:03:05 UTC
  • mto: This revision was merged to the branch mainline in revision 5664.
  • Revision ID: andrew.bennetts@canonical.com-20110214120305-7l7iu1h6f13voeo7
Add release note.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
        bzrdir,
26
26
        cache_utf8,
27
27
        config as _mod_config,
 
28
        controldir,
28
29
        debug,
29
30
        errors,
30
31
        fetch,
42
43
        urlutils,
43
44
        )
44
45
from bzrlib.config import BranchConfig, TransportConfig
 
46
from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5RichRoot
45
47
from bzrlib.tag import (
46
48
    BasicTags,
47
49
    DisabledTags,
48
50
    )
49
51
""")
50
52
 
51
 
from bzrlib import (
52
 
    controldir,
53
 
    )
54
 
from bzrlib.decorators import (
55
 
    needs_read_lock,
56
 
    needs_write_lock,
57
 
    only_raises,
58
 
    )
59
 
from bzrlib.hooks import Hooks
 
53
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
 
54
from bzrlib.hooks import HookPoint, Hooks
60
55
from bzrlib.inter import InterObject
61
56
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
62
57
from bzrlib import registry
78
73
    :ivar base:
79
74
        Base directory/url of the branch; using control_url and
80
75
        control_transport is more standardized.
81
 
    :ivar hooks: An instance of BranchHooks.
82
 
    :ivar _master_branch_cache: cached result of get_master_branch, see
83
 
        _clear_cached_state.
 
76
 
 
77
    hooks: An instance of BranchHooks.
84
78
    """
85
79
    # this is really an instance variable - FIXME move it there
86
80
    # - RBC 20060112
102
96
        self._partial_revision_history_cache = []
103
97
        self._tags_bytes = None
104
98
        self._last_revision_info_cache = None
105
 
        self._master_branch_cache = None
106
99
        self._merge_sorted_revisions_cache = None
107
100
        self._open_hook()
108
101
        hooks = Branch.hooks['open']
669
662
        raise errors.UnsupportedOperation(self.get_reference_info, self)
670
663
 
671
664
    @needs_write_lock
672
 
    def fetch(self, from_branch, last_revision=None, fetch_spec=None):
 
665
    def fetch(self, from_branch, last_revision=None, pb=None, fetch_spec=None):
673
666
        """Copy revisions from from_branch into this branch.
674
667
 
675
668
        :param from_branch: Where to copy from.
676
669
        :param last_revision: What revision to stop at (None for at the end
677
670
                              of the branch.
 
671
        :param pb: An optional progress bar to use.
678
672
        :param fetch_spec: If specified, a SearchResult or
679
673
            PendingAncestryResult that describes which revisions to copy.  This
680
674
            allows copying multiple heads at once.  Mutually exclusive with
681
675
            last_revision.
682
676
        :return: None
683
677
        """
684
 
        return InterBranch.get(from_branch, self).fetch(last_revision,
685
 
            fetch_spec)
 
678
        if fetch_spec is not None and last_revision is not None:
 
679
            raise AssertionError(
 
680
                "fetch_spec and last_revision are mutually exclusive.")
 
681
        if self.base == from_branch.base:
 
682
            return (0, [])
 
683
        if pb is not None:
 
684
            symbol_versioning.warn(
 
685
                symbol_versioning.deprecated_in((1, 14, 0))
 
686
                % "pb parameter to fetch()")
 
687
        from_branch.lock_read()
 
688
        try:
 
689
            if last_revision is None and fetch_spec is None:
 
690
                last_revision = from_branch.last_revision()
 
691
                last_revision = _mod_revision.ensure_null(last_revision)
 
692
            return self.repository.fetch(from_branch.repository,
 
693
                                         revision_id=last_revision,
 
694
                                         pb=pb, fetch_spec=fetch_spec)
 
695
        finally:
 
696
            from_branch.unlock()
686
697
 
687
698
    def get_bound_location(self):
688
699
        """Return the URL of the branch we are bound to.
799
810
 
800
811
    def _unstack(self):
801
812
        """Change a branch to be unstacked, copying data as needed.
802
 
 
 
813
        
803
814
        Don't call this directly, use set_stacked_on_url(None).
804
815
        """
805
816
        pb = ui.ui_factory.nested_progress_bar()
925
936
        self._revision_history_cache = None
926
937
        self._revision_id_to_revno_cache = None
927
938
        self._last_revision_info_cache = None
928
 
        self._master_branch_cache = None
929
939
        self._merge_sorted_revisions_cache = None
930
940
        self._partial_revision_history_cache = []
931
941
        self._partial_revision_id_to_revno_cache = {}
996
1006
        else:
997
1007
            return (0, _mod_revision.NULL_REVISION)
998
1008
 
 
1009
    @deprecated_method(deprecated_in((1, 6, 0)))
 
1010
    def missing_revisions(self, other, stop_revision=None):
 
1011
        """Return a list of new revisions that would perfectly fit.
 
1012
 
 
1013
        If self and other have not diverged, return a list of the revisions
 
1014
        present in other, but missing from self.
 
1015
        """
 
1016
        self_history = self.revision_history()
 
1017
        self_len = len(self_history)
 
1018
        other_history = other.revision_history()
 
1019
        other_len = len(other_history)
 
1020
        common_index = min(self_len, other_len) -1
 
1021
        if common_index >= 0 and \
 
1022
            self_history[common_index] != other_history[common_index]:
 
1023
            raise errors.DivergedBranches(self, other)
 
1024
 
 
1025
        if stop_revision is None:
 
1026
            stop_revision = other_len
 
1027
        else:
 
1028
            if stop_revision > other_len:
 
1029
                raise errors.NoSuchRevision(self, stop_revision)
 
1030
        return other_history[self_len:stop_revision]
 
1031
 
999
1032
    def update_revisions(self, other, stop_revision=None, overwrite=False,
1000
1033
                         graph=None, fetch_tags=True):
1001
1034
        """Pull in new perfect-fit revisions.
1526
1559
        else:
1527
1560
            raise AssertionError("invalid heads: %r" % (heads,))
1528
1561
 
1529
 
    def heads_to_fetch(self):
1530
 
        """Return the heads that must and that should be fetched to copy this
1531
 
        branch into another repo.
1532
 
 
1533
 
        :returns: a 2-tuple of (must_fetch, if_present_fetch).  must_fetch is a
1534
 
            set of heads that must be fetched.  if_present_fetch is a set of
1535
 
            heads that must be fetched if present, but no error is necessary if
1536
 
            they are not present.
1537
 
        """
1538
 
        # For bzr native formats must_fetch is just the tip, and if_present_fetch
1539
 
        # are the tags.
1540
 
        must_fetch = set([self.last_revision()])
1541
 
        try:
1542
 
            if_present_fetch = set(self.tags.get_reverse_tag_dict())
1543
 
        except errors.TagsNotSupported:
1544
 
            if_present_fetch = set()
1545
 
        must_fetch.discard(_mod_revision.NULL_REVISION)
1546
 
        if_present_fetch.discard(_mod_revision.NULL_REVISION)
1547
 
        return must_fetch, if_present_fetch
1548
 
 
1549
 
 
1550
 
class BranchFormat(controldir.ControlComponentFormat):
 
1562
 
 
1563
class BranchFormat(object):
1551
1564
    """An encapsulation of the initialization and open routines for a format.
1552
1565
 
1553
1566
    Formats provide three things:
1565
1578
    object will be created every time regardless.
1566
1579
    """
1567
1580
 
 
1581
    _default_format = None
 
1582
    """The default format used for new branches."""
 
1583
 
 
1584
    _formats = {}
 
1585
    """The known formats."""
 
1586
 
 
1587
    _extra_formats = []
 
1588
    """Extra formats that can not be part of a metadir."""
 
1589
 
1568
1590
    can_set_append_revisions_only = True
1569
1591
 
1570
1592
    def __eq__(self, other):
1579
1601
        try:
1580
1602
            transport = a_bzrdir.get_branch_transport(None, name=name)
1581
1603
            format_string = transport.get_bytes("format")
1582
 
            return format_registry.get(format_string)
 
1604
            format = klass._formats[format_string]
 
1605
            if isinstance(format, MetaDirBranchFormatFactory):
 
1606
                return format()
 
1607
            return format
1583
1608
        except errors.NoSuchFile:
1584
1609
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1585
1610
        except KeyError:
1586
1611
            raise errors.UnknownFormatError(format=format_string, kind='branch')
1587
1612
 
1588
1613
    @classmethod
1589
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1590
1614
    def get_default_format(klass):
1591
1615
        """Return the current default format."""
1592
 
        return format_registry.get_default()
 
1616
        return klass._default_format
1593
1617
 
1594
1618
    @classmethod
1595
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1596
1619
    def get_formats(klass):
1597
1620
        """Get all the known formats.
1598
1621
 
1599
1622
        Warning: This triggers a load of all lazy registered formats: do not
1600
1623
        use except when that is desireed.
1601
1624
        """
1602
 
        return format_registry._get_all()
 
1625
        result = []
 
1626
        for fmt in klass._formats.values():
 
1627
            if isinstance(fmt, MetaDirBranchFormatFactory):
 
1628
                fmt = fmt()
 
1629
            result.append(fmt)
 
1630
        return result + klass._extra_formats
1603
1631
 
1604
1632
    def get_reference(self, a_bzrdir, name=None):
1605
1633
        """Get the target reference of the branch in a_bzrdir.
1644
1672
        for hook in hooks:
1645
1673
            hook(params)
1646
1674
 
 
1675
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
 
1676
                           repository=None, lock_type='metadir',
 
1677
                           set_format=True):
 
1678
        """Initialize a branch in a bzrdir, with specified files
 
1679
 
 
1680
        :param a_bzrdir: The bzrdir to initialize the branch in
 
1681
        :param utf8_files: The files to create as a list of
 
1682
            (filename, content) tuples
 
1683
        :param name: Name of colocated branch to create, if any
 
1684
        :param set_format: If True, set the format with
 
1685
            self.get_format_string.  (BzrBranch4 has its format set
 
1686
            elsewhere)
 
1687
        :return: a branch in this format
 
1688
        """
 
1689
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
 
1690
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
 
1691
        lock_map = {
 
1692
            'metadir': ('lock', lockdir.LockDir),
 
1693
            'branch4': ('branch-lock', lockable_files.TransportLock),
 
1694
        }
 
1695
        lock_name, lock_class = lock_map[lock_type]
 
1696
        control_files = lockable_files.LockableFiles(branch_transport,
 
1697
            lock_name, lock_class)
 
1698
        control_files.create_lock()
 
1699
        try:
 
1700
            control_files.lock_write()
 
1701
        except errors.LockContention:
 
1702
            if lock_type != 'branch4':
 
1703
                raise
 
1704
            lock_taken = False
 
1705
        else:
 
1706
            lock_taken = True
 
1707
        if set_format:
 
1708
            utf8_files += [('format', self.get_format_string())]
 
1709
        try:
 
1710
            for (filename, content) in utf8_files:
 
1711
                branch_transport.put_bytes(
 
1712
                    filename, content,
 
1713
                    mode=a_bzrdir._get_file_mode())
 
1714
        finally:
 
1715
            if lock_taken:
 
1716
                control_files.unlock()
 
1717
        branch = self.open(a_bzrdir, name, _found=True,
 
1718
                found_repository=repository)
 
1719
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
 
1720
        return branch
 
1721
 
1647
1722
    def initialize(self, a_bzrdir, name=None, repository=None):
1648
1723
        """Create a branch of this format in a_bzrdir.
1649
1724
        
1698
1773
        raise NotImplementedError(self.open)
1699
1774
 
1700
1775
    @classmethod
1701
 
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1776
    def register_extra_format(klass, format):
 
1777
        """Register a branch format that can not be part of a metadir.
 
1778
 
 
1779
        This is mainly useful to allow custom branch formats, such as
 
1780
        older Bazaar formats and foreign formats, to be tested
 
1781
        """
 
1782
        klass._extra_formats.append(format)
 
1783
        network_format_registry.register(
 
1784
            format.network_name(), format.__class__)
 
1785
 
 
1786
    @classmethod
1702
1787
    def register_format(klass, format):
1703
1788
        """Register a metadir format.
1704
 
 
 
1789
        
1705
1790
        See MetaDirBranchFormatFactory for the ability to register a format
1706
1791
        without loading the code the format needs until it is actually used.
1707
1792
        """
1708
 
        format_registry.register(format)
 
1793
        klass._formats[format.get_format_string()] = format
 
1794
        # Metadir formats have a network name of their format string, and get
 
1795
        # registered as factories.
 
1796
        if isinstance(format, MetaDirBranchFormatFactory):
 
1797
            network_format_registry.register(format.get_format_string(), format)
 
1798
        else:
 
1799
            network_format_registry.register(format.get_format_string(),
 
1800
                format.__class__)
1709
1801
 
1710
1802
    @classmethod
1711
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1712
1803
    def set_default_format(klass, format):
1713
 
        format_registry.set_default(format)
 
1804
        klass._default_format = format
1714
1805
 
1715
1806
    def supports_set_append_revisions_only(self):
1716
1807
        """True if this format supports set_append_revisions_only."""
1720
1811
        """True if this format records a stacked-on branch."""
1721
1812
        return False
1722
1813
 
1723
 
    def supports_leaving_lock(self):
1724
 
        """True if this format supports leaving locks in place."""
1725
 
        return False # by default
1726
 
 
1727
1814
    @classmethod
1728
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1729
1815
    def unregister_format(klass, format):
1730
 
        format_registry.remove(format)
 
1816
        del klass._formats[format.get_format_string()]
 
1817
 
 
1818
    @classmethod
 
1819
    def unregister_extra_format(klass, format):
 
1820
        klass._extra_formats.remove(format)
1731
1821
 
1732
1822
    def __str__(self):
1733
1823
        return self.get_format_description().rstrip()
1778
1868
        These are all empty initially, because by default nothing should get
1779
1869
        notified.
1780
1870
        """
1781
 
        Hooks.__init__(self, "bzrlib.branch", "Branch.hooks")
1782
 
        self.add_hook('set_rh',
 
1871
        Hooks.__init__(self)
 
1872
        self.create_hook(HookPoint('set_rh',
1783
1873
            "Invoked whenever the revision history has been set via "
1784
1874
            "set_revision_history. The api signature is (branch, "
1785
1875
            "revision_history), and the branch will be write-locked. "
1786
1876
            "The set_rh hook can be expensive for bzr to trigger, a better "
1787
 
            "hook to use is Branch.post_change_branch_tip.", (0, 15))
1788
 
        self.add_hook('open',
 
1877
            "hook to use is Branch.post_change_branch_tip.", (0, 15), None))
 
1878
        self.create_hook(HookPoint('open',
1789
1879
            "Called with the Branch object that has been opened after a "
1790
 
            "branch is opened.", (1, 8))
1791
 
        self.add_hook('post_push',
 
1880
            "branch is opened.", (1, 8), None))
 
1881
        self.create_hook(HookPoint('post_push',
1792
1882
            "Called after a push operation completes. post_push is called "
1793
1883
            "with a bzrlib.branch.BranchPushResult object and only runs in the "
1794
 
            "bzr client.", (0, 15))
1795
 
        self.add_hook('post_pull',
 
1884
            "bzr client.", (0, 15), None))
 
1885
        self.create_hook(HookPoint('post_pull',
1796
1886
            "Called after a pull operation completes. post_pull is called "
1797
1887
            "with a bzrlib.branch.PullResult object and only runs in the "
1798
 
            "bzr client.", (0, 15))
1799
 
        self.add_hook('pre_commit',
 
1888
            "bzr client.", (0, 15), None))
 
1889
        self.create_hook(HookPoint('pre_commit',
1800
1890
            "Called after a commit is calculated but before it is "
1801
1891
            "completed. pre_commit is called with (local, master, old_revno, "
1802
1892
            "old_revid, future_revno, future_revid, tree_delta, future_tree"
1805
1895
            "basis revision. hooks MUST NOT modify this delta. "
1806
1896
            " future_tree is an in-memory tree obtained from "
1807
1897
            "CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1808
 
            "tree.", (0,91))
1809
 
        self.add_hook('post_commit',
 
1898
            "tree.", (0,91), None))
 
1899
        self.create_hook(HookPoint('post_commit',
1810
1900
            "Called in the bzr client after a commit has completed. "
1811
1901
            "post_commit is called with (local, master, old_revno, old_revid, "
1812
1902
            "new_revno, new_revid). old_revid is NULL_REVISION for the first "
1813
 
            "commit to a branch.", (0, 15))
1814
 
        self.add_hook('post_uncommit',
 
1903
            "commit to a branch.", (0, 15), None))
 
1904
        self.create_hook(HookPoint('post_uncommit',
1815
1905
            "Called in the bzr client after an uncommit completes. "
1816
1906
            "post_uncommit is called with (local, master, old_revno, "
1817
1907
            "old_revid, new_revno, new_revid) where local is the local branch "
1818
1908
            "or None, master is the target branch, and an empty branch "
1819
 
            "receives new_revno of 0, new_revid of None.", (0, 15))
1820
 
        self.add_hook('pre_change_branch_tip',
 
1909
            "receives new_revno of 0, new_revid of None.", (0, 15), None))
 
1910
        self.create_hook(HookPoint('pre_change_branch_tip',
1821
1911
            "Called in bzr client and server before a change to the tip of a "
1822
1912
            "branch is made. pre_change_branch_tip is called with a "
1823
1913
            "bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1824
 
            "commit, uncommit will all trigger this hook.", (1, 6))
1825
 
        self.add_hook('post_change_branch_tip',
 
1914
            "commit, uncommit will all trigger this hook.", (1, 6), None))
 
1915
        self.create_hook(HookPoint('post_change_branch_tip',
1826
1916
            "Called in bzr client and server after a change to the tip of a "
1827
1917
            "branch is made. post_change_branch_tip is called with a "
1828
1918
            "bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1829
 
            "commit, uncommit will all trigger this hook.", (1, 4))
1830
 
        self.add_hook('transform_fallback_location',
 
1919
            "commit, uncommit will all trigger this hook.", (1, 4), None))
 
1920
        self.create_hook(HookPoint('transform_fallback_location',
1831
1921
            "Called when a stacked branch is activating its fallback "
1832
1922
            "locations. transform_fallback_location is called with (branch, "
1833
1923
            "url), and should return a new url. Returning the same url "
1838
1928
            "fallback locations have not been activated. When there are "
1839
1929
            "multiple hooks installed for transform_fallback_location, "
1840
1930
            "all are called with the url returned from the previous hook."
1841
 
            "The order is however undefined.", (1, 9))
1842
 
        self.add_hook('automatic_tag_name',
 
1931
            "The order is however undefined.", (1, 9), None))
 
1932
        self.create_hook(HookPoint('automatic_tag_name',
1843
1933
            "Called to determine an automatic tag name for a revision. "
1844
1934
            "automatic_tag_name is called with (branch, revision_id) and "
1845
1935
            "should return a tag name or None if no tag name could be "
1846
1936
            "determined. The first non-None tag name returned will be used.",
1847
 
            (2, 2))
1848
 
        self.add_hook('post_branch_init',
 
1937
            (2, 2), None))
 
1938
        self.create_hook(HookPoint('post_branch_init',
1849
1939
            "Called after new branch initialization completes. "
1850
1940
            "post_branch_init is called with a "
1851
1941
            "bzrlib.branch.BranchInitHookParams. "
1852
1942
            "Note that init, branch and checkout (both heavyweight and "
1853
 
            "lightweight) will all trigger this hook.", (2, 2))
1854
 
        self.add_hook('post_switch',
 
1943
            "lightweight) will all trigger this hook.", (2, 2), None))
 
1944
        self.create_hook(HookPoint('post_switch',
1855
1945
            "Called after a checkout switches branch. "
1856
1946
            "post_switch is called with a "
1857
 
            "bzrlib.branch.SwitchHookParams.", (2, 2))
 
1947
            "bzrlib.branch.SwitchHookParams.", (2, 2), None))
1858
1948
 
1859
1949
 
1860
1950
 
1973
2063
            self.revision_id)
1974
2064
 
1975
2065
 
 
2066
class BzrBranchFormat4(BranchFormat):
 
2067
    """Bzr branch format 4.
 
2068
 
 
2069
    This format has:
 
2070
     - a revision-history file.
 
2071
     - a branch-lock lock file [ to be shared with the bzrdir ]
 
2072
    """
 
2073
 
 
2074
    def get_format_description(self):
 
2075
        """See BranchFormat.get_format_description()."""
 
2076
        return "Branch format 4"
 
2077
 
 
2078
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2079
        """Create a branch of this format in a_bzrdir."""
 
2080
        if repository is not None:
 
2081
            raise NotImplementedError(
 
2082
                "initialize(repository=<not None>) on %r" % (self,))
 
2083
        utf8_files = [('revision-history', ''),
 
2084
                      ('branch-name', ''),
 
2085
                      ]
 
2086
        return self._initialize_helper(a_bzrdir, utf8_files, name=name,
 
2087
                                       lock_type='branch4', set_format=False)
 
2088
 
 
2089
    def __init__(self):
 
2090
        super(BzrBranchFormat4, self).__init__()
 
2091
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
 
2092
 
 
2093
    def network_name(self):
 
2094
        """The network name for this format is the control dirs disk label."""
 
2095
        return self._matchingbzrdir.get_format_string()
 
2096
 
 
2097
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
2098
            found_repository=None):
 
2099
        """See BranchFormat.open()."""
 
2100
        if not _found:
 
2101
            # we are being called directly and must probe.
 
2102
            raise NotImplementedError
 
2103
        if found_repository is None:
 
2104
            found_repository = a_bzrdir.open_repository()
 
2105
        return BzrBranchPreSplitOut(_format=self,
 
2106
                         _control_files=a_bzrdir._control_files,
 
2107
                         a_bzrdir=a_bzrdir,
 
2108
                         name=name,
 
2109
                         _repository=found_repository)
 
2110
 
 
2111
    def __str__(self):
 
2112
        return "Bazaar-NG branch format 4"
 
2113
 
 
2114
 
1976
2115
class BranchFormatMetadir(BranchFormat):
1977
2116
    """Common logic for meta-dir based branch formats."""
1978
2117
 
1980
2119
        """What class to instantiate on open calls."""
1981
2120
        raise NotImplementedError(self._branch_class)
1982
2121
 
1983
 
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1984
 
                           repository=None):
1985
 
        """Initialize a branch in a bzrdir, with specified files
1986
 
 
1987
 
        :param a_bzrdir: The bzrdir to initialize the branch in
1988
 
        :param utf8_files: The files to create as a list of
1989
 
            (filename, content) tuples
1990
 
        :param name: Name of colocated branch to create, if any
1991
 
        :return: a branch in this format
1992
 
        """
1993
 
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1994
 
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1995
 
        control_files = lockable_files.LockableFiles(branch_transport,
1996
 
            'lock', lockdir.LockDir)
1997
 
        control_files.create_lock()
1998
 
        control_files.lock_write()
1999
 
        try:
2000
 
            utf8_files += [('format', self.get_format_string())]
2001
 
            for (filename, content) in utf8_files:
2002
 
                branch_transport.put_bytes(
2003
 
                    filename, content,
2004
 
                    mode=a_bzrdir._get_file_mode())
2005
 
        finally:
2006
 
            control_files.unlock()
2007
 
        branch = self.open(a_bzrdir, name, _found=True,
2008
 
                found_repository=repository)
2009
 
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2010
 
        return branch
2011
 
 
2012
2122
    def network_name(self):
2013
2123
        """A simple byte string uniquely identifying this format for RPC calls.
2014
2124
 
2047
2157
    def supports_tags(self):
2048
2158
        return True
2049
2159
 
2050
 
    def supports_leaving_lock(self):
2051
 
        return True
2052
 
 
2053
2160
 
2054
2161
class BzrBranchFormat5(BranchFormatMetadir):
2055
2162
    """Bzr branch format 5.
2147
2254
                      ]
2148
2255
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2149
2256
 
 
2257
    def __init__(self):
 
2258
        super(BzrBranchFormat8, self).__init__()
 
2259
        self._matchingbzrdir.repository_format = \
 
2260
            RepositoryFormatKnitPack5RichRoot()
 
2261
 
2150
2262
    def make_tags(self, branch):
2151
2263
        """See bzrlib.branch.BranchFormat.make_tags()."""
2152
2264
        return BasicTags(branch)
2160
2272
    supports_reference_locations = True
2161
2273
 
2162
2274
 
2163
 
class BzrBranchFormat7(BranchFormatMetadir):
 
2275
class BzrBranchFormat7(BzrBranchFormat8):
2164
2276
    """Branch format with last-revision, tags, and a stacked location pointer.
2165
2277
 
2166
2278
    The stacked location pointer is passed down to the repository and requires
2191
2303
    def supports_set_append_revisions_only(self):
2192
2304
        return True
2193
2305
 
2194
 
    def supports_stacking(self):
2195
 
        return True
2196
 
 
2197
 
    def make_tags(self, branch):
2198
 
        """See bzrlib.branch.BranchFormat.make_tags()."""
2199
 
        return BasicTags(branch)
2200
 
 
2201
2306
    supports_reference_locations = False
2202
2307
 
2203
2308
 
2303
2408
        return result
2304
2409
 
2305
2410
 
2306
 
class BranchFormatRegistry(controldir.ControlComponentFormatRegistry):
2307
 
    """Branch format registry."""
2308
 
 
2309
 
    def __init__(self, other_registry=None):
2310
 
        super(BranchFormatRegistry, self).__init__(other_registry)
2311
 
        self._default_format = None
2312
 
 
2313
 
    def set_default(self, format):
2314
 
        self._default_format = format
2315
 
 
2316
 
    def get_default(self):
2317
 
        return self._default_format
2318
 
 
2319
 
 
2320
2411
network_format_registry = registry.FormatRegistry()
2321
2412
"""Registry of formats indexed by their network name.
2322
2413
 
2325
2416
BranchFormat.network_name() for more detail.
2326
2417
"""
2327
2418
 
2328
 
format_registry = BranchFormatRegistry(network_format_registry)
2329
 
 
2330
2419
 
2331
2420
# formats which have no format string are not discoverable
2332
2421
# and not independently creatable, so are not registered.
2334
2423
__format6 = BzrBranchFormat6()
2335
2424
__format7 = BzrBranchFormat7()
2336
2425
__format8 = BzrBranchFormat8()
2337
 
format_registry.register(__format5)
2338
 
format_registry.register(BranchReferenceFormat())
2339
 
format_registry.register(__format6)
2340
 
format_registry.register(__format7)
2341
 
format_registry.register(__format8)
2342
 
format_registry.set_default(__format7)
 
2426
BranchFormat.register_format(__format5)
 
2427
BranchFormat.register_format(BranchReferenceFormat())
 
2428
BranchFormat.register_format(__format6)
 
2429
BranchFormat.register_format(__format7)
 
2430
BranchFormat.register_format(__format8)
 
2431
BranchFormat.set_default_format(__format7)
 
2432
BranchFormat.register_extra_format(BzrBranchFormat4())
2343
2433
 
2344
2434
 
2345
2435
class BranchWriteLockResult(LogicalLockResult):
2628
2718
            target.update_revisions(self, stop_revision,
2629
2719
                overwrite=overwrite, graph=graph)
2630
2720
        if self._push_should_merge_tags():
2631
 
            result.tag_conflicts = self.tags.merge_to(target.tags, overwrite)
 
2721
            result.tag_conflicts = self.tags.merge_to(target.tags,
 
2722
                overwrite)
2632
2723
        result.new_revno, result.new_revid = target.last_revision_info()
2633
2724
        return result
2634
2725
 
2649
2740
                mode=self.bzrdir._get_file_mode())
2650
2741
 
2651
2742
 
 
2743
class BzrBranchPreSplitOut(BzrBranch):
 
2744
 
 
2745
    def _get_checkout_format(self):
 
2746
        """Return the most suitable metadir for a checkout of this branch.
 
2747
        Weaves are used if this branch's repository uses weaves.
 
2748
        """
 
2749
        from bzrlib.repofmt.weaverepo import RepositoryFormat7
 
2750
        from bzrlib.bzrdir import BzrDirMetaFormat1
 
2751
        format = BzrDirMetaFormat1()
 
2752
        format.repository_format = RepositoryFormat7()
 
2753
        return format
 
2754
 
 
2755
 
2652
2756
class BzrBranch5(BzrBranch):
2653
2757
    """A format 5 branch. This supports new features over plain branches.
2654
2758
 
2666
2770
        """Return the branch we are bound to.
2667
2771
 
2668
2772
        :return: Either a Branch, or None
 
2773
 
 
2774
        This could memoise the branch, but if thats done
 
2775
        it must be revalidated on each new lock.
 
2776
        So for now we just don't memoise it.
 
2777
        # RBC 20060304 review this decision.
2669
2778
        """
2670
 
        if self._master_branch_cache is None:
2671
 
            self._master_branch_cache = self._get_master_branch(
2672
 
                possible_transports)
2673
 
        return self._master_branch_cache
2674
 
 
2675
 
    def _get_master_branch(self, possible_transports):
2676
2779
        bound_loc = self.get_bound_location()
2677
2780
        if not bound_loc:
2678
2781
            return None
2689
2792
 
2690
2793
        :param location: URL to the target branch
2691
2794
        """
2692
 
        self._master_branch_cache = None
2693
2795
        if location:
2694
2796
            self._transport.put_bytes('bound', location+'\n',
2695
2797
                mode=self.bzrdir._get_file_mode())
2947
3049
 
2948
3050
    def set_bound_location(self, location):
2949
3051
        """See Branch.set_push_location."""
2950
 
        self._master_branch_cache = None
2951
3052
        result = None
2952
3053
        config = self.get_config()
2953
3054
        if location is None:
3030
3131
        try:
3031
3132
            index = self._partial_revision_history_cache.index(revision_id)
3032
3133
        except ValueError:
3033
 
            try:
3034
 
                self._extend_partial_history(stop_revision=revision_id)
3035
 
            except errors.RevisionNotPresent, e:
3036
 
                raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
 
3134
            self._extend_partial_history(stop_revision=revision_id)
3037
3135
            index = len(self._partial_revision_history_cache) - 1
3038
3136
            if self._partial_revision_history_cache[index] != revision_id:
3039
3137
                raise errors.NoSuchRevision(self, revision_id)
3319
3417
        """
3320
3418
        raise NotImplementedError(self.copy_content_into)
3321
3419
 
3322
 
    @needs_write_lock
3323
 
    def fetch(self, stop_revision=None, fetch_spec=None):
3324
 
        """Fetch revisions.
3325
 
 
3326
 
        :param stop_revision: Last revision to fetch
3327
 
        :param fetch_spec: Fetch spec.
3328
 
        """
3329
 
        raise NotImplementedError(self.fetch)
3330
 
 
3331
3420
 
3332
3421
class GenericInterBranch(InterBranch):
3333
3422
    """InterBranch implementation that uses public Branch functions."""
3339
3428
 
3340
3429
    @classmethod
3341
3430
    def _get_branch_formats_to_test(klass):
3342
 
        return [(format_registry.get_default(), format_registry.get_default())]
 
3431
        return [(BranchFormat._default_format, BranchFormat._default_format)]
3343
3432
 
3344
3433
    @classmethod
3345
3434
    def unwrap_format(klass, format):
3368
3457
            self.source.tags.merge_to(self.target.tags)
3369
3458
 
3370
3459
    @needs_write_lock
3371
 
    def fetch(self, stop_revision=None, fetch_spec=None):
3372
 
        if fetch_spec is not None and stop_revision is not None:
3373
 
            raise AssertionError(
3374
 
                "fetch_spec and last_revision are mutually exclusive.")
3375
 
        if self.target.base == self.source.base:
3376
 
            return (0, [])
3377
 
        self.source.lock_read()
3378
 
        try:
3379
 
            if stop_revision is None and fetch_spec is None:
3380
 
                stop_revision = self.source.last_revision()
3381
 
                stop_revision = _mod_revision.ensure_null(stop_revision)
3382
 
            return self.target.repository.fetch(self.source.repository,
3383
 
                revision_id=stop_revision, fetch_spec=fetch_spec)
3384
 
        finally:
3385
 
            self.source.unlock()
3386
 
 
3387
 
    @needs_write_lock
3388
3460
    def update_revisions(self, stop_revision=None, overwrite=False,
3389
3461
        graph=None, fetch_tags=True):
3390
3462
        """See InterBranch.update_revisions()."""
3548
3620
        :param run_hooks: Private parameter - if false, this branch
3549
3621
            is being called because it's the master of the primary branch,
3550
3622
            so it should not run its hooks.
3551
 
            is being called because it's the master of the primary branch,
3552
 
            so it should not run its hooks.
3553
3623
        :param _override_hook_target: Private parameter - set the branch to be
3554
3624
            supplied as the target_branch to pull hooks.
3555
3625
        :param local: Only update the local branch, and not the bound branch.