/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2007-2011 Canonical Ltd
2466.7.3 by Robert Collins
Create bzrlib.branchbuilder.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2466.7.3 by Robert Collins
Create bzrlib.branchbuilder.
16
17
"""Tests for the BranchBuilder class."""
18
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
19
from .. import (
2466.7.4 by Robert Collins
Add BranchBuilder.get_branch().
20
    branch as _mod_branch,
21
    revision as _mod_revision,
22
    tests,
23
    )
6670.4.1 by Jelmer Vernooij
Update imports.
24
from ..bzr import (
25
    branch as _mod_bzrbranch,
26
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
27
from ..branchbuilder import BranchBuilder
2466.7.3 by Robert Collins
Create bzrlib.branchbuilder.
28
29
30
class TestBranchBuilder(tests.TestCaseWithMemoryTransport):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
31
2466.7.3 by Robert Collins
Create bzrlib.branchbuilder.
32
    def test_create(self):
33
        """Test the constructor api."""
34
        builder = BranchBuilder(self.get_transport().clone('foo'))
35
        # we dont care if the branch has been built or not at this point.
2466.7.4 by Robert Collins
Add BranchBuilder.get_branch().
36
37
    def test_get_branch(self):
38
        """get_branch returns the created branch."""
39
        builder = BranchBuilder(self.get_transport().clone('foo'))
40
        branch = builder.get_branch()
41
        self.assertIsInstance(branch, _mod_branch.Branch)
42
        self.assertEqual(self.get_transport().clone('foo').base,
43
            branch.base)
44
        self.assertEqual(
45
            (0, _mod_revision.NULL_REVISION),
46
            branch.last_revision_info())
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
47
2466.7.10 by Robert Collins
Add a format parameter to BranchBuilder.
48
    def test_format(self):
49
        """Making a BranchBuilder with a format option sets the branch type."""
50
        builder = BranchBuilder(self.get_transport(), format='dirstate-tags')
51
        branch = builder.get_branch()
6653.1.9 by Jelmer Vernooij
Fix set_default.
52
        self.assertIsInstance(branch, _mod_bzrbranch.BzrBranch6)
2466.7.10 by Robert Collins
Add a format parameter to BranchBuilder.
53
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
54
    def test_build_one_commit(self):
55
        """doing build_commit causes a commit to happen."""
56
        builder = BranchBuilder(self.get_transport().clone('foo'))
2466.7.9 by Robert Collins
Return the commited revision id from BranchBuilder.build_commit to save later instrospection.
57
        rev_id = builder.build_commit()
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
58
        branch = builder.get_branch()
2466.7.9 by Robert Collins
Return the commited revision id from BranchBuilder.build_commit to save later instrospection.
59
        self.assertEqual((1, rev_id), branch.last_revision_info())
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
60
        self.assertEqual(
61
            'commit 1',
62
            branch.repository.get_revision(branch.last_revision()).message)
63
4070.5.1 by Martin Pool
BranchBuilder now takes a timestamp for commits
64
    def test_build_commit_timestamp(self):
65
        """You can set a date when committing."""
66
        builder = self.make_branch_builder('foo')
67
        rev_id = builder.build_commit(timestamp=1236043340)
68
        branch = builder.get_branch()
69
        self.assertEqual((1, rev_id), branch.last_revision_info())
70
        rev = branch.repository.get_revision(branch.last_revision())
71
        self.assertEqual(
72
            'commit 1',
73
            rev.message)
74
        self.assertEqual(
75
            1236043340,
76
            int(rev.timestamp))
77
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
78
    def test_build_two_commits(self):
79
        """The second commit has the right parents and message."""
80
        builder = BranchBuilder(self.get_transport().clone('foo'))
2466.7.9 by Robert Collins
Return the commited revision id from BranchBuilder.build_commit to save later instrospection.
81
        rev_id1 = builder.build_commit()
82
        rev_id2 = builder.build_commit()
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
83
        branch = builder.get_branch()
2466.7.9 by Robert Collins
Return the commited revision id from BranchBuilder.build_commit to save later instrospection.
84
        self.assertEqual((2, rev_id2), branch.last_revision_info())
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
85
        self.assertEqual(
86
            'commit 2',
87
            branch.repository.get_revision(branch.last_revision()).message)
88
        self.assertEqual(
2466.7.9 by Robert Collins
Return the commited revision id from BranchBuilder.build_commit to save later instrospection.
89
            [rev_id1],
2466.7.6 by Robert Collins
Add BranchBuilder.build_commit.
90
            branch.repository.get_revision(branch.last_revision()).parent_ids)
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
91
6225.1.1 by Jelmer Vernooij
Add parent_ids argument to BranchBuilder.build_commit.
92
    def test_build_commit_parent_ids(self):
93
        """build_commit() takes a parent_ids argument."""
94
        builder = BranchBuilder(self.get_transport().clone('foo'))
95
        rev_id1 = builder.build_commit(
96
            parent_ids=["ghost"], allow_leftmost_as_ghost=True)
97
        rev_id2 = builder.build_commit(parent_ids=[])
98
        branch = builder.get_branch()
99
        self.assertEqual((1, rev_id2), branch.last_revision_info())
100
        self.assertEqual(
101
            ["ghost"],
102
            branch.repository.get_revision(rev_id1).parent_ids)
103
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
104
105
class TestBranchBuilderBuildSnapshot(tests.TestCaseWithMemoryTransport):
106
107
    def assertTreeShape(self, expected_shape, tree):
108
        """Check that the tree shape matches expectations."""
109
        tree.lock_read()
110
        try:
111
            entries = [(path, ie.file_id, ie.kind)
112
                       for path, ie in tree.iter_entries_by_dir()]
113
        finally:
114
            tree.unlock()
115
        self.assertEqual(expected_shape, entries)
116
117
    def build_a_rev(self):
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
118
        builder = BranchBuilder(self.get_transport().clone('foo'))
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
119
        rev_id1 = builder.build_snapshot(None,
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
120
            [('add', ('', 'a-root-id', 'directory', None)),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
121
             ('add', ('a', 'a-id', 'file', 'contents'))],
122
            revision_id='A-id')
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
123
        self.assertEqual('A-id', rev_id1)
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
124
        return builder
125
126
    def test_add_one_file(self):
127
        builder = self.build_a_rev()
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
128
        branch = builder.get_branch()
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
129
        self.assertEqual((1, 'A-id'), branch.last_revision_info())
130
        rev_tree = branch.repository.revision_tree('A-id')
3567.4.1 by John Arbash Meinel
Initial work to have BranchBuilder allow us to do tree-shape work.
131
        rev_tree.lock_read()
132
        self.addCleanup(rev_tree.unlock)
3567.4.2 by John Arbash Meinel
test that we can add more files into an existing build
133
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
134
                              (u'a', 'a-id', 'file')], rev_tree)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
