~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_fetch.py

Handled simultaneous renames of parent and child better

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
16
 
 
17
import os
 
18
import sys
 
19
 
 
20
from bzrlib.branch import Branch
 
21
from bzrlib.builtins import merge
16
22
import bzrlib.errors
17
 
from bzrlib.selftest.testrevision import make_branches
 
23
from bzrlib.fetch import greedy_fetch
 
24
from bzrlib.tests import TestCaseWithTransport
 
25
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
 
26
from bzrlib.tests.test_revision import make_branches
18
27
from bzrlib.trace import mutter
19
 
from bzrlib.branch import Branch
20
 
import sys
21
 
import os
22
 
 
23
 
from bzrlib.selftest import TestCaseInTempDir
 
28
from bzrlib.workingtree import WorkingTree
 
29
 
 
30
 
 
31
def has_revision(branch, revision_id):
 
32
    try:
 
33
        branch.repository.get_revision_xml_file(revision_id)
 
34
        return True
 
35
    except bzrlib.errors.NoSuchRevision:
 
36
        return False
 
37
 
 
38
 
 
39
def fetch_steps(self, br_a, br_b, writable_a):
 
40
    """A foreign test method for testing fetch locally and remotely."""
 
41
    def new_branch(name):
 
42
        os.mkdir(name)
 
43
        return WorkingTree.create_standalone(name).branch
 
44
            
 
45
    self.assertFalse(has_revision(br_b, br_a.revision_history()[3]))
 
46
    self.assert_(has_revision(br_b, br_a.revision_history()[2]))
 
47
    self.assertEquals(len(br_b.revision_history()), 7)
 
48
    self.assertEquals(greedy_fetch(br_b, br_a, br_a.revision_history()[2])[0], 0)
 
49
 
 
50
    # greedy_fetch is not supposed to alter the revision history
 
51
    self.assertEquals(len(br_b.revision_history()), 7)
 
52
    self.assertFalse(has_revision(br_b, br_a.revision_history()[3]))
 
53
 
 
54
    self.assertEquals(len(br_b.revision_history()), 7)
 
55
    self.assertEquals(greedy_fetch(br_b, br_a, br_a.revision_history()[3])[0], 1)
 
56
    self.assert_(has_revision(br_b, br_a.revision_history()[3]))
 
57
    self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
 
58
    self.assert_(has_revision(br_a, br_b.revision_history()[5]))
 
59
 
 
60
    # When a non-branch ancestor is missing, it should be unlisted...
 
61
    # as its not reference from the inventory weave.
 
62
    br_b4 = new_branch('br_4')
 
63
    count, failures = greedy_fetch(br_b4, br_b)
 
64
    self.assertEqual(count, 7)
 
65
    self.assertEqual(failures, [])
 
66
 
 
67
    self.assertEqual(greedy_fetch(writable_a, br_b)[0], 1)
 
68
    self.assert_(has_revision(br_a, br_b.revision_history()[3]))
 
69
    self.assert_(has_revision(br_a, br_b.revision_history()[4]))
24
70
        
25
 
 
26
 
class TestFetch(TestCaseInTempDir):
27
 
    def runTest(self):
28
 
        from bzrlib.fetch import greedy_fetch, has_revision
29
 
 
30
 
        def new_branch(name):
31
 
            os.mkdir(name)
32
 
            return Branch(name, init=True)
33
 
            
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
40
 
 
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])
44
 
 
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])
50
 
 
51
 
        # When a non-branch ancestor is missing, it should be a failure, not
52
 
        # exception
53
 
        br_a4 = new_branch('br_a4')
54
 
        count, failures = greedy_fetch(br_a4, br_a)
55
 
        assert count == 6
56
 
        assert failures == set((br_b.revision_history()[4],
57
 
                                br_b.revision_history()[5])) 
58
 
 
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])
62
 
 
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])
68
 
 
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])
73
 
 
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
82
 
        # that was requested.
83
 
        self.assertRaises(bzrlib.errors.InstallFailed, greedy_fetch, br_a3,
84
 
                          br_a2, 'pizza')
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,
89
 
                          br_a2)
90
 
 
91
 
 
92
 
 
93
 
if __name__ == '__main__':
94
 
    import unittest
95
 
    sys.exit(unittest.run_suite(unittest.makeSuite()))
 
71
    br_b2 = new_branch('br_b2')
 
