~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_repository_reference/test_commit_with_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) 2010, 2011 Canonical Ltd
2
 
#
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.
7
 
#
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.
12
 
#
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
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
from bzrlib import (
19
 
    errors,
20
 
    remote,
21
 
    tests,
22
 
    urlutils,
23
 
    )
24
 
from bzrlib.tests.per_repository import TestCaseWithRepository
25
 
 
26
 
 
27
 
class TestCaseWithStackedTarget(TestCaseWithRepository):
28
 
 
29
 
    r1_key = ('rev1-id',)
30
 
    r2_key = ('rev2-id',)
31
 
 
32
 
    def make_stacked_target(self):
33
 
        base_tree = self.make_branch_and_tree('base')
34
 
        self.build_tree(['base/f1.txt'])
35
 
        base_tree.add(['f1.txt'], ['f1.txt-id'])
36
 
        base_tree.commit('initial', rev_id=self.r1_key[0])
37
 
        self.build_tree(['base/f2.txt'])
38
 
        base_tree.add(['f2.txt'], ['f2.txt-id'])
39
 
        base_tree.commit('base adds f2', rev_id=self.r2_key[0])
40
 
        stacked_url = urlutils.join(base_tree.branch.base, '../stacked')
41
 
        stacked_bzrdir = base_tree.bzrdir.sprout(stacked_url,
42
 
            stacked=True)
43
 
        if isinstance(stacked_bzrdir, remote.RemoteBzrDir):
44
 
            stacked_branch = stacked_bzrdir.open_branch()
45
 
            stacked_tree = stacked_branch.create_checkout('stacked',
46
 
                lightweight=True)
47
 
        else:
48
 
            stacked_tree = stacked_bzrdir.open_workingtree()
49
 
        return base_tree, stacked_tree
50
 
 
51
 
 
52
 
class TestCommitWithStacking(TestCaseWithStackedTarget):
53
 
 
54
 
    def setUp(self):
55
 
        super(TestCommitWithStacking, self).setUp()
56
 
        format = self.repository_format
57
 
        if (not (isinstance(format, remote.RemoteRepositoryFormat)
58
 
                 or format.supports_chks)):
59
 
            raise tests.TestNotApplicable('stacked commit only supported'
60
 
                ' for chk repositories')
61
 
 
62
 
    def get_only_repo(self, tree):
63
 
        """Open just the repository used by this tree.
64
 
 
65
 
        This returns a read locked Repository object without any stacking
66
 
        fallbacks.
67
 
        """
68
 
        repo = tree.branch.repository.bzrdir.open_repository()
69
 
        repo.lock_read()
70
 
        self.addCleanup(repo.unlock)
71
 
        return repo
72
 
 
73
 
    def assertPresent(self, expected, vf, keys):
74
 
        """Check which of the supplied keys are present."""
75
 
        parent_map = vf.get_parent_map(keys)
76
 
        self.assertEqual(sorted(expected), sorted(parent_map))
77
 
 
78
 
    def test_simple_commit(self):
79
 
        base_tree, stacked_tree = self.make_stacked_target()
80
 
        self.assertEqual(1,
81
 
                len(stacked_tree.branch.repository._fallback_repositories))
82
 
        self.build_tree_contents([('stacked/f1.txt', 'new content\n')])
83
 
        stacked_tree.commit('new content', rev_id='new-rev-id')
84
 
        # We open the repository without fallbacks to ensure the data is
85
 
        # locally true
86
 
        stacked_only_repo = self.get_only_repo(stacked_tree)
87
 
        # We should have the immediate parent inventory available, but not the
88
 
        # grandparent's
89
 
        self.assertPresent([self.r2_key],
90
 
            stacked_only_repo.inventories, [self.r1_key, self.r2_key])
91
 
        # And we should be able to pull this revision into another stacked
92
 
        # branch
93
 
        stacked2_branch = base_tree.bzrdir.sprout('stacked2',
94
 
                                                  stacked=True).open_branch()
95
 
        stacked2_branch.repository.fetch(stacked_only_repo,
96
 
                                         revision_id='new-rev-id')
