~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Robert Collins
  • Date: 2009-02-13 00:52:18 UTC
  • mto: This revision was merged to the branch mainline in revision 4012.
  • Revision ID: robertc@robertcollins.net-20090213005218-yxrgiq7j1du2vldm
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
71
71
class RemoteBzrDir(BzrDir, _RpcHelper):
72
72
    """Control directory on a remote server, accessed via bzr:// or similar."""
73
73
 
74
 
    def __init__(self, transport, _client=None):
 
74
    def __init__(self, transport, format, _client=None):
75
75
        """Construct a RemoteBzrDir.
76
76
 
77
77
        :param _client: Private parameter for testing. Disables probing and the
78
78
            use of a real bzrdir.
79
79
        """
80
 
        BzrDir.__init__(self, transport, RemoteBzrDirFormat())
 
80
        BzrDir.__init__(self, transport, format)
81
81
        # this object holds a delegated bzrdir that uses file-level operations
82
82
        # to talk to the other side
83
83
        self._real_bzrdir = None
113
113
        return self._real_bzrdir.cloning_metadir(stacked)
114
114
 
115
115
    def create_repository(self, shared=False):
116
 
        self._ensure_real()
117
 
        self._real_bzrdir.create_repository(shared=shared)
118
 
        return self.open_repository()
 
116
        # as per meta1 formats - just delegate to the format object which may
 
117
        # be parameterised.
 
118
        result = self._format.repository_format.initialize(self, shared)
 
119
        if not isinstance(result, RemoteRepository):
 
120
            return self.open_repository()
 
121
        else:
 
122
            return result
119
123
 
120
124
    def destroy_repository(self):
121
125
        """See BzrDir.destroy_repository"""
123
127
        self._real_bzrdir.destroy_repository()
124
128
 
125
129
    def create_branch(self):
126
 
        self._ensure_real()
127
 
        real_branch = self._real_bzrdir.create_branch()
128
 
        return RemoteBranch(self, self.find_repository(), real_branch)
 
130
        # as per meta1 formats - just delegate to the format object which may
 
131
        # be parameterised.
 
132
        real_branch = self._format.get_branch_format().initialize(self)
 
133
        if not isinstance(real_branch, RemoteBranch):
 
134
            return RemoteBranch(self, self.find_repository(), real_branch)
 
135
        else:
 
136
            return real_branch
129
137
 
130
138
    def destroy_branch(self):
131
139
        """See BzrDir.destroy_branch"""
261
269
 
262
270
    _matchingbzrdir = RemoteBzrDirFormat()
263
271
 
 
272
    def __init__(self):
 
273
        repository.RepositoryFormat.__init__(self)
 
274
        self._custom_format = None
 
275
 
264
276
    def initialize(self, a_bzrdir, shared=False):
 
277
        if self._custom_format:
 
278
            # This returns a custom instance - e.g. a pack repo, not a remote
 
279
            # repo.
 
280
            return self._custom_format.initialize(a_bzrdir, shared=shared)
265
281
        if not isinstance(a_bzrdir, RemoteBzrDir):
266
282
            prior_repo = self._creating_bzrdir.open_repository()
267
283
            prior_repo._ensure_real()
268
284
            return prior_repo._real_repository._format.initialize(
269
285
                a_bzrdir, shared=shared)
270
 
        return a_bzrdir.create_repository(shared=shared)
 
286
        # delegate to a real object at this point (remoteBzrDir delegate to the
 
287
        # repository format which would lead to infinite recursion).
 
288
        a_bzrdir._ensure_real()
 
289
        result = a_bzrdir._real_bzrdir.create_repository(shared=shared)
 
290
        if not isinstance(result, RemoteRepository):
 
291
            return self.open(a_bzrdir)
 
292
        else:
 
293
            return result
271
294
    
272
295
    def open(self, a_bzrdir):
273
296
        if not isinstance(a_bzrdir, RemoteBzrDir):
1261
1284
        return a_bzrdir.open_branch()
1262
1285
 
1263
1286
    def initialize(self, a_bzrdir):
1264
 
        return a_bzrdir.create_branch()
 
1287
        # Delegate to a _real object here - the RemoteBzrDir format now
 
1288
        # supports delegating to parameterised branch formats and as such
 
1289
        # this RemoteBranchFormat method is only called when no specific format
 
1290
        # is selected.
 
1291
        if not isinstance(a_bzrdir, RemoteBzrDir):
 
1292
            result = a_bzrdir.create_branch()
 
1293
        else:
 
1294
            a_bzrdir._ensure_real()
 
1295
            result = a_bzrdir._real_bzrdir.create_branch()
 
1296
        if not isinstance(result, RemoteBranch):
 
1297
            result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
 
1298
        return result
1265
1299
 
1266
1300
    def supports_tags(self):
1267
1301
        # Remote branches might support tags, but we won't know until we
1580
1614
 
1581
1615
    def _set_last_revision_descendant(self, revision_id, other_branch,
1582
1616
            allow_diverged=False, allow_overwrite_descendant=False):
 
1617
        # This performs additional work to meet the hook contract; while its
 
1618
        # undesirable, we have to synthesise the revno to call the hook, and
 
1619
        # not calling the hook is worse as it means changes can't be prevented.
 