135
        self.assertEqual('contents', rev_tree.get_file_text('a'))
3567.4.2 by John Arbash Meinel
test that we can add more files into an existing build
136
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
137
    def test_add_second_file(self):
138
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
139
        rev_id2 = builder.build_snapshot(None,
140
            [('add', ('b', 'b-id', 'file', 'content_b'))],
141
            revision_id='B-id')
3567.4.2 by John Arbash Meinel
test that we can add more files into an existing build
142
        self.assertEqual('B-id', rev_id2)
143
        branch = builder.get_branch()
144
        self.assertEqual((2, rev_id2), branch.last_revision_info())
145
        rev_tree = branch.repository.revision_tree(rev_id2)
146
        rev_tree.lock_read()
147
        self.addCleanup(rev_tree.unlock)
148
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
149
                              (u'a', 'a-id', 'file'),
150
                              (u'b', 'b-id', 'file')], rev_tree)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
151
        self.assertEqual('content_b', rev_tree.get_file_text('b'))
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
152
3567.4.7 by John Arbash Meinel
Revert back to using MemoryTree.mkdir() rather than creating the directory during add().
153
    def test_add_empty_dir(self):
154
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
155
        rev_id2 = builder.build_snapshot(None,
156
            [('add', ('b', 'b-id', 'directory', None))],
157
            revision_id='B-id')
3567.4.7 by John Arbash Meinel
Revert back to using MemoryTree.mkdir() rather than creating the directory during add().
158
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
159
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
160
                              (u'a', 'a-id', 'file'),
161
                              (u'b', 'b-id', 'directory'),
162
                             ], rev_tree)
163
4070.5.1 by Martin Pool
BranchBuilder now takes a timestamp for commits
164
    def test_commit_timestamp(self):
165
        builder = self.make_branch_builder('foo')
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
166
        rev_id = builder.build_snapshot(None,
4070.5.1 by Martin Pool
BranchBuilder now takes a timestamp for commits
167
            [('add', (u'', None, 'directory', None))],
168
            timestamp=1234567890)
169
        rev = builder.get_branch().repository.get_revision(rev_id)