97
 
 
98
 
    def test_merge_commit(self):
99
 
        base_tree, stacked_tree = self.make_stacked_target()
100
 
        self.build_tree_contents([('base/f1.txt', 'new content\n')])
101
 
        r3_key = ('rev3-id',)
102
 
        base_tree.commit('second base', rev_id=r3_key[0])
103
 
        to_be_merged_tree = base_tree.bzrdir.sprout('merged'
104
 
            ).open_workingtree()
105
 
        self.build_tree(['merged/f2.txt'])
106
 
        to_be_merged_tree.add(['f2.txt'], ['f2.txt-id'])
107
 
        to_merge_key = ('to-merge-rev-id',)
108
 
        to_be_merged_tree.commit('new-to-be-merged', rev_id=to_merge_key[0])
109
 
        stacked_tree.merge_from_branch(to_be_merged_tree.branch)
110
 
        merged_key = ('merged-rev-id',)
111
 
        stacked_tree.commit('merge', rev_id=merged_key[0])
112
 
        # to-merge isn't in base, so it should be in stacked.
113
 
        # rev3-id is a parent of a revision we have, so we should have the
114
 
        # inventory, but not the revision.
115
 
        # merged has a parent of r2, so we should also have r2's
116
 
        # inventory-but-not-revision.
117
 
        # Nothing has r1 directly, so we shouldn't have anything present for it
118
 
        stacked_only_repo = self.get_only_repo(stacked_tree)
119
 
        all_keys = [self.r1_key, self.r2_key, r3_key, to_merge_key, merged_key]
120
 
        self.assertPresent([to_merge_key, merged_key],
121
 
                           stacked_only_repo.revisions, all_keys)
122
 
        self.assertPresent([self.r2_key, r3_key, to_merge_key, merged_key],
123
 
                           stacked_only_repo.inventories, all_keys)
124
 
 
125
 
    def test_merge_from_master(self):
126
 
        base_tree, stacked_tree = self.make_stacked_target()
127
 
        self.build_tree_contents([('base/f1.txt', 'new content\n')])
128
 
        r3_key = ('rev3-id',)
129
 
        base_tree.commit('second base', rev_id=r3_key[0])
130
 
        stacked_tree.merge_from_branch(base_tree.branch)
131
 
        merged_key = ('merged-rev-id',)
132
 
        stacked_tree.commit('merge', rev_id=merged_key[0])
133
 
        all_keys = [self.r1_key, self.r2_key, r3_key, merged_key]
134
 
        # We shouldn't have any of the base revisions in the local repo, but we
135
 
        # should have both base inventories.
136
 
        stacked_only_repo = self.get_only_repo(stacked_tree)
137
 
        self.assertPresent([merged_key],
138
 
                           stacked_only_repo.revisions, all_keys)
139
 
        self.assertPresent([self.r2_key, r3_key, merged_key],
140
 
                           stacked_only_repo.inventories, all_keys)
141
 
 
142
 
    def test_multi_stack(self):
143
 
        """base + stacked + stacked-on-stacked"""
144
 
        base_tree, stacked_tree = self.make_stacked_target()
145
 
        self.build_tree(['stacked/f3.txt'])
146
 
        stacked_tree.add(['f3.txt'], ['f3.txt-id'])
147
 
        stacked_key = ('stacked-rev-id',)
148
 
        stacked_tree.commit('add f3', rev_id=stacked_key[0])
149
 
        stacked_only_repo = self.get_only_repo(stacked_tree)
150
 
        self.assertPresent([self.r2_key], stacked_only_repo.inventories,
151
 
                           [self.r1_key, self.r2_key])
152
 
        # This ensures we get a Remote URL, rather than a local one.
153
 
        stacked2_url = urlutils.join(base_tree.branch.base, '../stacked2')
154
 
        stacked2_bzrdir = stacked_tree.bzrdir.sprout(stacked2_url,
155
 
                            revision_id=self.r1_key[0],
156
 
                            stacked=True)
157
 
        if isinstance(stacked2_bzrdir, remote.RemoteBzrDir):