1620
        # Having calculated this though, we can't just call into
 
1621
        # set_last_revision_info as a simple call, because there is a set_rh
 
1622
        # hook that some folk may still be using.
 
1623
        old_revno, old_revid = self.last_revision_info()
 
1624
        history = self._lefthand_history(revision_id)
 
1625
        self._run_pre_change_branch_tip_hooks(len(history), revision_id)
1583
1626
        err_context = {'other_branch': other_branch}
1584
1627
        response = self._call('Branch.set_last_revision_ex',
1585
1628
            self._remote_path(), self._lock_token, self._repo_lock_token,
1590
1633
            raise errors.UnexpectedSmartServerResponse(response)
1591
1634
        new_revno, new_revision_id = response[1:]
1592
1635
        self._last_revision_info_cache = new_revno, new_revision_id
 
1636
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1593
1637
        if self._real_branch is not None:
1594
1638
            cache = new_revno, new_revision_id
1595
1639
            self._real_branch._last_revision_info_cache = cache
1596
1640
 
1597
1641
    def _set_last_revision(self, revision_id):
 
1642
        old_revno, old_revid = self.last_revision_info()
 
1643
        # This performs additional work to meet the hook contract; while its
 
1644
        # undesirable, we have to synthesise the revno to call the hook, and
 
1645
        # not calling the hook is worse as it means changes can't be prevented.
 
1646
        # Having calculated this though, we can't just call into
 
1647
        # set_last_revision_info as a simple call, because there is a set_rh
 
1648
        # hook that some folk may still be using.
 
1649
        history = self._lefthand_history(revision_id)
 
1650
        self._run_pre_change_branch_tip_hooks(len(history), revision_id)
1598
1651
        self._clear_cached_state()
1599
1652
        response = self._call('Branch.set_last_revision',
1600
1653
            self._remote_path(), self._lock_token, self._repo_lock_token,
1601
1654
            revision_id)
1602
1655
        if response != ('ok',):
1603
1656
            raise errors.UnexpectedSmartServerResponse(response)
 
1657
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1604
1658
 
1605
1659
    @needs_write_lock
1606
1660
    def set_revision_history(self, rev_history):
1612
1666
        else:
1613
1667
            rev_id = rev_history[-1]
1614
1668
        self._set_last_revision(rev_id)
 
1669
        for hook in branch.Branch.hooks['set_rh']:
 
1670
            hook(self, rev_history)
1615
1671
        self._cache_revision_history(rev_history)
1616
1672
 
1617
1673
    def get_parent(self):
1618
1674
        self._ensure_real()
1619
1675
        return self._real_branch.get_parent()
 
1676
 
 
1677
    def _get_parent_location(self):
 
1678
        # Used by tests, when checking normalisation of given vs stored paths.
 
1679
        self._ensure_real()
 
1680
        return self._real_branch._get_parent_location()
1620
1681
        
1621
1682
    def set_parent(self, url):
1622
1683
        self._ensure_real()
1623
1684
        return self._real_branch.set_parent(url)
 
1685
 
 
1686
    def _set_parent_location(self, url):
 
1687
        # Used by tests, to poke bad urls into branch configurations
 
1688
        if url is None:
 
1689
            self.set_parent(url)
 
1690
        else:
 
1691
            self._ensure_real()
 
1692
            return self._real_branch._set_parent_location(url)
1624
1693
        
1625
1694
    def set_stacked_on_url(self, stacked_location):
1626
1695
        """Set the URL this branch is stacked against.
1678
1747
 
1679
1748
    @needs_write_lock
1680
1749
    def set_last_revision_info(self, revno, revision_id):
 
1750
        # XXX: These should be returned by the set_last_revision_info verb
 
1751
        old_revno, old_revid = self.last_revision_info()
 
1752
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
1681
1753
        revision_id = ensure_null(revision_id)
1682
1754
        try:
1683
1755
            response = self._call('Branch.set_last_revision_info',
1692
1764
        if response == ('ok',):
1693
1765
            self._clear_cached_state()
1694
1766
            self._last_revision_info_cache = revno, revision_id
 
1767
            self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1695
1768
            # Update the _real_branch's cache too.
1696
1769
            if self._real_branch is not None:
1697
1770
                cache = self._last_revision_info_cache
1704
1777
                                  other_branch=None):
1705
1778
        medium = self._client._medium
1706
1779
        if not medium._is_remote_before((1, 6)):
 
1780
            # Use a smart method for 1.6 and above servers
1707
1781
            try:
1708
1782
                self._set_last_revision_descendant(revision_id, other_branch,
1709
1783
                    allow_diverged=True, allow_overwrite_descendant=True)
1711
1785
            except errors.UnknownSmartMethod:
1712
1786
                medium._remember_remote_is_before((1, 6))
1713
1787
        self._clear_cached_state_of_remote_branch_only()
1714
 
        self._ensure_real()
1715
 
        self._real_branch.generate_revision_history(
1716
 
            revision_id, last_rev=last_rev, other_branch=other_branch)
 
1788
        self.set_revision_history(self._lefthand_history(revision_id,
 
1789
            last_rev=last_rev,other_branch=other_branch))
1717
1790
 
1718
1791
    @property
1719
1792
    def tags(self):