~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/branch_implementations/test_stacking.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008-2012, 2016 Canonical Ltd
 
1
# Copyright (C) 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
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
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Tests for Branch.get_stacked_on_url and set_stacked_on_url."""
18
18
 
19
19
from bzrlib import (
20
 
    branch,
21
 
    controldir,
22
 
    check,
 
20
    bzrdir,
23
21
    errors,
24
22
    )
25
23
from bzrlib.revision import NULL_REVISION
26
 
from bzrlib.tests import fixtures, TestNotApplicable, transport_util
27
 
from bzrlib.tests.per_branch import TestCaseWithBranch
28
 
 
29
 
 
30
 
unstackable_format_errors = (
31
 
    errors.UnstackableBranchFormat,
32
 
    errors.UnstackableRepositoryFormat,
33
 
    )
 
24
from bzrlib.tests import TestNotApplicable, KnownFailure
 
25
from bzrlib.tests.branch_implementations import TestCaseWithBranch
34
26
 
35
27
 
36
28
class TestStacking(TestCaseWithBranch):
37
29
 
38
 
    def check_lines_added_or_present(self, stacked_branch, revid):
39
 
        # similar to a failure seen in bug 288751 by mbp 20081120
40
 
        stacked_repo = stacked_branch.repository
41
 
        stacked_repo.lock_read()
42
 
        try:
43
 
            list(stacked_repo.inventories.iter_lines_added_or_present_in_keys(
44
 
                    [(revid,)]))
45
 
        finally:
46
 
            stacked_repo.unlock()
47
 
 
48
30
    def test_get_set_stacked_on_url(self):
49
31
        # branches must either:
50
32
        # raise UnstackableBranchFormat or
52
34
        # permit stacking to be done and then return the stacked location.
53
35
        branch = self.make_branch('branch')
54
36
        target = self.make_branch('target')
 
37
        old_format_errors = (
 
38
            errors.UnstackableBranchFormat,
 
39
            errors.UnstackableRepositoryFormat,
 
40
            )
55
41
        try:
56
42
            branch.set_stacked_on_url(target.base)
57
 
        except unstackable_format_errors:
 
43
        except old_format_errors:
58
44
            # if the set failed, so must the get
59
 
            self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
60
 
            self.assertFalse(branch._format.supports_stacking())
 
45
            self.assertRaises(old_format_errors, branch.get_stacked_on_url)
61
46
            return
62
 
        self.assertTrue(branch._format.supports_stacking())
63
47
        # now we have a stacked branch:
64
48
        self.assertEqual(target.base, branch.get_stacked_on_url())
65
49
        branch.set_stacked_on_url(None)
69
53
        # Branches can be stacked on other branches using relative paths.
70
54
        branch = self.make_branch('branch')
71
55
        target = self.make_branch('target')
72
 
        try:
73
 
            branch.set_stacked_on_url('../target')
74
 
        except unstackable_format_errors:
75
 
            # if the set failed, so must the get
76
 
            self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
77
 
            return
78
 
        self.assertEqual('../target', branch.get_stacked_on_url())
79
 
 
80
 
    def test_set_stacked_on_same_branch_raises(self):
81
 
        # Stacking on the same branch silently raises and doesn't execute the
82
 
        # change. Reported in bug 376243.
83
 
        branch = self.make_branch('branch')
84
 
        try:
85
 
            self.assertRaises(errors.UnstackableLocationError,
86
 
                branch.set_stacked_on_url, '../branch')
87
 
        except unstackable_format_errors:
88
 
            # if the set failed, so must the get
89
 
            self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
90
 
            return
91
 
        self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
92
 
 
93
 
    def test_set_stacked_on_same_branch_after_being_stacked_raises(self):
94
 
        # Stacking on the same branch silently raises and doesn't execute the
95
 
        # change.
96
 
        branch = self.make_branch('branch')
97
 
        target = self.make_branch('target')
98
 
        try:
99
 
            branch.set_stacked_on_url('../target')
100
 
        except unstackable_format_errors:
101
 
            # if the set failed, so must the get
102
 
            self.assertRaises(unstackable_format_errors, branch.get_stacked_on_url)
103
 
            return
104
 
        self.assertRaises(errors.UnstackableLocationError,
105
 
            branch.set_stacked_on_url, '../branch')
 
56
        old_format_errors = (
 
57
            errors.UnstackableBranchFormat,
 
58
            errors.UnstackableRepositoryFormat,
 
59
            )
 
60
        try:
 
61
            branch.set_stacked_on_url('../target')
 
62
        except old_format_errors:
 
63
            # if the set failed, so must the get
 
64
            self.assertRaises(old_format_errors, branch.get_stacked_on_url)
 
65
            return
106
66
        self.assertEqual('../target', branch.get_stacked_on_url())
107
67
 
108
68
    def assertRevisionInRepository(self, repo_path, revid):
109
69
        """Check that a revision is in a repository, disregarding stacking."""
110
 
        repo = controldir.ControlDir.open(repo_path).open_repository()
 
70
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
111
71
        self.assertTrue(repo.has_revision(revid))
112
72
 
113
73
    def assertRevisionNotInRepository(self, repo_path, revid):
114
74
        """Check that a revision is not in a repository, disregarding stacking."""
115
 
        repo = controldir.ControlDir.open(repo_path).open_repository()
 
75
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
116
76
        self.assertFalse(repo.has_revision(revid))
117
77
 
118
78
    def test_get_graph_stacked(self):
125
85
        new_branch = self.make_branch('new_branch')
126
86
        try:
127
87
            new_branch.set_stacked_on_url(trunk_tree.branch.base)
128
 
        except unstackable_format_errors, e:
 
88
        except (errors.UnstackableBranchFormat,
 
89
            errors.UnstackableRepositoryFormat), e:
129
90
            raise TestNotApplicable(e)
130
91
        # reading the graph from the stacked branch's repository should see
131
92
        # data from the stacked-on branch
144
105
        # and make branch from it which is stacked
145
106
        try:
146
107
            new_dir = trunk_tree.bzrdir.sprout('newbranch', stacked=True)
147
 
        except unstackable_format_errors, e:
148
 
            raise TestNotApplicable(e)
149
 
        # stacked repository
150
 
        self.assertRevisionNotInRepository('newbranch', trunk_revid)
151
 
        tree = new_dir.open_branch().create_checkout('local')
152
 
        new_branch_revid = tree.commit('something local')
153
 
        self.assertRevisionNotInRepository(
154
 
            trunk_tree.branch.base, new_branch_revid)
155
 
        self.assertRevisionInRepository('newbranch', new_branch_revid)
156
 
 
157
 
    def test_sprout_stacked_from_smart_server(self):
158
 
        # We have a mainline
159
 
        trunk_tree = self.make_branch_and_tree('mainline')
160
 
        trunk_revid = trunk_tree.commit('mainline')
161
 
        # Make sure that we can make a stacked branch from it
162
 
        try:
163
 
            trunk_tree.bzrdir.sprout('testbranch', stacked=True)
164
 
        except unstackable_format_errors, e:
165
 
            raise TestNotApplicable(e)
166
 
        # Now serve the original mainline from a smart server
167
 
        remote_transport = self.make_smart_server('mainline')
168
 
        remote_bzrdir = controldir.ControlDir.open_from_transport(remote_transport)
169
 
        # and make branch from the smart server which is stacked
170
 
        new_dir = remote_bzrdir.sprout('newbranch', stacked=True)
171
 
        # stacked repository
172
 
        self.assertRevisionNotInRepository('newbranch', trunk_revid)
173
 
        tree = new_dir.open_branch().create_checkout('local')
174
 
        new_branch_revid = tree.commit('something local')
175
 
        self.assertRevisionNotInRepository(trunk_tree.branch.user_url,
176
 
            new_branch_revid)
 
108
        except (errors.UnstackableBranchFormat,
 
109
            errors.UnstackableRepositoryFormat), e:
 
110
            raise TestNotApplicable(e)
 
111
        # stacked repository
 
112
        self.assertRevisionNotInRepository('newbranch', trunk_revid)
 
113
        new_tree = new_dir.open_workingtree()
 
114
        new_branch_revid = new_tree.commit('something local')
 
115
        self.assertRevisionNotInRepository('mainline', new_branch_revid)
177
116
        self.assertRevisionInRepository('newbranch', new_branch_revid)
178
117
 
179
118
    def test_unstack_fetches(self):
180
119
        """Removing the stacked-on branch pulls across all data"""
181
 
        try:
182
 
            builder = self.make_branch_builder('trunk')
183
 
        except errors.UninitializableFormat:
184
 
            raise TestNotApplicable('uninitializeable format')
185
120
        # We have a mainline
186
 
        trunk = fixtures.build_branch_with_non_ancestral_rev(builder)
187
 
        mainline_revid = 'rev-1'
188
 
        # and make branch from it which is stacked (with no tags)
 
121
        trunk_tree = self.make_branch_and_tree('mainline')
 
122
        trunk_revid = trunk_tree.commit('revision on mainline')
 
123
        # and make branch from it which is stacked
189
124
        try:
190
 
            new_dir = trunk.bzrdir.sprout(self.get_url('newbranch'), stacked=True)
191
 
        except unstackable_format_errors, e:
 
125
            new_dir = trunk_tree.bzrdir.sprout('newbranch', stacked=True)
 
126
        except (errors.UnstackableBranchFormat,
 
127
            errors.UnstackableRepositoryFormat), e:
192
128
            raise TestNotApplicable(e)
193
129
        # stacked repository
194
 
        self.assertRevisionNotInRepository('newbranch', mainline_revid)
195
 
        # TODO: we'd like to commit in the stacked repository; that requires
196
 
        # some care (maybe a BranchBuilder) if it's remote and has no
197
 
        # workingtree
198
 
        ##newbranch_revid = new_dir.open_workingtree().commit('revision in '
199
 
            ##'newbranch')
 
130
        self.assertRevisionNotInRepository('newbranch', trunk_revid)
200
131
        # now when we unstack that should implicitly fetch, to make sure that
201
132
        # the branch will still work
202
133
        new_branch = new_dir.open_branch()
203
 
        try:
204
 
            new_branch.tags.set_tag('tag-a', 'rev-2')
205
 
        except errors.TagsNotSupported:
206
 
            tags_supported = False
207
 
        else:
208
 
            tags_supported = True
209
134
        new_branch.set_stacked_on_url(None)
210
 
        self.assertRevisionInRepository('newbranch', mainline_revid)
 
135
        self.assertRevisionInRepository('newbranch', trunk_revid)
211
136
        # of course it's still in the mainline
212
 
        self.assertRevisionInRepository('trunk', mainline_revid)
213
 
        if tags_supported:
214
 
            # the tagged revision in trunk is now in newbranch too
215
 
            self.assertRevisionInRepository('newbranch', 'rev-2')
 
137
        self.assertRevisionInRepository('mainline', trunk_revid)
216
138
        # and now we're no longer stacked
217
 
        self.assertRaises(errors.NotStacked, new_branch.get_stacked_on_url)
218
 
 
219
 
    def test_unstack_already_locked(self):
220
 
        """Removing the stacked-on branch with an already write-locked branch