170
        self.assertEqual(
171
            1234567890,
172
            int(rev.timestamp))
173
3567.4.15 by John Arbash Meinel
Allow setting the commit message.
174
    def test_commit_message_default(self):
175
        builder = BranchBuilder(self.get_transport().clone('foo'))
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
176
        rev_id = builder.build_snapshot(None,
3567.4.15 by John Arbash Meinel
Allow setting the commit message.
177
            [('add', (u'', None, 'directory', None))])
178
        branch = builder.get_branch()
179
        rev = branch.repository.get_revision(rev_id)
180
        self.assertEqual(u'commit 1', rev.message)
181
182
    def test_commit_message_supplied(self):
183
        builder = BranchBuilder(self.get_transport().clone('foo'))
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
184
        rev_id = builder.build_snapshot(None,
3567.4.15 by John Arbash Meinel
Allow setting the commit message.
185
            [('add', (u'', None, 'directory', None))],
186
            message=u'Foo')
187
        branch = builder.get_branch()
188
        rev = branch.repository.get_revision(rev_id)
189
        self.assertEqual(u'Foo', rev.message)
190
5060.1.1 by Robert Collins
``bzrlib.branchbuilder.BranchBuilder.build_snapshot`` now accepts a
191
    def test_commit_message_callback(self):
192
        builder = BranchBuilder(self.get_transport().clone('foo'))
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
193
        rev_id = builder.build_snapshot(None,
5060.1.1 by Robert Collins
``bzrlib.branchbuilder.BranchBuilder.build_snapshot`` now accepts a
194
            [('add', (u'', None, 'directory', None))],
195
            message_callback=lambda x:u'Foo')
196
        branch = builder.get_branch()
197
        rev = branch.repository.get_revision(rev_id)
198
        self.assertEqual(u'Foo', rev.message)
199
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
200
    def test_modify_file(self):
201
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
202
        rev_id2 = builder.build_snapshot(None,
203
            [('modify', ('a-id', 'new\ncontent\n'))],
204
            revision_id='B-id')
3567.4.3 by John Arbash Meinel
Add an action for modifying an existing file
205
        self.assertEqual('B-id', rev_id2)
206
        branch = builder.get_branch()
207
        rev_tree = branch.repository.revision_tree(rev_id2)
208
        rev_tree.lock_read()
209
        self.addCleanup(rev_tree.unlock)
6809.4.13 by Jelmer Vernooij
Fix tests.
210
        self.assertEqual('new\ncontent\n',
211
                         rev_tree.get_file_text(rev_tree.id2path('a-id')))
3567.4.4 by John Arbash Meinel
Add the ability to 'unversion' files, and handle unknown actions.
212
213
    def test_delete_file(self):
214
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
215
        rev_id2 = builder.build_snapshot(None,
216
            [('unversion', 'a-id')], revision_id='B-id')
3567.4.4 by John Arbash Meinel
Add the ability to 'unversion' files, and handle unknown actions.
217
        self.assertEqual('B-id', rev_id2)
218
        branch = builder.get_branch()
219
        rev_tree = branch.repository.revision_tree(rev_id2)
220
        rev_tree.lock_read()
221
        self.addCleanup(rev_tree.unlock)
222
        self.assertTreeShape([(u'', 'a-root-id', 'directory')], rev_tree)
223
3567.4.5 by John Arbash Meinel
MemoryTree.add(directory) will now create a directory node in the Transport
224
    def test_delete_directory(self):
225
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
226
        rev_id2 = builder.build_snapshot(None,
3567.4.5 by John Arbash Meinel
MemoryTree.add(directory) will now create a directory node in the Transport
227
            [('add', ('b', 'b-id', 'directory', None)),
228
             ('add', ('b/c', 'c-id', 'file', 'foo\n')),
229
             ('add', ('b/d', 'd-id', 'directory', None)),
230
             ('add', ('b/d/e', 'e-id', 'file', 'eff\n')),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
231
            ], revision_id='B-id')
3567.4.5 by John Arbash Meinel
MemoryTree.add(directory) will now create a directory node in the Transport
232
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
233
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
234
                              (u'a', 'a-id', 'file'),
235
                              (u'b', 'b-id', 'directory'),
236
                              (u'b/c', 'c-id', 'file'),
237
                              (u'b/d', 'd-id', 'directory'),
238
                              (u'b/d/e', 'e-id', 'file')], rev_tree)
