Merge lp:~spiv/bzr/cross-format-stacking-fetch-562380-2.1 into lp:bzr/2.1

Proposed by Andrew Bennetts
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~spiv/bzr/cross-format-stacking-fetch-562380-2.1
Merge into: lp:bzr/2.1
Diff against target: 139 lines (+40/-5)
5 files modified
NEWS (+6/-0)
bzrlib/remote.py (+12/-0)
bzrlib/tests/per_repository_reference/__init__.py (+17/-0)
bzrlib/tests/per_repository_reference/test_default_stacking.py (+0/-1)
bzrlib/tests/test_remote.py (+5/-4)
To merge this branch: bzr merge lp:~spiv/bzr/cross-format-stacking-fetch-562380-2.1
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+23986@code.launchpad.net

Commit message

Don't allow RemoteRepository to stack on an incompatible-format repository. (#562380)

Description of the change

Backport to 2.1 of <https://code.edge.launchpad.net/~spiv/bzr/cross-format-stacking-fetch-562380/+merge/23526>: Don't allow RemoteRepository to stack on an incompatible-format repository. (#562380)

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-04-15 12:02:11 +0000
3+++ NEWS 2010-04-23 05:33:17 +0000
4@@ -38,6 +38,12 @@
5 problems importing bzrlib from a non-main thread.
6 (Elliot Murphy, #521989)
7
8+* Repositories accessed via a smart server now reject being stacked on a
9+ repository in an incompatible format, as is the case when accessing them
10+ via other methods. This was causing fetches from those repositories via
11+ a smart server (e.g. using ``bzr branch``) to receive invalid data.
12+ (Andrew Bennetts, #562380)
13+
14 * Standardize the error handling when creating a new ``StaticTuple``
15 (problems will raise TypeError). (Matt Nordhoff, #457979)
16
17
18=== modified file 'bzrlib/remote.py'
19--- bzrlib/remote.py 2010-02-17 17:11:16 +0000
20+++ bzrlib/remote.py 2010-04-23 05:33:17 +0000
21@@ -27,6 +27,7 @@
22 lock,
23 lockdir,
24 repository,
25+ repository as _mod_repository,
26 revision,
27 revision as _mod_revision,
28 symbol_versioning,
29@@ -1214,6 +1215,7 @@
30 # state, so always add a lock here. If a caller passes us a locked
31 # repository, they are responsible for unlocking it later.
32 repository.lock_read()
33+ self._check_fallback_repository(repository)
34 self._fallback_repositories.append(repository)
35 # If self._real_repository was parameterised already (e.g. because a
36 # _real_branch had its get_stacked_on_url method called), then the
37@@ -1224,6 +1226,16 @@
38 if repository.bzrdir.root_transport.base not in fallback_locations:
39 self._real_repository.add_fallback_repository(repository)
40
41+ def _check_fallback_repository(self, repository):
42+ """Check that this repository can fallback to repository safely.
43+
44+ Raise an error if not.
45+
46+ :param repository: A repository to fallback to.
47+ """
48+ return _mod_repository.InterRepository._assert_same_model(
49+ self, repository)
50+
51 def add_inventory(self, revid, inv, parents):
52 self._ensure_real()
53 return self._real_repository.add_inventory(revid, inv, parents)
54
55=== modified file 'bzrlib/tests/per_repository_reference/__init__.py'
56--- bzrlib/tests/per_repository_reference/__init__.py 2009-07-15 17:51:40 +0000
57+++ bzrlib/tests/per_repository_reference/__init__.py 2010-04-23 05:33:17 +0000
58@@ -23,6 +23,7 @@
59 """
60
61 from bzrlib import (
62+ errors,
63 repository,
64 remote,
65 )
66@@ -66,6 +67,22 @@
67 self.repository_format.__class__)
68
69
70+class TestIncompatibleStacking(TestCaseWithRepository):
71+
72+ def test_add_fallback_repository_rejects_incompatible(self):
73+ # Repository.add_fallback_repository raises IncompatibleRepositories if
74+ # you take two repositories in different serializations and try to
75+ # stack them.
76+ if self.make_repository('test')._format.supports_chks:
77+ different_fmt = '1.9'
78+ else:
79+ different_fmt = '2a'
80+ repo = self.make_repository('repo', format=different_fmt)
81+ referring = self.make_repository('referring')
82+ self.assertRaises(errors.IncompatibleRepositories,
83+ referring.add_fallback_repository, repo)
84+
85+
86 def external_reference_test_scenarios():
87 """Generate test scenarios for repositories supporting external references.
88 """
89
90=== modified file 'bzrlib/tests/per_repository_reference/test_default_stacking.py'
91--- bzrlib/tests/per_repository_reference/test_default_stacking.py 2009-06-10 03:56:49 +0000
92+++ bzrlib/tests/per_repository_reference/test_default_stacking.py 2010-04-23 05:33:17 +0000
93@@ -15,7 +15,6 @@
94 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
95
96
97-from bzrlib.smart import server
98 from bzrlib.tests.per_repository import TestCaseWithRepository
99
100
101
102=== modified file 'bzrlib/tests/test_remote.py'
103--- bzrlib/tests/test_remote.py 2010-02-17 17:11:16 +0000
104+++ bzrlib/tests/test_remote.py 2010-04-23 05:33:17 +0000
105@@ -1222,8 +1222,8 @@
106 len(branch.repository._real_repository._fallback_repositories))
107
108 def test_get_stacked_on_real_branch(self):
109- base_branch = self.make_branch('base', format='1.6')
110- stacked_branch = self.make_branch('stacked', format='1.6')
111+ base_branch = self.make_branch('base')
112+ stacked_branch = self.make_branch('stacked')
113 stacked_branch.set_stacked_on_url('../base')
114 reference_format = self.get_repo_format()
115 network_name = reference_format.network_name()
116@@ -1234,7 +1234,7 @@
117 'success', ('branch', branch_network_name))
118 client.add_expected_call(
119 'BzrDir.find_repositoryV3', ('stacked/',),
120- 'success', ('ok', '', 'no', 'no', 'yes', network_name))
121+ 'success', ('ok', '', 'yes', 'no', 'yes', network_name))
122 # called twice, once from constructor and then again by us
123 client.add_expected_call(
124 'Branch.get_stacked_on_url', ('stacked/',),
125@@ -2193,12 +2193,13 @@
126 """
127 # Make a repo with a fallback repo, both using a FakeClient.
128 format = remote.response_tuple_to_repo_format(
129- ('yes', 'no', 'yes', 'fake-network-name'))
130+ ('yes', 'no', 'yes', self.get_repo_format().network_name()))
131 repo, client = self.setup_fake_client_and_repository('quack')
132 repo._format = format
133 fallback_repo, ignored = self.setup_fake_client_and_repository(
134 'fallback')
135 fallback_repo._client = client
136+ fallback_repo._format = format
137 repo.add_fallback_repository(fallback_repo)
138 # First the client should ask the primary repo
139 client.add_expected_call(

Subscribers

People subscribed via source and target branches