158
 
            stacked2_branch = stacked2_bzrdir.open_branch()
159
 
            stacked2_tree = stacked2_branch.create_checkout('stacked2',
160
 
                lightweight=True)
161
 
        else:
162
 
            stacked2_tree = stacked2_bzrdir.open_workingtree()
163
 
        # stacked2 is stacked on stacked, but its content is rev1, so
164
 
        # it needs to pull the basis information from a fallback-of-fallback.
165
 
        self.build_tree(['stacked2/f3.txt'])
166
 
        stacked2_only_repo = self.get_only_repo(stacked2_tree)
167
 
        self.assertPresent([], stacked2_only_repo.inventories,
168
 
                           [self.r1_key, self.r2_key])
169
 
        stacked2_tree.add(['f3.txt'], ['f3.txt-id'])
170
 
        stacked2_tree.commit('add f3', rev_id='stacked2-rev-id')
171
 
        # We added data to this read-locked repo, so refresh it
172
 
        stacked2_only_repo.refresh_data()
173
 
        self.assertPresent([self.r1_key], stacked2_only_repo.inventories,
174
 
                           [self.r1_key, self.r2_key])
175
 
 
176
 
    def test_commit_with_ghosts_fails(self):
177
 
        base_tree, stacked_tree = self.make_stacked_target()
178
 
        stacked_tree.set_parent_ids([stacked_tree.last_revision(),
179
 
                                     'ghost-rev-id'])
180
 
        self.assertRaises(errors.BzrError,
181
 
            stacked_tree.commit, 'failed_commit')
182
 
 
183
 
    def test_commit_with_ghost_in_ancestry(self):
184
 
        base_tree, stacked_tree = self.make_stacked_target()
185
 
        self.build_tree_contents([('base/f1.txt', 'new content\n')])
186
 
        r3_key = ('rev3-id',)
187
 
        base_tree.commit('second base', rev_id=r3_key[0])
188
 
        to_be_merged_tree = base_tree.bzrdir.sprout('merged'
189
 
            ).open_workingtree()
190
 
        self.build_tree(['merged/f2.txt'])
191
 
        to_be_merged_tree.add(['f2.txt'], ['f2.txt-id'])
192
 
        ghost_key = ('ghost-rev-id',)
193
 
        to_be_merged_tree.set_parent_ids([r3_key[0], ghost_key[0]])
194
 
        to_merge_key = ('to-merge-rev-id',)
195
 
        to_be_merged_tree.commit('new-to-be-merged', rev_id=to_merge_key[0])
196
 
        stacked_tree.merge_from_branch(to_be_merged_tree.branch)
197
 
        merged_key = ('merged-rev-id',)
198
 
        stacked_tree.commit('merge', rev_id=merged_key[0])
199
 
        # vs test_merge_commit, the fetch for 'merge_from_branch' should
200
 
        # already have handled that 'ghost-rev-id' is a ghost, and commit
201
 
        # should not try to fill it in at this point.
202
 
        stacked_only_repo = self.get_only_repo(stacked_tree)
203
 
        all_keys = [self.r1_key, self.r2_key, r3_key, to_merge_key, merged_key,
204
 
                    ghost_key]
205
 
        self.assertPresent([to_merge_key, merged_key],
206
 
                           stacked_only_repo.revisions, all_keys)
207
 
        self.assertPresent([self.r2_key, r3_key, to_merge_key, merged_key],
208
 
                           stacked_only_repo.inventories, all_keys)
209
 
 
210
 
 
211
 
class TestCommitStackedFailsAppropriately(TestCaseWithStackedTarget):
212
 
 
213
 
    def test_stacked_commit_fails_on_old_formats(self):
214
 
        base_tree, stacked_tree = self.make_stacked_target()
215
 
        format = stacked_tree.branch.repository._format
216
 
        if format.supports_chks:
217
 
            stacked_tree.commit('should succeed')
218
 
        else:
219
 
            self.assertRaises(errors.BzrError,
220
 
                stacked_tree.commit, 'unsupported format')