221
 
        works.
222
 
 
223
 
        This was bug 551525.
224
 
        """
225
 
        try:
226
 
            stacked_bzrdir = self.make_stacked_bzrdir()
227
 
        except unstackable_format_errors, e:
228
 
            raise TestNotApplicable(e)
229
 
        stacked_branch = stacked_bzrdir.open_branch()
230
 
        stacked_branch.lock_write()
231
 
        stacked_branch.set_stacked_on_url(None)
232
 
        stacked_branch.unlock()
233
 
 
234
 
    def test_unstack_already_multiple_locked(self):
235
 
        """Unstacking a branch preserves the lock count (even though it
236
 
        replaces the br.repository object).
237
 
 
238
 
        This is a more extreme variation of test_unstack_already_locked.
239
 
        """
240
 
        try:
241
 
            stacked_bzrdir = self.make_stacked_bzrdir()
242
 
        except unstackable_format_errors, e:
243
 
            raise TestNotApplicable(e)
244
 
        stacked_branch = stacked_bzrdir.open_branch()
245
 
        stacked_branch.lock_write()
246
 
        stacked_branch.lock_write()
247
 
        stacked_branch.lock_write()
248
 
        stacked_branch.set_stacked_on_url(None)
249
 
        stacked_branch.unlock()
250
 
        stacked_branch.unlock()
251
 
        stacked_branch.unlock()
 
139
        self.assertRaises(errors.NotStacked,
 
140
            new_branch.get_stacked_on_url)
252
141
 
253
142
    def make_stacked_bzrdir(self, in_directory=None):
254
143
        """Create a stacked branch and return its bzrdir.
