~bzr-pqm/bzr/bzr.dev

2697.2.2 by Martin Pool
deprecate Branch.append_revision
1
# Copyright (C) 2005, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1115 by Martin Pool
- split fetch tests into a separate file
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1115 by Martin Pool
- split fetch tests into a separate file
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1115 by Martin Pool
- split fetch tests into a separate file
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1238 by Martin Pool
- remove a lot of dead code from fetch
16
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
17
import os
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
18
import re
1238 by Martin Pool
- remove a lot of dead code from fetch
19
import sys
20
2697.2.2 by Martin Pool
deprecate Branch.append_revision
21
import bzrlib
2323.8.2 by Aaron Bentley
Give a nicer error on fetch when repos are in incompatible formats
22
from bzrlib import (
23
    bzrdir,
24
    errors,
3871.4.2 by John Arbash Meinel
Finally a test case that reproduces bug #304841
25
    osutils,
1551.15.70 by Aaron Bentley
Avoid using builtins.merge
26
    merge,
2323.8.2 by Aaron Bentley
Give a nicer error on fetch when repos are in incompatible formats
27
    repository,
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
28
    versionedfile,
2323.8.2 by Aaron Bentley
Give a nicer error on fetch when repos are in incompatible formats
29
    )
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
30
from bzrlib.branch import Branch
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
31
from bzrlib.bzrdir import BzrDir
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
32
from bzrlib.repofmt import knitrepo
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
33
from bzrlib.tests import TestCaseWithTransport
2929.3.8 by Vincent Ladeuil
Rename bzrlib/test/HTTPTestUtils.py to bzrlib/tests/http_utils.py and fix uses.
34
from bzrlib.tests.http_utils import TestCaseWithWebserver
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
35
from bzrlib.tests.test_revision import make_branches
36
from bzrlib.trace import mutter
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
37
from bzrlib.upgrade import Convert
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
38
from bzrlib.workingtree import WorkingTree
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
39
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
40
# These tests are a bit old; please instead add new tests into
41
# interrepository_implementations/ so they'll run on all relevant
42
# combinations.
43
1115 by Martin Pool
- split fetch tests into a separate file
44
1238 by Martin Pool
- remove a lot of dead code from fetch
45
def has_revision(branch, revision_id):
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
46
    return branch.repository.has_revision(revision_id)