3567.4.6 by John Arbash Meinel
unversioning a directory is recursive.
239
        # Removing a directory removes all child dirs
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
240
        builder.build_snapshot(
241
                None, [('unversion', 'b-id')],
242
                revision_id='C-id')
3567.4.6 by John Arbash Meinel
unversioning a directory is recursive.
243
        rev_tree = builder.get_branch().repository.revision_tree('C-id')
244
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
245
                              (u'a', 'a-id', 'file'),
246
                             ], rev_tree)
3567.4.5 by John Arbash Meinel
MemoryTree.add(directory) will now create a directory node in the Transport
247
3567.4.4 by John Arbash Meinel
Add the ability to 'unversion' files, and handle unknown actions.
248
    def test_unknown_action(self):
249
        builder = self.build_a_rev()
3567.4.18 by John Arbash Meinel
Apply the review changes from Martin to the exact patch he approved.
250
        e = self.assertRaises(ValueError,
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
251
            builder.build_snapshot, None, [('weirdo', ('foo',))],
252
            revision_id='B-id')
3567.4.18 by John Arbash Meinel
Apply the review changes from Martin to the exact patch he approved.
253
        self.assertEqual('Unknown build action: "weirdo"', str(e))
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
254
3567.5.1 by John Arbash Meinel
Implement rename_one on MemoryTree, and expose that in the Branch Builder
255
    def test_rename(self):
256
        builder = self.build_a_rev()
6816.2.3 by Jelmer Vernooij
Port over last uses of build_snapshot.
257
        builder.build_snapshot(None,
258
            [('rename', ('a', 'b'))], revision_id='B-id')
3567.5.1 by John Arbash Meinel
Implement rename_one on MemoryTree, and expose that in the Branch Builder
259
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
260
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
261
                              (u'b', 'a-id', 'file')], rev_tree)
262
263
    def test_rename_into_subdir(self):
264
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
265
        builder.build_snapshot(None,
3567.5.1 by John Arbash Meinel
Implement rename_one on MemoryTree, and expose that in the Branch Builder
266
            [('add', ('dir', 'dir-id', 'directory', None)),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
267
             ('rename', ('a', 'dir/a'))], revision_id='B-id')
3567.5.1 by John Arbash Meinel
Implement rename_one on MemoryTree, and expose that in the Branch Builder
268
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
269
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
270
                              (u'dir', 'dir-id', 'directory'),
271
                              (u'dir/a', 'a-id', 'file')], rev_tree)
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
272
6008.2.1 by Andrew Bennetts
Allow renaming entries out of a dir and unversioning a dir in the one build_snapshot call.
273
    def test_rename_out_of_unversioned_subdir(self):
274
        builder = self.build_a_rev()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
275
        builder.build_snapshot(None,
6008.2.1 by Andrew Bennetts
Allow renaming entries out of a dir and unversioning a dir in the one build_snapshot call.
276
            [('add', ('dir', 'dir-id', 'directory', None)),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
277
             ('rename', ('a', 'dir/a'))],
278
            revision_id='B-id')
279
        builder.build_snapshot(None,
6008.2.1 by Andrew Bennetts
Allow renaming entries out of a dir and unversioning a dir in the one build_snapshot call.
280
            [('rename', ('dir/a', 'a')),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
281
             ('unversion', 'dir-id')], revision_id='C-id')
6008.2.1 by Andrew Bennetts
Allow renaming entries out of a dir and unversioning a dir in the one build_snapshot call.
282
        rev_tree = builder.get_branch().repository.revision_tree('C-id')
283
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
284
                              (u'a', 'a-id', 'file')], rev_tree)
285
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
286
    def test_set_parent(self):
287
        builder = self.build_a_rev()
3567.4.17 by John Arbash Meinel
Add the ability to define a series of commits, which allows us to hold open the locks.
288
        builder.start_series()
289
        self.addCleanup(builder.finish_series)
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
290
        builder.build_snapshot(['A-id'],
291
            [('modify', ('a-id', 'new\ncontent\n'))],
292
            revision_id='B-id')
293
        builder.build_snapshot(['A-id'],
294
            [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))],
295
            revision_id='C-id')
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
296
        # We should now have a graph:
297
        #   A
298
        #   |\
299
        #   C B
300
        # And not A => B => C
301
        repo = builder.get_branch().repository
302
        self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',)},
303
                         repo.get_parent_map(['B-id', 'C-id']))
304
        b_tree = repo.revision_tree('B-id')
305
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
306
                              (u'a', 'a-id', 'file'),
307
                             ], b_tree)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