265
154
        tree = self.make_branch_and_tree(prefix + 'stacked-on')
266
155
        tree.commit('Added foo')
267
156
        stacked_bzrdir = tree.branch.bzrdir.sprout(
268
 
            self.get_url(prefix + 'stacked'), tree.branch.last_revision(),
269
 
            stacked=True)
 
157
            prefix + 'stacked', tree.branch.last_revision(), stacked=True)
270
158
        return stacked_bzrdir
271
159
 
272
160
    def test_clone_from_stacked_branch_preserve_stacking(self):
275
163
        # same branch as the original.
276
164
        try:
277
165
            stacked_bzrdir = self.make_stacked_bzrdir()
278
 
        except unstackable_format_errors, e:
 
166
        except (errors.UnstackableBranchFormat,
 
167
                errors.UnstackableRepositoryFormat), e:
 
168
            # not a testable combination.
279
169
            raise TestNotApplicable(e)
280
170
        cloned_bzrdir = stacked_bzrdir.clone('cloned', preserve_stacking=True)
281
171
        try:
282
172
            self.assertEqual(
283
173
                stacked_bzrdir.open_branch().get_stacked_on_url(),
284
174
                cloned_bzrdir.open_branch().get_stacked_on_url())
285
 
        except unstackable_format_errors, e:
 