1534.4.5 by Robert Collins
Turn branch format.open into a factory.
47
1393 by Robert Collins
reenable remotebranch tests
48
def fetch_steps(self, br_a, br_b, writable_a):
49
    """A foreign test method for testing fetch locally and remotely."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
50
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
51
    # TODO RBC 20060201 make this a repository test.
52
    repo_b = br_b.repository
53
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
54
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[2]))
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
55
    self.assertEquals(len(br_b.revision_history()), 7)
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
56
    br_b.fetch(br_a, br_a.revision_history()[2])
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
57
    # branch.fetch is not supposed to alter the revision history
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
58
    self.assertEquals(len(br_b.revision_history()), 7)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
59
    self.assertFalse(repo_b.has_revision(br_a.revision_history()[3]))
1393 by Robert Collins
reenable remotebranch tests
60
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
61
    # fetching the next revision up in sample data copies one revision
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
62
    br_b.fetch(br_a, br_a.revision_history()[3])
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
63
    self.assertTrue(repo_b.has_revision(br_a.revision_history()[3]))
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
64
    self.assertFalse(has_revision(br_a, br_b.revision_history()[6]))
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
65
    self.assertTrue(br_a.repository.has_revision(br_b.revision_history()[5]))
1393 by Robert Collins
reenable remotebranch tests
66
1092.2.28 by Robert Collins
reenable test of fetching a branch with ghosts
67
    # When a non-branch ancestor is missing, it should be unlisted...
1415 by Robert Collins
remove the ancestry weave file
68
    # as its not reference from the inventory weave.
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
69
    br_b4 = self.make_branch('br_4')
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
70
    br_b4.fetch(br_b)
1393 by Robert Collins
reenable remotebranch tests
71
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
72
    writable_a.fetch(br_b)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
73
    self.assertTrue(has_revision(br_a, br_b.revision_history()[3]))
74
    self.assertTrue(has_revision(br_a, br_b.revision_history()[4]))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
75
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
76
    br_b2 = self.make_branch('br_b2')
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
77
    br_b2.fetch(br_b)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
78
    self.assertTrue(has_revision(br_b2, br_b.revision_history()[4]))
79
    self.assertTrue(has_revision(br_b2, br_a.revision_history()[2]))
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
80
    self.assertFalse(has_revision(br_b2, br_a.revision_history()[3]))
1393 by Robert Collins
reenable remotebranch tests
81
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
82
    br_a2 = self.make_branch('br_a2')
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
83
    br_a2.fetch(br_a)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
84
    self.assertTrue(has_revision(br_a2, br_b.revision_history()[4]))
85
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[3]))
86
    self.assertTrue(has_revision(br_a2, br_a.revision_history()[2]))
1393 by Robert Collins
reenable remotebranch tests
87
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
88
    br_a3 = self.make_branch('br_a3')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
89
    # pulling a branch with no revisions grabs nothing, regardless of
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
90
    # whats in the inventory.
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
91
    br_a3.fetch(br_a2)
1393 by Robert Collins
reenable remotebranch tests
92
    for revno in range(4):
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
93
        self.assertFalse(
94
            br_a3.repository.has_revision(br_a.revision_history()[revno]))
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
95
    br_a3.fetch(br_a2, br_a.revision_history()[2])
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
96
    # pull the 3 revisions introduced by a@u-0-3
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
97
    br_a3.fetch(br_a2, br_a.revision_history()[3])
4316.1.1 by Jonathan Lange
Don't raise InstallFailed from fetch. Instead let the search_missing_revision_ids error bubble up.
98
    # NoSuchRevision should be raised if the branch is missing the revision
1393 by Robert Collins
reenable remotebranch tests
99
    # that was requested.
4316.1.1 by Jonathan Lange
Don't raise InstallFailed from fetch. Instead let the search_missing_revision_ids error bubble up.
100
    self.assertRaises(errors.NoSuchRevision, br_a3.fetch, br_a2, 'pizza')
2697.2.2 by Martin Pool
deprecate Branch.append_revision
101
2697.2.5 by Martin Pool
Kill off append_revision
102
    # TODO: Test trying to fetch from a branch that points to a revision not
103
    # actually present in its repository.  Not every branch format allows you
104
    # to directly point to such revisions, so it's a bit complicated to
105
    # construct.  One way would be to uncommit and gc the revision, but not
106
    # every branch supports that.  -- mbp 20070814
1638.1.2 by Robert Collins
Change the basis-inventory file to not have the revision-id in the file name.
107
1185.13.4 by Robert Collins
make reweave visible as a weave method, and quickly integrate into fetch
108
    #TODO: test that fetch correctly does reweaving when needed. RBC 20051008
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
109
    # Note that this means - updating the weave when ghosts are filled in to
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
110
    # add the right parents.
111
1185.13.4 by Robert Collins
make reweave visible as a weave method, and quickly integrate into fetch
112
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
113
class TestFetch(TestCaseWithTransport):
1392 by Robert Collins
reinstate testfetch test case
114
115
    def test_fetch(self):
1115 by Martin Pool
- split fetch tests into a separate file
116
        #highest indices a: 5, b: 7
2696.3.3 by Martin Pool
Start setting the default format to dirstate-tags
117
        br_a, br_b = make_branches(self, format='dirstate-tags')
1393 by Robert Collins
reenable remotebranch tests
118
        fetch_steps(self, br_a, br_b, br_a)
1404 by Robert Collins
only pull remote text weaves once per fetch operation
119
1558.4.11 by Aaron Bentley
Allow merge against self, make fetching self a noop
120
    def test_fetch_self(self):
121
        wt = self.make_branch_and_tree('br')
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
122
        wt.branch.fetch(wt.branch)
1558.4.11 by Aaron Bentley
Allow merge against self, make fetching self a noop
123
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
124
    def test_fetch_root_knit(self):
1551.8.43 by Aaron Bentley
Update from reviews
125
        """Ensure that knit2.fetch() updates the root knit
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
126
1551.8.43 by Aaron Bentley
Update from reviews
127
        This tests the case where the root has a new revision, but there are no