308
        self.assertEqual('new\ncontent\n', b_tree.get_file_text('a'))
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
309
310
        # We should still be using the content from A in C, not from B
311
        c_tree = repo.revision_tree('C-id')
312
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
313
                              (u'a', 'a-id', 'file'),
314
                              (u'c', 'c-id', 'file'),
315
                             ], c_tree)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
316
        self.assertEqual('contents', c_tree.get_file_text('a'))
317
        self.assertEqual('alt\ncontent\n', c_tree.get_file_text('c'))
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
318
319
    def test_set_merge_parent(self):
320
        builder = self.build_a_rev()
3567.4.17 by John Arbash Meinel
Add the ability to define a series of commits, which allows us to hold open the locks.
321
        builder.start_series()
322
        self.addCleanup(builder.finish_series)
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
323
        builder.build_snapshot(['A-id'],
324
            [('add', ('b', 'b-id', 'file', 'b\ncontent\n'))],
325
            revision_id='B-id')
326
        builder.build_snapshot(['A-id'],
327
            [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))],
328
            revision_id='C-id')
329
        builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
330
        repo = builder.get_branch().repository
331
        self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',),
332
                          'D-id': ('B-id', 'C-id')},
333
                         repo.get_parent_map(['B-id', 'C-id', 'D-id']))
334
        d_tree = repo.revision_tree('D-id')
335
        # Note: by default a merge node does *not* pull in the changes from the
336
        #       merged tree, you have to supply it yourself.
337
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
338
                              (u'a', 'a-id', 'file'),
339
                              (u'b', 'b-id', 'file'),
340
                             ], d_tree)
341
342
    def test_set_merge_parent_and_contents(self):
343
        builder = self.build_a_rev()
3567.4.17 by John Arbash Meinel
Add the ability to define a series of commits, which allows us to hold open the locks.
344
        builder.start_series()
345
        self.addCleanup(builder.finish_series)
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
346
        builder.build_snapshot(['A-id'],
347
            [('add', ('b', 'b-id', 'file', 'b\ncontent\n'))],
348
            revision_id='B-id')
349
        builder.build_snapshot(['A-id'],
350
            [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))],
351
            revision_id='C-id')
352
        builder.build_snapshot(['B-id', 'C-id'],
353
            [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))],
354
            revision_id='D-id')
3567.4.8 by John Arbash Meinel
Add the ability to force a basis for a revision.
355
        repo = builder.get_branch().repository
356
        self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',),
357
                          'D-id': ('B-id', 'C-id')},
358
                         repo.get_parent_map(['B-id', 'C-id', 'D-id']))
359
        d_tree = repo.revision_tree('D-id')
360
        self.assertTreeShape([(u'', 'a-root-id', 'directory'),
361
                              (u'a', 'a-id', 'file'),
362
                              (u'b', 'b-id', 'file'),
363
                              (u'c', 'c-id', 'file'),
364
                             ], d_tree)
365
        # Because we copied the exact text into *this* tree, the 'c' file
366
        # should look like it was not modified in the merge
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
367
        self.assertEqual('C-id', d_tree.get_file_revision('c'))
3567.4.17 by John Arbash Meinel
Add the ability to define a series of commits, which allows us to hold open the locks.
368
5540.1.1 by Gary van der Merwe
Make ``BranchBuilder.build_snapshot`` accept parent_ids == ['null:'].
369
    def test_set_parent_to_null(self):
370
        builder = self.build_a_rev()
371
        builder.start_series()
372
        self.addCleanup(builder.finish_series)
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
373
        builder.build_snapshot([],
374
            [('add', ('', None, 'directory', None))],
375
            revision_id='B-id')
5540.1.1 by Gary van der Merwe
Make ``BranchBuilder.build_snapshot`` accept parent_ids == ['null:'].
376
        # We should now have a graph:
377
        #   A B
378
        # And not A => B
379
        repo = builder.get_branch().repository
380
        self.assertEqual({'A-id': (_mod_revision.NULL_REVISION,),
381
                          'B-id': (_mod_revision.NULL_REVISION,),},
382
                         repo.get_parent_map(['A-id', 'B-id']))
383
384
    
3567.4.17 by John Arbash Meinel
Add the ability to define a series of commits, which allows us to hold open the locks.
385
    def test_start_finish_series(self):
386
        builder = BranchBuilder(self.get_transport().clone('foo'))
387
        builder.start_series()
388
        try:
389
            self.assertIsNot(None, builder._tree)
390
            self.assertEqual('w', builder._tree._lock_mode)