175
        except (errors.UnstackableBranchFormat,
 
176
                errors.UnstackableRepositoryFormat):
286
177
            pass
287
178
 
288
179
    def test_clone_from_branch_stacked_on_relative_url_preserve_stacking(self):
291
182
        # on an appropriately adjusted relative url.
292
183
        try:
293
184
            stacked_bzrdir = self.make_stacked_bzrdir(in_directory='dir')
294
 
        except unstackable_format_errors, e:
 
185
        except (errors.UnstackableBranchFormat,
 
186
                errors.UnstackableRepositoryFormat), e:
 
187
            # not a testable combination.
295
188
            raise TestNotApplicable(e)
296
189
        stacked_bzrdir.open_branch().set_stacked_on_url('../stacked-on')
297
 
        cloned_bzrdir = stacked_bzrdir.clone(
298
 
            self.get_url('cloned'), preserve_stacking=True)
 
190
        cloned_bzrdir = stacked_bzrdir.clone('cloned', preserve_stacking=True)
299
191
        self.assertEqual(
300
192
            '../dir/stacked-on',
301
193
            cloned_bzrdir.open_branch().get_stacked_on_url())
303
195
    def test_clone_from_stacked_branch_no_preserve_stacking(self):
304
196
        try:
305
197
            stacked_bzrdir = self.make_stacked_bzrdir()
306
 
        except unstackable_format_errors, e:
 
198
        except (errors.UnstackableBranchFormat,
 
199
                errors.UnstackableRepositoryFormat), e:
307
200
            # not a testable combination.
308
201
            raise TestNotApplicable(e)