128
        corresponding filename, parent, contents or other changes.
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
129
        """
1551.8.43 by Aaron Bentley
Update from reviews
130
        knit1_format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
131
        knit1_format.repository_format = knitrepo.RepositoryFormatKnit1()
1551.8.43 by Aaron Bentley
Update from reviews
132
        knit2_format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
133
        knit2_format.repository_format = knitrepo.RepositoryFormatKnit3()
1551.8.43 by Aaron Bentley
Update from reviews
134
        # we start with a knit1 repository because that causes the
135
        # root revision to change for each commit, even though the content,
136
        # parent, name, and other attributes are unchanged.
137
        tree = self.make_branch_and_tree('tree', knit1_format)
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
138
        tree.set_root_id('tree-root')
139
        tree.commit('rev1', rev_id='rev1')
140
        tree.commit('rev2', rev_id='rev2')
1551.8.43 by Aaron Bentley
Update from reviews
141
142
        # Now we convert it to a knit2 repository so that it has a root knit
143
        Convert(tree.basedir, knit2_format)
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
144
        tree = WorkingTree.open(tree.basedir)
1551.8.43 by Aaron Bentley
Update from reviews
145
        branch = self.make_branch('branch', format=knit2_format)
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
146
        branch.pull(tree.branch, stop_revision='rev1')
147
        repo = branch.repository
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
148
        repo.lock_read()
149
        try:
150
            # Make sure fetch retrieved only what we requested
151
            self.assertEqual({('tree-root', 'rev1'):()},
152
                repo.texts.get_parent_map(
153
                    [('tree-root', 'rev1'), ('tree-root', 'rev2')]))
154
        finally:
155
            repo.unlock()
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
156
        branch.pull(tree.branch)
1551.8.43 by Aaron Bentley
Update from reviews
157
        # Make sure that the next revision in the root knit was retrieved,
158
        # even though the text, name, parent_id, etc., were unchanged.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
159
        repo.lock_read()
160
        try:
161
            # Make sure fetch retrieved only what we requested
162
            self.assertEqual({('tree-root', 'rev2'):(('tree-root', 'rev1'),)},
163
                repo.texts.get_parent_map([('tree-root', 'rev2')]))
164
        finally:
165
            repo.unlock()
1551.8.42 by Aaron Bentley
Ensure that fetch properly updates inventory root knit
166
2323.8.2 by Aaron Bentley
Give a nicer error on fetch when repos are in incompatible formats
167
    def test_fetch_incompatible(self):
168
        knit_tree = self.make_branch_and_tree('knit', format='knit')
169
        knit3_tree = self.make_branch_and_tree('knit3',
170
            format='dirstate-with-subtree')
171
        knit3_tree.commit('blah')
3582.1.2 by Martin Pool
Default InterRepository.fetch raises IncompatibleRepositories
172
        e = self.assertRaises(errors.IncompatibleRepositories,
173
                              knit_tree.branch.fetch, knit3_tree.branch)
174
        self.assertContainsRe(str(e),
175
            r"(?m).*/knit.*\nis not compatible with\n.*/knit3/.*\n"
176
            r"different rich-root support")
2323.8.2 by Aaron Bentley
Give a nicer error on fetch when repos are in incompatible formats
177
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
178
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
179
class TestMergeFetch(TestCaseWithTransport):
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
180
181
    def test_merge_fetches_unrelated(self):
182
        """Merge brings across history from unrelated source"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
183
        wt1 = self.make_branch_and_tree('br1')
184
        br1 = wt1.branch
185
        wt1.commit(message='rev 1-1', rev_id='1-1')
186
        wt1.commit(message='rev 1-2', rev_id='1-2')
187
        wt2 = self.make_branch_and_tree('br2')
188
        br2 = wt2.branch
189
        wt2.commit(message='rev 2-1', rev_id='2-1')
1551.15.70 by Aaron Bentley
Avoid using builtins.merge
190
        wt2.merge_from_branch(br1, from_revision='null:')
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
191
        self._check_revs_present(br2)
192
1185.16.94 by mbp at sourcefrog
New test that merge fetches revisions from source
193
    def test_merge_fetches(self):
