13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
from bzrlib.branch import Branch
21
from bzrlib.bzrdir import BzrDir
22
from bzrlib.builtins import merge
23
16
import bzrlib.errors
24
from bzrlib.tests import TestCaseWithTransport
25
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
26
from bzrlib.tests.test_revision import make_branches
17
from bzrlib.selftest.testrevision import make_branches
27
18
from bzrlib.trace import mutter
28
from bzrlib.workingtree import WorkingTree
31
def has_revision(branch, revision_id):
32
return branch.repository.has_revision(revision_id)
34
def fetch_steps(self, br_a, br_b, writable_a):
35
"""A foreign test method for testing fetch locally and remotely."""
37
# TODO RBC 20060201 make this a repository test.
38
repo_b = br_b.repository
39
self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
40
self.assertTrue(repo_b.has_revision(br_a.revision_history()[2]))
41
self.assertEquals(len(br_b.revision_history()), 7)
42
self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[2])[0], 0)
43
# branch.fetch is not supposed to alter the revision history
44
self.assertEquals(len(br_b.revision_history()), 7)
45
self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
47
# fetching the next revision up in sample data copies one revision
48
self.assertEquals(br_b.fetch(br_a, br_a.revision_history()[3])[0], 1)
49
self.assertTrue(repo_b.has_revision(br_a.revision_history()[3]))
50
self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
51
self.assertTrue(br_a.repository.has_revision(br_b.revision_history()[5]))
53
# When a non-branch ancestor is missing, it should be unlisted...
54
# as its not reference from the inventory weave.
55
br_b4 = self.make_branch('br_4')
56
count, failures = br_b4.fetch(br_b)
57
self.assertEqual(count, 7)
58
self.assertEqual(failures, [])
60
self.assertEqual(writable_a.fetch(br_b)[0], 1)
61
self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
62
self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
19
from bzrlib.branch import Branch
23
from bzrlib.selftest import TestCaseInTempDir
64
br_b2 = self.make_branch('br_b2')
65
self.assertEquals(br_b2.fetch(br_b)[0], 7)
66
self.assertTrue(has_revision(br_b2, br_b.revision_history()[4]))
67
self.assertTrue(has_revision(br_b2, br_a.revision_history()[2]))
68
self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
70
br_a2 = self.make_branch('br_a2')
71
self.assertEquals(br_a2.fetch(br_a)[0], 9)
72
self.assertTrue(has_revision(br_a2, br_b.revision_history()[4]))
73
self.assertTrue(has_revision(br_a2, br_a.revision_history()[3]))
74
self.assertTrue(has_revision(br_a2, br_a.revision_history()[2]))
76
br_a3 = self.make_branch('br_a3')
77
# pulling a branch with no revisions grabs nothing, regardless of
78
# whats in the inventory.
79
self.assertEquals(br_a3.fetch(br_a2)[0], 0)
80
for revno in range(4):
82
br_a3.repository.has_revision(br_a.revision_history()[revno]))
83
self.assertEqual(br_a3.fetch(br_a2, br_a.revision_history()[2])[0], 3)
84
# pull the 3 revisions introduced by a@u-0-3
85
fetched = br_a3.fetch(br_a2, br_a.revision_history()[3])[0]
86
self.assertEquals(fetched, 3, "fetched %d instead of 3" % fetched)
87
# InstallFailed should be raised if the branch is missing the revision
89
self.assertRaises(bzrlib.errors.InstallFailed, br_a3.fetch, br_a2, 'pizza')
90
# InstallFailed should be raised if the branch is missing a revision
91
# from its own revision history
92
br_a2.append_revision('a-b-c')
93
self.assertRaises(bzrlib.errors.InstallFailed, br_a3.fetch, br_a2)
94
#TODO: test that fetch correctly does reweaving when needed. RBC 20051008
95
# Note that this means - updating the weave when ghosts are filled in to
96
# add the right parents.
99
class TestFetch(TestCaseWithTransport):
101
def test_fetch(self):
102
#highest indices a: 5, b: 7
103
br_a, br_b = make_branches(self)
104
fetch_steps(self, br_a, br_b, br_a)
107
class TestMergeFetch(TestCaseWithTransport):
109
def test_merge_fetches_unrelated(self):
110
"""Merge brings across history from unrelated source"""
111
wt1 = self.make_branch_and_tree('br1')
113
wt1.commit(message='rev 1-1', rev_id='1-1')
114
wt1.commit(message='rev 1-2', rev_id='1-2')
115
wt2 = self.make_branch_and_tree('br2')
117
wt2.commit(message='rev 2-1', rev_id='2-1')
118
merge(other_revision=['br1', -1], base_revision=['br1', 0],
120
self._check_revs_present(br2)
122
def test_merge_fetches(self):
123
"""Merge brings across history from source"""
124
wt1 = self.make_branch_and_tree('br1')
126
wt1.commit(message='rev 1-1', rev_id='1-1')
127
dir_2 = br1.bzrdir.sprout('br2')
128
br2 = dir_2.open_branch()
129
wt1.commit(message='rev 1-2', rev_id='1-2')
130
dir_2.open_workingtree().commit(message='rev 2-1', rev_id='2-1')
131
merge(other_revision=['br1', -1], base_revision=[None, None],
133
self._check_revs_present(br2)
135
def _check_revs_present(self, br2):
136
for rev_id in '1-1', '1-2', '2-1':
137
self.assertTrue(br2.repository.has_revision(rev_id))
138
rev = br2.repository.get_revision(rev_id)
139
self.assertEqual(rev.revision_id, rev_id)
140
self.assertTrue(br2.repository.get_inventory(rev_id))
143
class TestMergeFileHistory(TestCaseWithTransport):
146
super(TestMergeFileHistory, self).setUp()
147
wt1 = self.make_branch_and_tree('br1')
149
self.build_tree_contents([('br1/file', 'original contents\n')])
150
wt1.add('file', 'this-file-id')
151
wt1.commit(message='rev 1-1', rev_id='1-1')
152
dir_2 = br1.bzrdir.sprout('br2')
153
br2 = dir_2.open_branch()
154
wt2 = dir_2.open_workingtree()
155
self.build_tree_contents([('br1/file', 'original from 1\n')])
156
wt1.commit(message='rev 1-2', rev_id='1-2')
157
self.build_tree_contents([('br1/file', 'agreement\n')])
158
wt1.commit(message='rev 1-3', rev_id='1-3')
159
self.build_tree_contents([('br2/file', 'contents in 2\n')])
160
wt2.commit(message='rev 2-1', rev_id='2-1')
161
self.build_tree_contents([('br2/file', 'agreement\n')])
162
wt2.commit(message='rev 2-2', rev_id='2-2')
164
def test_merge_fetches_file_history(self):
165
"""Merge brings across file histories"""
166
br2 = Branch.open('br2')
167
merge(other_revision=['br1', -1], base_revision=[None, None],
169
for rev_id, text in [('1-2', 'original from 1\n'),
170
('1-3', 'agreement\n'),
171
('2-1', 'contents in 2\n'),
172
('2-2', 'agreement\n')]:
173
self.assertEqualDiff(
174
br2.repository.revision_tree(
175
rev_id).get_file_text('this-file-id'), text)
178
class TestHttpFetch(TestCaseWithWebserver):
179
# FIXME RBC 20060124 this really isn't web specific, perhaps an
180
# instrumented readonly transport? Can we do an instrumented
181
# adapter and use self.get_readonly_url ?
183
def test_fetch(self):
184
#highest indices a: 5, b: 7
185
br_a, br_b = make_branches(self)
186
br_rem_a = Branch.open(self.get_readonly_url('branch1'))
187
fetch_steps(self, br_rem_a, br_b, br_a)
189
def test_weaves_are_retrieved_once(self):
190
self.build_tree(("source/", "source/file", "target/"))
191
wt = self.make_branch_and_tree('source')
193
wt.add(["file"], ["id"])
194
wt.commit("added file")
195
print >>open("source/file", 'w'), "blah"
196
wt.commit("changed file")
197
target = BzrDir.create_branch_and_repo("target/")
198
source = Branch.open(self.get_readonly_url("source/"))
199
self.assertEqual(target.fetch(source), (2, []))
200
log_pattern = '%%s HTTP/1.1" 200 - "-" "bzr/%s"' % bzrlib.__version__
201
# this is the path to the literal file. As format changes
202
# occur it needs to be updated. FIXME: ask the store for the
204
weave_suffix = log_pattern % 'weaves/ce/id.weave'
206
len([log for log in self.get_readonly_server().logs if log.endswith(weave_suffix)]))
207
inventory_weave_suffix = log_pattern % 'inventory.weave'
209
len([log for log in self.get_readonly_server().logs if log.endswith(
210
inventory_weave_suffix)]))
211
# this r-h check test will prevent regressions, but it currently already
212
# passes, before the patch to cache-rh is applied :[
213
revision_history_suffix = log_pattern % 'revision-history'
215
len([log for log in self.get_readonly_server().logs if log.endswith(
216
revision_history_suffix)]))
217
# FIXME naughty poking in there.
218
self.get_readonly_server().logs = []
219
# check there is nothing more to fetch
220
source = Branch.open(self.get_readonly_url("source/"))
221
self.assertEqual(target.fetch(source), (0, []))
222
self.failUnless(self.get_readonly_server().logs[0].endswith(log_pattern % 'branch-format'))
223
self.failUnless(self.get_readonly_server().logs[1].endswith(log_pattern % 'revision-history'))
224
self.assertEqual(2, len(self.get_readonly_server().logs))
26
class TestFetch(TestCaseInTempDir):
28
from bzrlib.fetch import greedy_fetch, has_revision
32
return Branch(name, init=True)
34
#highest indices a: 5, b: 7
35
br_a, br_b = make_branches()
36
assert not has_revision(br_b, br_a.revision_history()[3])
37
assert has_revision(br_b, br_a.revision_history()[2])
38
assert len(br_b.revision_history()) == 7
39
assert greedy_fetch(br_b, br_a, br_a.revision_history()[2])[0] == 0
41
# greedy_fetch is not supposed to alter the revision history
42
assert len(br_b.revision_history()) == 7
43
assert not has_revision(br_b, br_a.revision_history()[3])
45
assert len(br_b.revision_history()) == 7
46
assert greedy_fetch(br_b, br_a, br_a.revision_history()[3])[0] == 1
47
assert has_revision(br_b, br_a.revision_history()[3])
48
assert not has_revision(br_a, br_b.revision_history()[3])
49
assert not has_revision(br_a, br_b.revision_history()[4])
51
# When a non-branch ancestor is missing, it should be a failure, not
53
br_a4 = new_branch('br_a4')
54
count, failures = greedy_fetch(br_a4, br_a)
56
assert failures == set((br_b.revision_history()[4],
57
br_b.revision_history()[5]))
59
assert greedy_fetch(br_a, br_b)[0] == 4
60
assert has_revision(br_a, br_b.revision_history()[3])
61
assert has_revision(br_a, br_b.revision_history()[4])
63
br_b2 = new_branch('br_b2')
64
assert greedy_fetch(br_b2, br_b)[0] == 7
65
assert has_revision(br_b2, br_b.revision_history()[4])
66
assert has_revision(br_b2, br_a.revision_history()[2])
67
assert not has_revision(br_b2, br_a.revision_history()[3])
69
br_a2 = new_branch('br_a2')
70
assert greedy_fetch(br_a2, br_a)[0] == 9
71
assert has_revision(br_a2, br_b.revision_history()[4])
72
assert has_revision(br_a2, br_a.revision_history()[3])
74
br_a3 = new_branch('br_a3')
75
assert greedy_fetch(br_a3, br_a2)[0] == 0
76
for revno in range(4):
77
assert not has_revision(br_a3, br_a.revision_history()[revno])
78
assert greedy_fetch(br_a3, br_a2, br_a.revision_history()[2])[0] == 3
79
fetched = greedy_fetch(br_a3, br_a2, br_a.revision_history()[3])[0]
80
assert fetched == 3, "fetched %d instead of 3" % fetched
81
# InstallFailed should be raised if the branch is missing the revision
83
self.assertRaises(bzrlib.errors.InstallFailed, greedy_fetch, br_a3,
85
# InstallFailed should be raised if the branch is missing a revision
86
# from its own revision history
87
br_a2.append_revision('a-b-c')
88
self.assertRaises(bzrlib.errors.InstallFailed, greedy_fetch, br_a3,
93
if __name__ == '__main__':
95
sys.exit(unittest.run_suite(unittest.makeSuite()))