309
202
        cloned_unstacked_bzrdir = stacked_bzrdir.clone('cloned-unstacked',
319
212
        self.assertRaises((errors.NotStacked, errors.UnstackableBranchFormat),
320
213
                          cloned_bzrdir.open_branch().get_stacked_on_url)
321
214
 
322
 
    def make_stacked_on_matching(self, source):
323
 
        if source.repository.supports_rich_root():
324
 
            if source.repository._format.supports_chks:
325
 
                format = "2a"
326
 
            else:
327
 
                format = "1.9-rich-root"
328
 
        else:
329
 
            format = "1.9"
330
 
        return self.make_branch('stack-on', format)
331
 
 
332
215
    def test_sprout_stacking_policy_handling(self):
333
216
        """Obey policy where possible, ignore otherwise."""
334
 
        if self.bzrdir_format.fixed_components:
335
 
            raise TestNotApplicable('Branch format 4 does not autoupgrade.')
336
 
        source = self.make_branch('source')
337
 
        stack_on = self.make_stacked_on_matching(source)
 
217
        stack_on = self.make_branch('stack-on')
338
218
        parent_bzrdir = self.make_bzrdir('.', format='default')
339
219
        parent_bzrdir.get_config().set_default_stack_on('stack-on')
 
220
        source = self.make_branch('source')
340
221
        target = source.bzrdir.sprout('target').open_branch()
341
 
        # When we sprout we upgrade the branch when there is a default stack_on
342
 
        # set by a config *and* the targeted branch supports stacking.
343
 
        if stack_on._format.supports_stacking():
 
222
        try:
344
223
            self.assertEqual('../stack-on', target.get_stacked_on_url())
345
 
        else:
346
 
            self.assertRaises(
347
 
                errors.UnstackableBranchFormat, target.get_stacked_on_url)
 
224
        except errors.UnstackableBranchFormat:
 
225
            pass
348
226
 
349
227
    def test_clone_stacking_policy_handling(self):
350
228
        """Obey policy where possible, ignore otherwise."""
351
 
        if self.bzrdir_format.fixed_components:
352
 
            raise TestNotApplicable('Branch format 4 does not autoupgrade.')
353
 
        source = self.make_branch('source')
354
 
        stack_on = self.make_stacked_on_matching(source)
 
229
        stack_on = self.make_branch('stack-on')
355
230
        parent_bzrdir = self.make_bzrdir('.', format='default')
356
231
        parent_bzrdir.get_config().set_default_stack_on('stack-on')
 
232
        source = self.make_branch('source')
357
233
        target = source.bzrdir.clone('target').open_branch()
358
 
        # When we clone we upgrade the branch when there is a default stack_on
359
 
        # set by a config *and* the targeted branch supports stacking.
360
 
        if stack_on._format.supports_stacking():
361
 
            self.assertEqual('../stack-on', target.get_stacked_on_url())
362
 
        else:
363
 
            self.assertRaises(
364
 
                errors.UnstackableBranchFormat, target.get_stacked_on_url)
365
 
 
366
 
    def test_sprout_to_smart_server_stacking_policy_handling(self):
367
 
        """Obey policy where possible, ignore otherwise."""
368
 
        if not self.branch_format.supports_leaving_lock():
369
 
            raise TestNotApplicable('Branch format is not usable via HPSS.')
370
 
        source = self.make_branch('source')
371
 
        stack_on = self.make_stacked_on_matching(source)
372
 
        parent_bzrdir = self.make_bzrdir('.', format='default')
373
 
        parent_bzrdir.get_config().set_default_stack_on('stack-on')
374
 
        url = self.make_smart_server('target').base
375
 
        target = source.bzrdir.sprout(url).open_branch()
376
 
        # When we sprout we upgrade the branch when there is a default stack_on
377
 
        # set by a config *and* the targeted branch supports stacking.
378
 
        if stack_on._format.supports_stacking():
379
 
            self.assertEqual('../stack-on', target.get_stacked_on_url())
380
 
        else:
381
 
            self.assertRaises(
382
 
                errors.UnstackableBranchFormat, target.get_stacked_on_url)
 
234
        try:
 
235
            self.assertEqual('../stack-on', target.get_stacked_on_url())
 
236
        except errors.UnstackableBranchFormat:
 
237
            pass
383
238
 
384
239
    def prepare_stacked_on_fetch(self):
385
240
        stack_on = self.make_branch_and_tree('stack-on')
386
241
        stack_on.commit('first commit', rev_id='rev1')
387
242
        try:
388
243
            stacked_dir = stack_on.bzrdir.sprout('stacked', stacked=True)
389
 
        except unstackable_format_errors, e:
 
244
        except (errors.UnstackableRepositoryFormat,
 
245
                errors.UnstackableBranchFormat):
390
246
            raise TestNotApplicable('Format does not support stacking.')
391
247
        unstacked = self.make_repository('unstacked')
392
248
        return stacked_dir.open_workingtree(), unstacked
398
254
 
399
255
    def test_fetch_copies_from_stacked_on_and_stacked(self):
400
256
        stacked, unstacked = self.prepare_stacked_on_fetch()
401
 
        tree = stacked.branch.create_checkout('local')
402
 
        tree.commit('second commit', rev_id='rev2')
 
257
        stacked.commit('second commit', rev_id='rev2')
403
258
        unstacked.fetch(stacked.branch.repository, 'rev2')
404
259
        unstacked.get_revision('rev1')
405
260
        unstacked.get_revision('rev2')
406
 
        self.check_lines_added_or_present(stacked.branch, 'rev1')
407
 
        self.check_lines_added_or_present(stacked.branch, 'rev2')
408
261
 
409
262
    def test_autopack_when_stacked(self):
410
263
        # in bzr.dev as of 20080730, autopack was reported to fail in stacked
412
265
        # repository boundaries.  however, i didn't actually get this test to
413
266
        # fail on that code. -- mbp
414
267
        # see https://bugs.launchpad.net/bzr/+bug/252821
415
 
        stack_on = self.make_branch_and_tree('stack-on')
416
 
        if not stack_on.branch._format.supports_stacking():
 
268
        if not self.branch_format.supports_stacking():
417
269
            raise TestNotApplicable("%r does not support stacking"
418
270
                % self.branch_format)
 
271
        stack_on = self.make_branch_and_tree('stack-on')
419
272
        text_lines = ['line %d blah blah blah\n' % i for i in range(20)]
420
273
        self.build_tree_contents([('stack-on/a', ''.join(text_lines))])
421
274
        stack_on.add('a')
422
275
        stack_on.commit('base commit')
423
276
        stacked_dir = stack_on.bzrdir.sprout('stacked', stacked=True)
424
 
        stacked_branch = stacked_dir.open_branch()
425
 
        local_tree = stack_on.bzrdir.sprout('local').open_workingtree()
 
277
        stacked_tree = stacked_dir.open_workingtree()
426
278
        for i in range(20):
427
279
            text_lines[0] = 'changed in %d\n' % i
428
 
            self.build_tree_contents([('local/a', ''.join(text_lines))])
429
 
            local_tree.commit('commit %d' % i)
430
 
            local_tree.branch.push(stacked_branch)
431
 
        stacked_branch.repository.pack()
432
 
        check.check_dwim(stacked_branch.base, False, True, True)
 
280
            self.build_tree_contents([('stacked/a', ''.join(text_lines))])
 
281
            stacked_tree.commit('commit %d' % i)
 
282
        stacked_tree.branch.repository.pack()
 
283
        stacked_tree.branch.check()
433
284
 
434
285
    def test_pull_delta_when_stacked(self):
435
286
        if not self.branch_format.supports_stacking():
448
299
        other_tree = other_dir.open_workingtree()
449
300
        text_lines[9] = 'changed in other\n'
450
301
        self.build_tree_contents([('other/a', ''.join(text_lines))])
451
 
        stacked_revid = other_tree.commit('commit in other')
 
302
        other_tree.commit('commit in other')
452
303
        # this should have generated a delta; try to pull that across
453
304
        # bug 252821 caused a RevisionNotPresent here...
454
305
        stacked_tree.pull(other_tree.branch)
455
306
        stacked_tree.branch.repository.pack()
456
 
        check.check_dwim(stacked_tree.branch.base, False, True, True)
457
 
        self.check_lines_added_or_present(stacked_tree.branch, stacked_revid)
 
307
        stacked_tree.branch.check()
458
308
 
459
309
    def test_fetch_revisions_with_file_changes(self):
460
310
        # Fetching revisions including file changes into a stacked branch
472
322
        target = self.make_branch('target')
473
323
        try:
474
324
            target.set_stacked_on_url('../stacked-on')
475
 
        except unstackable_format_errors, e:
 
325
        except (errors.UnstackableRepositoryFormat,
 
326
                errors.UnstackableBranchFormat):
476
327
            raise TestNotApplicable('Format does not support stacking.')
477
328
 
478
329
        # Change the source branch.
484
335
        rtree = target.repository.revision_tree('rev2')
485
336
        rtree.lock_read()
486
337
        self.addCleanup(rtree.unlock)
487
 
        self.assertEqual(
488
 
            'new content',
489
 
            rtree.get_file_text(rtree.path2id('a'), 'a'))
490
 
        self.check_lines_added_or_present(target, 'rev2')
491
 
 
492
 
    def test_transform_fallback_location_hook(self):
493
 
        # The 'transform_fallback_location' branch hook allows us to inspect
494
 
        # and transform the URL of the fallback location for the branch.
495
 
        stack_on = self.make_branch('stack-on')
496
 
        stacked = self.make_branch('stacked')
497
 
        try:
498
 
            stacked.set_stacked_on_url('../stack-on')
499
 
        except unstackable_format_errors, e:
500
 
            raise TestNotApplicable('Format does not support stacking.')
501
 
        self.get_transport().rename('stack-on', 'new-stack-on')
502
 
        hook_calls = []
503
 
        def hook(stacked_branch, url):
504
 
            hook_calls.append(url)
505
 
            return '../new-stack-on'
506
 
        branch.Branch.hooks.install_named_hook(
507
 
            'transform_fallback_location', hook, None)
508
 
        branch.Branch.open('stacked')
509
 
        self.assertEqual(['../stack-on'], hook_calls)
510
 
 
511
 
    def test_stack_on_repository_branch(self):
512
 
        # Stacking should work when the repo isn't co-located with the
513
 
        # stack-on branch.
514
 
        try:
515
 
            repo = self.make_repository('repo', shared=True)
516
 
        except errors.IncompatibleFormat:
517
 
            raise TestNotApplicable()
518
 
        if not repo._format.supports_nesting_repositories:
519
 
            raise TestNotApplicable()
520
 
        # Avoid make_branch, which produces standalone branches.
521
 
        bzrdir = self.make_bzrdir('repo/stack-on')
522
 
        try:
523
 
            b = bzrdir.create_branch()
524
 
        except errors.UninitializableFormat:
525
 
            raise TestNotApplicable()
526
 
        transport = self.get_transport('stacked')
527
 
        b.bzrdir.clone_on_transport(transport, stacked_on=b.base)
528
 
        # Ensure that opening the branch doesn't raise.
529
 
        branch.Branch.open(transport.base)
530
 
 
531
 
    def test_revision_history_of_stacked(self):
532
 
        # See <https://launchpad.net/bugs/380314>.
533
 
        stack_on = self.make_branch_and_tree('stack-on')
534
 
        stack_on.commit('first commit', rev_id='rev1')
535
 
        try:
536
 
            stacked_dir = stack_on.bzrdir.sprout(
537
 
                self.get_url('stacked'), stacked=True)
538
 
        except unstackable_format_errors, e:
539
 
            raise TestNotApplicable('Format does not support stacking.')
540
 
        try:
541
 
            stacked = stacked_dir.open_workingtree()
542
 
        except errors.NoWorkingTree:
543
 
            stacked = stacked_dir.open_branch().create_checkout(
544
 
                'stacked-checkout', lightweight=True)
545
 
        tree = stacked.branch.create_checkout('local')
546
 
        tree.commit('second commit', rev_id='rev2')
547
 
        # Sanity check: stacked's repo should not contain rev1, otherwise this
548
 
        # test isn't testing what it's supposed to.
549
 
        repo = stacked.branch.repository.bzrdir.open_repository()
550
 
        repo.lock_read()
551
 
        self.addCleanup(repo.unlock)
552
 
        self.assertEqual({}, repo.get_parent_map(['rev1']))
553
 
        # revision_history should work, even though the history is spread over
554
 
        # multiple repositories.
555
 
        self.assertEqual((2, 'rev2'), stacked.branch.last_revision_info())
556
 
 
557
 
 
558
 
class TestStackingConnections(
559
 
    transport_util.TestCaseWithConnectionHookedTransport):
560
 
 
561
 
    def setUp(self):
562
 
        super(TestStackingConnections, self).setUp()
563
 
        try:
564
 
            base_tree = self.make_branch_and_tree('base',
565
 
                                                  format=self.bzrdir_format)
566
 
        except errors.UninitializableFormat, e:
567
 
            raise TestNotApplicable(e)
568
 
        stacked = self.make_branch('stacked', format=self.bzrdir_format)
569
 
        try:
570
 
            stacked.set_stacked_on_url(base_tree.branch.base)
571
 
        except unstackable_format_errors, e:
572
 
            raise TestNotApplicable(e)
573
 
        base_tree.commit('first', rev_id='rev-base')
574
 
        stacked.set_last_revision_info(1, 'rev-base')
575
 
        stacked_relative = self.make_branch('stacked_relative',
576
 
                                            format=self.bzrdir_format)
577
 
        stacked_relative.set_stacked_on_url(base_tree.branch.user_url)
578
 
        stacked.set_last_revision_info(1, 'rev-base')
579
 
        self.start_logging_connections()
580
 
 
581
 
    def test_open_stacked(self):
582
 
        b = branch.Branch.open(self.get_url('stacked'))
583
 
        rev = b.repository.get_revision('rev-base')
584
 
        self.assertEqual(1, len(self.connections))
585
 
 
586
 
    def test_open_stacked_relative(self):
587
 
        b = branch.Branch.open(self.get_url('stacked_relative'))
588
 
        rev = b.repository.get_revision('rev-base')
589
 
        self.assertEqual(1, len(self.connections))
 
338
        self.assertEqual('new content', rtree.get_file_by_path('a').read())