194
        """Merge brings across history from source"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
195
        wt1 = self.make_branch_and_tree('br1')
196
        br1 = wt1.branch
197
        wt1.commit(message='rev 1-1', rev_id='1-1')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
198
        dir_2 = br1.bzrdir.sprout('br2')
199
        br2 = dir_2.open_branch()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
200
        wt1.commit(message='rev 1-2', rev_id='1-2')
1551.15.70 by Aaron Bentley
Avoid using builtins.merge
201
        wt2 = dir_2.open_workingtree()
202
        wt2.commit(message='rev 2-1', rev_id='2-1')
203
        wt2.merge_from_branch(br1)
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
204
        self._check_revs_present(br2)
205
206
    def _check_revs_present(self, br2):
1185.16.94 by mbp at sourcefrog
New test that merge fetches revisions from source
207
        for rev_id in '1-1', '1-2', '2-1':
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
208
            self.assertTrue(br2.repository.has_revision(rev_id))
209
            rev = br2.repository.get_revision(rev_id)
1185.16.94 by mbp at sourcefrog
New test that merge fetches revisions from source
210
            self.assertEqual(rev.revision_id, rev_id)
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
211
            self.assertTrue(br2.repository.get_inventory(rev_id))
1185.16.94 by mbp at sourcefrog
New test that merge fetches revisions from source
212
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
213
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
214
class TestMergeFileHistory(TestCaseWithTransport):
215
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
216
    def setUp(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
217
        super(TestMergeFileHistory, self).setUp()
218
        wt1 = self.make_branch_and_tree('br1')
219
        br1 = wt1.branch
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
220
        self.build_tree_contents([('br1/file', 'original contents\n')])
1534.4.28 by Robert Collins
first cut at merge from integration.
221
        wt1.add('file', 'this-file-id')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
222
        wt1.commit(message='rev 1-1', rev_id='1-1')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
223
        dir_2 = br1.bzrdir.sprout('br2')
224
        br2 = dir_2.open_branch()
225
        wt2 = dir_2.open_workingtree()
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
226
        self.build_tree_contents([('br1/file', 'original from 1\n')])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
227
        wt1.commit(message='rev 1-2', rev_id='1-2')
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
228
        self.build_tree_contents([('br1/file', 'agreement\n')])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
229
        wt1.commit(message='rev 1-3', rev_id='1-3')
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
230
        self.build_tree_contents([('br2/file', 'contents in 2\n')])
1534.4.28 by Robert Collins
first cut at merge from integration.
231
        wt2.commit(message='rev 2-1', rev_id='2-1')
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
232
        self.build_tree_contents([('br2/file', 'agreement\n')])
1534.4.28 by Robert Collins
first cut at merge from integration.
233
        wt2.commit(message='rev 2-2', rev_id='2-2')
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
234
235
    def test_merge_fetches_file_history(self):
236
        """Merge brings across file histories"""
237
        br2 = Branch.open('br2')
1551.15.70 by Aaron Bentley
Avoid using builtins.merge
238
        br1 = Branch.open('br1')
239
        wt2 = WorkingTree.open('br2').merge_from_branch(br1)
3010.1.4 by Robert Collins
Make the knit specific fetch tests knit specific, and lock the branch when looking at historical texts in test_fetch.
240
        br2.lock_read()
241
        self.addCleanup(br2.unlock)
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
242
        for rev_id, text in [('1-2', 'original from 1\n'),
243
                             ('1-3', 'agreement\n'),
244
                             ('2-1', 'contents in 2\n'),
245
                             ('2-2', 'agreement\n')]:
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
246
            self.assertEqualDiff(
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
247
                br2.repository.revision_tree(
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
248
                    rev_id).get_file_text('this-file-id'), text)
1185.16.96 by mbp at sourcefrog
More merge/fetch tests
249
250
1404 by Robert Collins
only pull remote text weaves once per fetch operation
251
class TestHttpFetch(TestCaseWithWebserver):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
252
    # FIXME RBC 20060124 this really isn't web specific, perhaps an
253
    # instrumented readonly transport? Can we do an instrumented
254
    # adapter and use self.get_readonly_url ?
1404 by Robert Collins
only pull remote text weaves once per fetch operation
255
256
    def test_fetch(self):
257
        #highest indices a: 5, b: 7
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
258
        br_a, br_b = make_branches(self)
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
259
        br_rem_a = Branch.open(self.get_readonly_url('branch1'))
1404 by Robert Collins
only pull remote text weaves once per fetch operation
260
        fetch_steps(self, br_rem_a, br_b, br_a)
261
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
262
    def _count_log_matches(self, target, logs):
263
        """Count the number of times the target file pattern was fetched in an http log"""
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
264
        get_succeeds_re = re.compile(
265
            '.*"GET .*%s HTTP/1.1" 20[06] - "-" "bzr/%s' %
266
            (     target,                    bzrlib.__version__))
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
267
        c = 0
268
        for line in logs:
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
269
            if get_succeeds_re.match(line):
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
270
                c += 1
271
        return c
272
1404 by Robert Collins
only pull remote text weaves once per fetch operation
273
    def test_weaves_are_retrieved_once(self):
274
        self.build_tree(("source/", "source/file", "target/"))
3010.1.4 by Robert Collins
Make the knit specific fetch tests knit specific, and lock the branch when looking at historical texts in test_fetch.
275
        # This test depends on knit dasta storage.
276
        wt = self.make_branch_and_tree('source', format='dirstate-tags')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
277
        branch = wt.branch
278
        wt.add(["file"], ["id"])
279
        wt.commit("added file")
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
280
        open("source/file", 'w').write("blah\n")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
281
        wt.commit("changed file")
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
282
        target = BzrDir.create_branch_and_repo("target/")
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
283
        source = Branch.open(self.get_readonly_url("source/"))
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
284
        target.fetch(source)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
285
        # this is the path to the literal file. As format changes
1430 by Robert Collins
touchup the prefixed-store patch
286
        # occur it needs to be updated. FIXME: ask the store for the
287
        # path.
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
288
        self.log("web server logs are:")
289
        http_logs = self.get_readonly_server().logs
290
        self.log('\n'.join(http_logs))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
291
        # unfortunately this log entry is branch format specific. We could
292
        # factor out the 'what files does this format use' to a method on the
1666.1.6 by Robert Collins
Make knit the default format.
293
        # repository, which would let us to this generically. RBC 20060419
3422.1.1 by John Arbash Meinel
merge in bzr-1.5rc1, revert the transaction cache change
294
        # RBC 20080408: Or perhaps we can assert that no files are fully read
295
        # twice?
1666.1.6 by Robert Collins
Make knit the default format.
296
        self.assertEqual(1, self._count_log_matches('/ce/id.kndx', http_logs))
297
        self.assertEqual(1, self._count_log_matches('/ce/id.knit', http_logs))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
298
        self.assertEqual(1, self._count_log_matches('inventory.kndx', http_logs))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
299
        # this r-h check test will prevent regressions, but it currently already
1417.1.12 by Robert Collins
cache revision history during read transactions
300
        # passes, before the patch to cache-rh is applied :[
2230.3.10 by Aaron Bentley
Genericised test_fetch to handle branch 6 retrieval patterns
301
        self.assertTrue(1 >= self._count_log_matches('revision-history',
302
                                                     http_logs))
303
        self.assertTrue(1 >= self._count_log_matches('last-revision',
304
                                                     http_logs))
1530.1.18 by Robert Collins
unbreak test_fetch
305
        # FIXME naughty poking in there.
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
306
        self.get_readonly_server().logs = []
3241.1.4 by Andrew Bennetts
Use get_smart_medium as suggested by Robert, and deal with the fallout.
307
        # check there is nothing more to fetch.  We take care to re-use the
308
        # existing transport so that the request logs we're about to examine
309
        # aren't cluttered with redundant probes for a smart server.
3241.1.5 by Andrew Bennetts
Add comment suggested by Robert.
310
        # XXX: Perhaps this further parameterisation: test http with smart
311
        # server, and test http without smart server?
3241.1.4 by Andrew Bennetts
Use get_smart_medium as suggested by Robert, and deal with the fallout.
312
        source = Branch.open(
313
            self.get_readonly_url("source/"),
314
            possible_transports=[source.bzrdir.root_transport])
4065.1.1 by Robert Collins
Change the return value of fetch() to None.
315
        target.fetch(source)
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
316
        # should make just two requests
317
        http_logs = self.get_readonly_server().logs
318
        self.log("web server logs are:")
319
        self.log('\n'.join(http_logs))
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
320
        self.assertEqual(1, self._count_log_matches('branch-format', http_logs))
321
        self.assertEqual(1, self._count_log_matches('branch/format', http_logs))
3422.1.1 by John Arbash Meinel
merge in bzr-1.5rc1, revert the transaction cache change
322
        self.assertEqual(1, self._count_log_matches('repository/format',
323
            http_logs))
4307.2.5 by Robert Collins
Remove too-early checks for revisions adding unnecessary round trips, at the cost of actually reading revision data when pulling (because we currently don't have a hint as about whats local for fetch).
324
        self.assertEqual(1, self._count_log_matches('revisions.kndx',
325
            http_logs))
2230.3.11 by Aaron Bentley
Fix line endings
326
        self.assertTrue(1 >= self._count_log_matches('revision-history',
327
                                                     http_logs))
328
        self.assertTrue(1 >= self._count_log_matches('last-revision',
329
                                                     http_logs))
4307.2.5 by Robert Collins
Remove too-early checks for revisions adding unnecessary round trips, at the cost of actually reading revision data when pulling (because we currently don't have a hint as about whats local for fetch).
330
        self.assertLength(5, http_logs)
3380.1.1 by Aaron Bentley
Fix inventory insertion to work in topological order
331
332
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
333
class TestKnitToPackFetch(TestCaseWithTransport):
334
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
335
    def find_get_record_stream(self, calls, expected_count=1):
336
        """In a list of calls, find the last 'get_record_stream'.
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
337
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
338
        :param expected_count: The number of calls we should exepect to find.