72
    self.assertEquals(greedy_fetch(br_b2, br_b)[0], 7)
 
73
    self.assert_(has_revision(br_b2, br_b.revision_history()[4]))
 
74
    self.assert_(has_revision(br_b2, br_a.revision_history()[2]))
 
75
    self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
 
76
 
 
77
    br_a2 = new_branch('br_a2')
 
78
    self.assertEquals(greedy_fetch(br_a2, br_a)[0], 9)
 
79
    self.assert_(has_revision(br_a2, br_b.revision_history()[4]))
 
80
    self.assert_(has_revision(br_a2, br_a.revision_history()[3]))
 
81
    self.assert_(has_revision(br_a2, br_a.revision_history()[2]))
 
82
 
 
83
    br_a3 = new_branch('br_a3')
 
84
    self.assertEquals(greedy_fetch(br_a3, br_a2)[0], 0)
 
85
    for revno in range(4):
 
86
        self.assertFalse(has_revision(br_a3, br_a.revision_history()[revno]))
 
87
    self.assertEqual(greedy_fetch(br_a3, br_a2, br_a.revision_history()[2])[0], 3)
 
88
    fetched = greedy_fetch(br_a3, br_a2, br_a.revision_history()[3])[0]
 
89
    self.assertEquals(fetched, 6, "fetched %d instead of 6" % fetched)
 
90
    # InstallFailed should be raised if the branch is missing the revision
 
91
    # that was requested.
 
92
    self.assertRaises(bzrlib.errors.InstallFailed, greedy_fetch, br_a3,
 
93
                      br_a2, 'pizza')
 
94
    # InstallFailed should be raised if the branch is missing a revision
 
95
    # from its own revision history
 
96
    br_a2.append_revision('a-b-c')
 
97
    self.assertRaises(bzrlib.errors.InstallFailed, greedy_fetch, br_a3,
 
98
                      br_a2)
 
99
 
 
100
 
 
101
    #TODO: test that fetch correctly does reweaving when needed. RBC 20051008
 
102
 
 
103
class TestFetch(TestCaseWithTransport):
 
104
 
 
105
    def test_fetch(self):
 
106
        #highest indices a: 5, b: 7
 
107
        br_a, br_b = make_branches(self)
 
108
        fetch_steps(self, br_a, br_b, br_a)
 
109
 
 
110
 
 
111
class TestMergeFetch(TestCaseWithTransport):
 
112
 
 
113
    def test_merge_fetches_unrelated(self):
 
114
        """Merge brings across history from unrelated source"""
 
115
        wt1 = self.make_branch_and_tree('br1')
 
116
        br1 = wt1.branch
 
117
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
118
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
119
        wt2 = self.make_branch_and_tree('br2')
 
120
        br2 = wt2.branch
 
121
        wt2.commit(message='rev 2-1', rev_id='2-1')
 
122
        merge(other_revision=['br1', -1], base_revision=['br1', 0],
 
123
              this_dir='br2')
 
124
        self._check_revs_present(br2)
 
125
 
 
126
    def test_merge_fetches(self):
 
127
        """Merge brings across history from source"""
 
128
        wt1 = self.make_branch_and_tree('br1')
 
129
        br1 = wt1.branch
 
130
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
131
        br2 = br1.clone('br2')
 
132
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
133
        WorkingTree('br2', br2).commit(message='rev 2-1', rev_id='2-1')
 
134
        merge(other_revision=['br1', -1], base_revision=[None, None], 
 
135
              this_dir='br2')
 
136
        self._check_revs_present(br2)
 
137
 
 
138
    def _check_revs_present(self, br2):
 
139
        for rev_id in '1-1', '1-2', '2-1':
 
140
            self.assertTrue(br2.repository.has_revision(rev_id))
 
141
            rev = br2.repository.get_revision(rev_id)
 
142
            self.assertEqual(rev.revision_id, rev_id)
 
143
            self.assertTrue(br2.repository.get_inventory(rev_id))
 
144
 
 
145
 
 
146
class TestMergeFileHistory(TestCaseWithTransport):
 
147
 
 
148
    def setUp(self):
 
149
        super(TestMergeFileHistory, self).setUp()
 
150
        wt1 = self.make_branch_and_tree('br1')
 
151
        br1 = wt1.branch
 
152
        self.build_tree_contents([('br1/file', 'original contents\n')])
 
153
        wt1.add('file', 'this-file-id')
 