391
            self.assertTrue(builder._branch.is_locked())
392
        finally:
393
            builder.finish_series()
394
        self.assertIs(None, builder._tree)
395
        self.assertFalse(builder._branch.is_locked())
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
396
397
    def test_ghost_mainline_history(self):
398
        builder = BranchBuilder(self.get_transport().clone('foo'))
399
        builder.start_series()
400
        try:
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
401
            builder.build_snapshot(['ghost'],
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
402
                [('add', ('', 'ROOT_ID', 'directory', ''))],
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
403
                allow_leftmost_as_ghost=True, revision_id='tip')
4324.3.1 by Robert Collins
When adding rich root data follow the standard revision graph rules, so it does not create 'inconstent parents'.
404
        finally:
405
            builder.finish_series()
406
        b = builder.get_branch()
407
        b.lock_read()
408
        self.addCleanup(b.unlock)
409
        self.assertEqual(('ghost',),
410
            b.repository.get_graph().get_parent_map(['tip'])['tip'])
6008.2.2 by Andrew Bennetts
Add unit test for regression.
411
412
    def test_unversion_root_add_new_root(self):
413
        builder = BranchBuilder(self.get_transport().clone('foo'))
414
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
415
        builder.build_snapshot(None,
416
            [('add', ('', 'TREE_ROOT', 'directory', ''))],
417
            revision_id='rev-1')
418
        builder.build_snapshot(None,
6008.2.2 by Andrew Bennetts
Add unit test for regression.
419
            [('unversion', 'TREE_ROOT'),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
420
             ('add', ('', 'my-root', 'directory', ''))],
421
            revision_id='rev-2')
6008.2.2 by Andrew Bennetts
Add unit test for regression.
422
        builder.finish_series()
423
        rev_tree = builder.get_branch().repository.revision_tree('rev-2')
424
        self.assertTreeShape([(u'', 'my-root', 'directory')], rev_tree)
425
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
426
    def test_empty_flush(self):
427
        """A flush with no actions before it is a no-op."""
428
        builder = BranchBuilder(self.get_transport().clone('foo'))
429
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
430
        builder.build_snapshot(None,
431
            [('add', ('', 'TREE_ROOT', 'directory', ''))],
432
            revision_id='rev-1')
433
        builder.build_snapshot(None, [('flush', None)], revision_id='rev-2')
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
434
        builder.finish_series()
435
        rev_tree = builder.get_branch().repository.revision_tree('rev-2')
436
        self.assertTreeShape([(u'', 'TREE_ROOT', 'directory')], rev_tree)
437
438
    def test_kind_change(self):
439
        """It's possible to change the kind of an entry in a single snapshot
440
        with a bit of help from the 'flush' action.
441
        """
442
        builder = BranchBuilder(self.get_transport().clone('foo'))
443
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
444
        builder.build_snapshot(None,
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
445
            [('add', (u'', 'a-root-id', 'directory', None)),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
446
             ('add', (u'a', 'a-id', 'file', 'content\n'))],
447
            revision_id='A-id')
448
        builder.build_snapshot(None,
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
449
            [('unversion', 'a-id'),
450
             ('flush', None),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
451
             ('add', (u'a', 'a-id', 'directory', None))],
452
            revision_id='B-id')
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
453
        builder.finish_series()
454
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
455
        self.assertTreeShape(
456
            [(u'', 'a-root-id', 'directory'), (u'a', 'a-id', 'directory')],
457
            rev_tree)
458
459
    def test_pivot_root(self):
460
        """It's possible (albeit awkward) to move an existing dir to the root
461
        in a single snapshot by using unversion then flush then add.
462
        """
463
        builder = BranchBuilder(self.get_transport().clone('foo'))
464
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
465
        builder.build_snapshot(None,
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
466
            [('add', (u'', 'orig-root', 'directory', None)),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
467
             ('add', (u'dir', 'dir-id', 'directory', None))],
468
            revision_id='A-id')
469
        builder.build_snapshot(None,
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
470
            [('unversion', 'orig-root'),  # implicitly unversions all children
471
             ('flush', None),
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
472
             ('add', (u'', 'dir-id', 'directory', None))],
473
            revision_id='B-id')
6008.2.5 by Andrew Bennetts
Rename 'checkpoint' to 'flush', add some unit tests and more comments.
474
        builder.finish_series()
475
        rev_tree = builder.get_branch().repository.revision_tree('B-id')
476
        self.assertTreeShape([(u'', 'dir-id', 'directory')], rev_tree)
477