339
            If a different number is found, an assertion is raised.
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
340
        """
341
        get_record_call = None
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
342
        call_count = 0
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
343
        for call in calls:
344
            if call[0] == 'get_record_stream':
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
345
                call_count += 1
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
346
                get_record_call = call
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
347
        self.assertEqual(expected_count, call_count)
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
348
        return get_record_call
349
350
    def test_fetch_with_deltas_no_delta_closure(self):
351
        tree = self.make_branch_and_tree('source', format='dirstate')
352
        target = self.make_repository('target', format='pack-0.92')
353
        self.build_tree(['source/file'])
354
        tree.set_root_id('root-id')
355
        tree.add('file', 'file-id')
356
        tree.commit('one', rev_id='rev-one')
357
        source = tree.branch.repository
358
        source.texts = versionedfile.RecordingVersionedFilesDecorator(
359
                        source.texts)
360
        source.signatures = versionedfile.RecordingVersionedFilesDecorator(
361
                        source.signatures)
362
        source.revisions = versionedfile.RecordingVersionedFilesDecorator(
363
                        source.revisions)
364
        source.inventories = versionedfile.RecordingVersionedFilesDecorator(
365
                        source.inventories)
366
        # precondition
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
367
        self.assertTrue(target._format._fetch_uses_deltas)
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
368
        target.fetch(source, revision_id='rev-one')
369
        self.assertEqual(('get_record_stream', [('file-id', 'rev-one')],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
370
                          target._format._fetch_order, False),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
371
                         self.find_get_record_stream(source.texts.calls))
372
        self.assertEqual(('get_record_stream', [('rev-one',)],
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
373
          target._format._fetch_order, False),
374
          self.find_get_record_stream(source.inventories.calls, 2))
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
375
        self.assertEqual(('get_record_stream', [('rev-one',)],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
376
                          target._format._fetch_order, False),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
377
                         self.find_get_record_stream(source.revisions.calls))
378
        # XXX: Signatures is special, and slightly broken. The
379
        # standard item_keys_introduced_by actually does a lookup for every
380
        # signature to see if it exists, rather than waiting to do them all at
381
        # once at the end. The fetch code then does an all-at-once and just
382
        # allows for some of them to be missing.
383
        # So we know there will be extra calls, but the *last* one is the one
384
        # we care about.
385
        signature_calls = source.signatures.calls[-1:]
386
        self.assertEqual(('get_record_stream', [('rev-one',)],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
387
                          target._format._fetch_order, False),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
388
                         self.find_get_record_stream(signature_calls))
389
390
    def test_fetch_no_deltas_with_delta_closure(self):
391
        tree = self.make_branch_and_tree('source', format='dirstate')
392
        target = self.make_repository('target', format='pack-0.92')
393
        self.build_tree(['source/file'])
394
        tree.set_root_id('root-id')
395
        tree.add('file', 'file-id')
396
        tree.commit('one', rev_id='rev-one')
397
        source = tree.branch.repository
398
        source.texts = versionedfile.RecordingVersionedFilesDecorator(
399
                        source.texts)
400
        source.signatures = versionedfile.RecordingVersionedFilesDecorator(
401
                        source.signatures)
402
        source.revisions = versionedfile.RecordingVersionedFilesDecorator(
403
                        source.revisions)
404
        source.inventories = versionedfile.RecordingVersionedFilesDecorator(
405
                        source.inventories)
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
406
        # XXX: This won't work in general, but for the dirstate format it does.
407
        old_fetch_uses_deltas_setting = target._format._fetch_uses_deltas
408
        def restore():
409
            target._format._fetch_uses_deltas = old_fetch_uses_deltas_setting
410
        self.addCleanup(restore)
411
        target._format._fetch_uses_deltas = False
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
412
        target.fetch(source, revision_id='rev-one')
413
        self.assertEqual(('get_record_stream', [('file-id', 'rev-one')],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
414
                          target._format._fetch_order, True),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
415
                         self.find_get_record_stream(source.texts.calls))
416
        self.assertEqual(('get_record_stream', [('rev-one',)],
4098.4.3 by Robert Collins
Change fetch effort tests to reflect the new change to read the adjacent inventories to ensure accurate fetching.
417
            target._format._fetch_order, True),
418
            self.find_get_record_stream(source.inventories.calls, 2))
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
419
        self.assertEqual(('get_record_stream', [('rev-one',)],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
420
                          target._format._fetch_order, True),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
421
                         self.find_get_record_stream(source.revisions.calls))
422
        # XXX: Signatures is special, and slightly broken. The
423
        # standard item_keys_introduced_by actually does a lookup for every
424
        # signature to see if it exists, rather than waiting to do them all at
425
        # once at the end. The fetch code then does an all-at-once and just
426
        # allows for some of them to be missing.
427
        # So we know there will be extra calls, but the *last* one is the one
428
        # we care about.
429
        signature_calls = source.signatures.calls[-1:]
430
        self.assertEqual(('get_record_stream', [('rev-one',)],
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
431
                          target._format._fetch_order, True),
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
432
                         self.find_get_record_stream(signature_calls))
433
3849.3.1 by John Arbash Meinel
Part of bug #300289, stop requiring plain fulltexts for revisions.
434
    def test_fetch_revisions_with_deltas_into_pack(self):
435
        # See BUG #261339, dev versions of bzr could accidentally create deltas
436
        # in revision texts in knit branches (when fetching from packs). So we
437
        # ensure that *if* a knit repository has a delta in revisions, that it
438
        # gets properly expanded back into a fulltext when stored in the pack
439
        # file.
440
        tree = self.make_branch_and_tree('source', format='dirstate')
441
        target = self.make_repository('target', format='pack-0.92')
442
        self.build_tree(['source/file'])
443
        tree.set_root_id('root-id')
444
        tree.add('file', 'file-id')
445
        tree.commit('one', rev_id='rev-one')
446
        # Hack the KVF for revisions so that it "accidentally" allows a delta
447
        tree.branch.repository.revisions._max_delta_chain = 200
448
        tree.commit('two', rev_id='rev-two')
449
        source = tree.branch.repository
450
        # Ensure that we stored a delta
451
        source.lock_read()
452
        self.addCleanup(source.unlock)
453
        record = source.revisions.get_record_stream([('rev-two',)],
454
            'unordered', False).next()
455
        self.assertEqual('knit-delta-gz', record.storage_kind)
456
        target.fetch(tree.branch.repository, revision_id='rev-two')
457
        # The record should get expanded back to a fulltext
458
        target.lock_read()
459
        self.addCleanup(target.unlock)
460
        record = target.revisions.get_record_stream([('rev-two',)],
461
            'unordered', False).next()
462
        self.assertEqual('knit-ft-gz', record.storage_kind)
463
3871.4.2 by John Arbash Meinel
Finally a test case that reproduces bug #304841
464
    def test_fetch_with_fallback_and_merge(self):
465
        builder = self.make_branch_builder('source', format='pack-0.92')
466
        builder.start_series()
467
        # graph
468
        #   A
469
        #   |\
470
        #   B C
471
        #   | |
472
        #   | D
473
        #   | |
474
        #   | E
475
        #    \|
476
        #     F
477
        # A & B are present in the base (stacked-on) repository, A-E are
478
        # present in the source.
3871.4.4 by John Arbash Meinel
Another fix for bug #304841. As a broad-spectrum solution,
479
        # This reproduces bug #304841
3871.4.2 by John Arbash Meinel
Finally a test case that reproduces bug #304841
480
        # We need a large enough inventory that total size of compressed deltas
481
        # is shorter than the size of a compressed fulltext. We have to use
482
        # random ids because otherwise the inventory fulltext compresses too
483
        # well and the deltas get bigger.
484
        to_add = [
485
            ('add', ('', 'TREE_ROOT', 'directory', None))]
486
        for i in xrange(10):
487
            fname = 'file%03d' % (i,)
488
            fileid = '%s-%s' % (fname, osutils.rand_chars(64))
489
            to_add.append(('add', (fname, fileid, 'file', 'content\n')))
490
        builder.build_snapshot('A', None, to_add)
491
        builder.build_snapshot('B', ['A'], [])
492
        builder.build_snapshot('C', ['A'], [])
493
        builder.build_snapshot('D', ['C'], [])
494
        builder.build_snapshot('E', ['D'], [])
495
        builder.build_snapshot('F', ['E', 'B'], [])
496
        builder.finish_series()
497
        source_branch = builder.get_branch()
498
        source_branch.bzrdir.sprout('base', revision_id='B')
499
        target_branch = self.make_branch('target', format='1.6')
500
        target_branch.set_stacked_on_url('../base')
501
        source = source_branch.repository
502
        source.lock_read()
503
        self.addCleanup(source.unlock)
504
        source.inventories = versionedfile.OrderingVersionedFilesDecorator(
505
                        source.inventories,
506
                        key_priority={('E',): 1, ('D',): 2, ('C',): 4,
507
                                      ('F',): 3})
508
        # Ensure that the content is yielded in the proper order, and given as
509
        # the expected kinds
510
        records = [(record.key, record.storage_kind)
511
                   for record in source.inventories.get_record_stream(
512
                        [('D',), ('C',), ('E',), ('F',)], 'unordered', False)]
513
        self.assertEqual([(('E',), 'knit-delta-gz'), (('D',), 'knit-delta-gz'),
514
                          (('F',), 'knit-delta-gz'), (('C',), 'knit-delta-gz')],
515
                          records)
516
517
        target_branch.lock_write()
518
        self.addCleanup(target_branch.unlock)
519
        target = target_branch.repository
520
        target.fetch(source, revision_id='F')
521
        # 'C' should be expanded to a fulltext, but D and E should still be
522
        # deltas
523
        stream = target.inventories.get_record_stream(
524
            [('C',), ('D',), ('E',), ('F',)],
525
            'unordered', False)
526
        kinds = dict((record.key, record.storage_kind) for record in stream)
527
        self.assertEqual({('C',): 'knit-ft-gz', ('D',): 'knit-delta-gz',
528
                          ('E',): 'knit-delta-gz', ('F',): 'knit-delta-gz'},
529
                         kinds)
3849.3.1 by John Arbash Meinel
Part of bug #300289, stop requiring plain fulltexts for revisions.
530
3606.7.7 by John Arbash Meinel
Add tests for the fetching behavior.
531
3380.1.1 by Aaron Bentley
Fix inventory insertion to work in topological order
532
class Test1To2Fetch(TestCaseWithTransport):
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
533
    """Tests for Model1To2 failure modes"""
3380.1.1 by Aaron Bentley
Fix inventory insertion to work in topological order
534
3380.2.4 by Aaron Bentley
Updates from review
535
    def make_tree_and_repo(self):
536
        self.tree = self.make_branch_and_tree('tree', format='pack-0.92')
537
        self.repo = self.make_repository('rich-repo', format='rich-root-pack')
538
        self.repo.lock_write()
539
        self.addCleanup(self.repo.unlock)
540
541
    def do_fetch_order_test(self, first, second):
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
542
        """Test that fetch works no matter what the set order of revision is.