154
        wt1.commit(message='rev 1-1', rev_id='1-1')
 
155
        br2 = br1.clone('br2')
 
156
        wt2 = WorkingTree('br2', br2)
 
157
        self.build_tree_contents([('br1/file', 'original from 1\n')])
 
158
        wt1.commit(message='rev 1-2', rev_id='1-2')
 
159
        self.build_tree_contents([('br1/file', 'agreement\n')])
 
160
        wt1.commit(message='rev 1-3', rev_id='1-3')
 
161
        self.build_tree_contents([('br2/file', 'contents in 2\n')])
 
162
        wt2.commit(message='rev 2-1', rev_id='2-1')
 
163
        self.build_tree_contents([('br2/file', 'agreement\n')])
 
164
        wt2.commit(message='rev 2-2', rev_id='2-2')
 
165
 
 
166
    def test_merge_fetches_file_history(self):
 
167
        """Merge brings across file histories"""
 
168
        br2 = Branch.open('br2')
 
169
        merge(other_revision=['br1', -1], base_revision=[None, None], 
 
170
              this_dir='br2')
 
171
        for rev_id, text in [('1-2', 'original from 1\n'),
 
172
                             ('1-3', 'agreement\n'),
 
173
                             ('2-1', 'contents in 2\n'),
 
174
                             ('2-2', 'agreement\n')]:
 
175
            self.assertEqualDiff(
 
176
                br2.repository.revision_tree(
 
177
                    rev_id).get_file_text('this-file-id'), text)
 
178
 
 
179
 
 
180
class TestHttpFetch(TestCaseWithWebserver):
 
181
    # FIXME RBC 20060124 this really isn't web specific, perhaps an
 
182
    # instrumented readonly transport? Can we do an instrumented
 
183
    # adapter and use self.get_readonly_url ?
 
184
 
 
185
    def test_fetch(self):
 
186
        #highest indices a: 5, b: 7
 
187
        print "TestHttpFetch.test_fetch disabled during transition."
 
188
        return
 
189
        br_a, br_b = make_branches(self)
 
190
        br_rem_a = Branch.open(self.get_remote_url(br_a.base))
 
191
        fetch_steps(self, br_rem_a, br_b, br_a)
 
192
 
 
193
    def test_weaves_are_retrieved_once(self):
 
194
        self.build_tree(("source/", "source/file", "target/"))
 
195
        wt = WorkingTree.create_standalone('source')
 
196
        branch = wt.branch
 
197
        wt.add(["file"], ["id"])
 
198
        wt.commit("added file")
 
199
        print >>open("source/file", 'w'), "blah"
 
200
        wt.commit("changed file")
 
201
        target = Branch.create("target/")
 
202
        source = Branch.open(self.get_remote_url("source/"))
 
203
        self.assertEqual(greedy_fetch(target, source), (2, []))
 
204
        # this is the path to the literal file. As format changes 
 
205
        # occur it needs to be updated. FIXME: ask the store for the
 
206
        # path.
 
207
        weave_suffix = 'weaves/ce/id.weave HTTP/1.1" 200 -'
 
208
        self.assertEqual(1,
 
209
            len([log for log in self.server.logs if log.endswith(weave_suffix)]))
 
210
        inventory_weave_suffix = 'inventory.weave HTTP/1.1" 200 -'
 
211
        self.assertEqual(1,
 
212
            len([log for log in self.server.logs if log.endswith(
 
213
                inventory_weave_suffix)]))
 
214
        # this r-h check test will prevent regressions, but it currently already 
 
215
        # passes, before the patch to cache-rh is applied :[
 
216
        revision_history_suffix = 'revision-history HTTP/1.1" 200 -'
 
217
        self.assertEqual(1,
 
218
            len([log for log in self.server.logs if log.endswith(
 
219
                revision_history_suffix)]))
 
220
        # FIXME naughty poking in there.
 
221
        self.server.logs = []
 
222
        # check there is nothing more to fetch
 
223
        source = Branch.open(self.get_remote_url("source/"))
 
224
        self.assertEqual(greedy_fetch(target, source), (0, []))
 
225
        self.failUnless(self.server.logs[0].endswith('branch-format HTTP/1.1" 200 -'))
 
226
        self.failUnless(self.server.logs[1].endswith('revision-history HTTP/1.1" 200 -'))
 
227
        self.assertEqual(2, len(self.server.logs))