3380.1.1 by Aaron Bentley
Fix inventory insertion to work in topological order
543
544
        This test depends on the order of items in a set, which is
545
        implementation-dependant, so we test A, B and then B, A.
546
        """
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
547
        self.make_tree_and_repo()
548
        self.tree.commit('Commit 1', rev_id=first)
549
        self.tree.commit('Commit 2', rev_id=second)
550
        self.repo.fetch(self.tree.branch.repository, second)
551
3380.2.4 by Aaron Bentley
Updates from review
552
    def test_fetch_order_AB(self):
3380.2.7 by Aaron Bentley
Update docs
553
        """See do_fetch_order_test"""
3380.2.4 by Aaron Bentley
Updates from review
554
        self.do_fetch_order_test('A', 'B')
555
556
    def test_fetch_order_BA(self):
3380.2.7 by Aaron Bentley
Update docs
557
        """See do_fetch_order_test"""
3380.2.4 by Aaron Bentley
Updates from review
558
        self.do_fetch_order_test('B', 'A')
559
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
560
    def get_parents(self, file_id, revision_id):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
561
        self.repo.lock_read()
562
        try:
563
            parent_map = self.repo.texts.get_parent_map([(file_id, revision_id)])
564
            return parent_map[(file_id, revision_id)]
565
        finally:
566
            self.repo.unlock()
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
567
3380.1.2 by Aaron Bentley
Improve handling ghosts and changing root_ids
568
    def test_fetch_ghosts(self):
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
569
        self.make_tree_and_repo()
570
        self.tree.commit('first commit', rev_id='left-parent')
571
        self.tree.add_parent_tree_id('ghost-parent')
572
        fork = self.tree.bzrdir.sprout('fork', 'null:').open_workingtree()
3380.1.2 by Aaron Bentley
Improve handling ghosts and changing root_ids
573
        fork.commit('not a ghost', rev_id='not-ghost-parent')
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
574
        self.tree.branch.repository.fetch(fork.branch.repository,
3380.1.2 by Aaron Bentley
Improve handling ghosts and changing root_ids
575
                                     'not-ghost-parent')
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
576
        self.tree.add_parent_tree_id('not-ghost-parent')
577
        self.tree.commit('second commit', rev_id='second-id')
578
        self.repo.fetch(self.tree.branch.repository, 'second-id')
579
        root_id = self.tree.get_root_id()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
580
        self.assertEqual(
4324.3.4 by Robert Collins
Update static rich root test to support new, reconcile-compatible algorithm.
581
            ((root_id, 'left-parent'), (root_id, 'not-ghost-parent')),
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
582
            self.get_parents(root_id, 'second-id'))
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
583
584
    def make_two_commits(self, change_root, fetch_twice):
585
        self.make_tree_and_repo()
586
        self.tree.commit('first commit', rev_id='first-id')
587
        if change_root:
588
            self.tree.set_root_id('unique-id')
589
        self.tree.commit('second commit', rev_id='second-id')
590
        if fetch_twice:
591
            self.repo.fetch(self.tree.branch.repository, 'first-id')
592
        self.repo.fetch(self.tree.branch.repository, 'second-id')
3380.1.2 by Aaron Bentley
Improve handling ghosts and changing root_ids
593
594
    def test_fetch_changed_root(self):
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
595
        self.make_two_commits(change_root=True, fetch_twice=False)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
596
        self.assertEqual((), self.get_parents('unique-id', 'second-id'))
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
597
598
    def test_two_fetch_changed_root(self):
599
        self.make_two_commits(change_root=True, fetch_twice=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
600
        self.assertEqual((), self.get_parents('unique-id', 'second-id'))
3380.1.3 by Aaron Bentley
Fix model-change fetching with ghosts and when fetch is resumed
601
602
    def test_two_fetches(self):
603
        self.make_two_commits(change_root=False, fetch_twice=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
604
        self.assertEqual((('TREE_ROOT', 'first-id'),),
605
            self.get_parents('TREE_ROOT', 'second-id'))