/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5128.1.1 by Vincent Ladeuil
Uncontroversial cleanups, mostly comments
1
# Copyright (C) 2006-2010 Canonical Ltd
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
17
18
import os
19
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
20
from bzrlib import (
21
    branch,
22
    bzrdir,
2922.2.4 by John Arbash Meinel
Fix bug #114615 by teaching unversion() to not touch renamed entries.
23
    conflicts,
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
24
    errors,
3335.1.3 by Jelmer Vernooij
Add tests for start_commit hook.
25
    mutabletree,
2922.2.1 by John Arbash Meinel
Add failing tests exposing part of bug #114615
26
    osutils,
2598.5.2 by Aaron Bentley
Got all tests passing with Branch returning 'null:' for null revision
27
    revision as _mod_revision,
28
    ui,
29
    )
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
30
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
5422.1.5 by Martin Pool
Move ProgressRecordingUIFactory to bzrlib.tests.testui
31
from bzrlib.tests.testui import ProgressRecordingUIFactory
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
32
33
34
class TestCommit(TestCaseWithWorkingTree):
35
2922.2.1 by John Arbash Meinel
Add failing tests exposing part of bug #114615
36
    def test_autodelete_renamed(self):
37
        tree_a = self.make_branch_and_tree('a')
38
        self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2'])
39
        tree_a.add(['dir', 'dir/f1', 'dir/f2'], ['dir-id', 'f1-id', 'f2-id'])
40
        rev_id1 = tree_a.commit('init')
41
        # Start off by renaming entries,
42
        # but then actually auto delete the whole tree
43
        # https://bugs.launchpad.net/bzr/+bug/114615
44
        tree_a.rename_one('dir/f1', 'dir/a')
45
        tree_a.rename_one('dir/f2', 'dir/z')
46
        osutils.rmtree('a/dir')
47
        tree_a.commit('autoremoved')
48
49
        tree_a.lock_read()
50
        try:
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
51
            root_id = tree_a.get_root_id()
2922.2.1 by John Arbash Meinel
Add failing tests exposing part of bug #114615
52
            paths = [(path, ie.file_id)
53
                     for path, ie in tree_a.iter_entries_by_dir()]
54
        finally:
55
            tree_a.unlock()
56
        # The only paths left should be the root
57
        self.assertEqual([('', root_id)], paths)
58
2922.2.3 by John Arbash Meinel
Add a test which shows why the previous fix is broken.
59
    def test_no_autodelete_renamed_away(self):
60
        tree_a = self.make_branch_and_tree('a')
61
        self.build_tree(['a/dir/', 'a/dir/f1', 'a/dir/f2', 'a/dir2/'])
62
        tree_a.add(['dir', 'dir/f1', 'dir/f2', 'dir2'],
63
                   ['dir-id', 'f1-id', 'f2-id', 'dir2-id'])
64
        rev_id1 = tree_a.commit('init')
65
        # Rename one entry out of this directory
66
        tree_a.rename_one('dir/f1', 'dir2/a')
67
        osutils.rmtree('a/dir')
68
        tree_a.commit('autoremoved')
69
70
        tree_a.lock_read()
71
        try:
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
72
            root_id = tree_a.get_root_id()
2922.2.3 by John Arbash Meinel
Add a test which shows why the previous fix is broken.
73
            paths = [(path, ie.file_id)
74
                     for path, ie in tree_a.iter_entries_by_dir()]
75
        finally:
76
            tree_a.unlock()
77
        # The only paths left should be the root
78
        self.assertEqual([('', root_id), ('dir2', 'dir2-id'),
79
                          ('dir2/a', 'f1-id'),
80
                         ], paths)
81
2922.2.4 by John Arbash Meinel
Fix bug #114615 by teaching unversion() to not touch renamed entries.
82
    def test_no_autodelete_alternate_renamed(self):
83
        # Test for bug #114615
84
        tree_a = self.make_branch_and_tree('A')
85
        self.build_tree(['A/a/', 'A/a/m', 'A/a/n'])
86
        tree_a.add(['a', 'a/m', 'a/n'], ['a-id', 'm-id', 'n-id'])
87
        tree_a.commit('init')
88
89
        tree_a.lock_read()
90
        try:
2946.3.3 by John Arbash Meinel
Prefer tree.get_root_id() as more explicit than tree.path2id('')
91
            root_id = tree_a.get_root_id()
2922.2.4 by John Arbash Meinel
Fix bug #114615 by teaching unversion() to not touch renamed entries.
92
        finally:
93
            tree_a.unlock()
94
95
        tree_b = tree_a.bzrdir.sprout('B').open_workingtree()
96
        self.build_tree(['B/xyz/'])
97
        tree_b.add(['xyz'], ['xyz-id'])
98
        tree_b.rename_one('a/m', 'xyz/m')
99
        osutils.rmtree('B/a')
100
        tree_b.commit('delete in B')
101
102
        paths = [(path, ie.file_id)
103
                 for path, ie in tree_b.iter_entries_by_dir()]
104
        self.assertEqual([('', root_id),
105
                          ('xyz', 'xyz-id'),
106
                          ('xyz/m', 'm-id'),
107
                         ], paths)
108
109
        self.build_tree_contents([('A/a/n', 'new contents for n\n')])
110
        tree_a.commit('change n in A')
111
112
        # Merging from A should introduce conflicts because 'n' was modified
5128.1.1 by Vincent Ladeuil
Uncontroversial cleanups, mostly comments
113
        # (in A) and removed (in B), so 'a' needs to be restored.
2922.2.4 by John Arbash Meinel
Fix bug #114615 by teaching unversion() to not touch renamed entries.
114
        num_conflicts = tree_b.merge_from_branch(tree_a.branch)
115
        self.assertEqual(3, num_conflicts)
116
        paths = [(path, ie.file_id)
117
                 for path, ie in tree_b.iter_entries_by_dir()]
118
        self.assertEqual([('', root_id),
119
                          ('a', 'a-id'),
120
                          ('xyz', 'xyz-id'),
121
                          ('a/n.OTHER', 'n-id'),
122
                          ('xyz/m', 'm-id'),
123
                         ], paths)
124
        osutils.rmtree('B/a')
125
        try:
126
            # bzr resolve --all
127
            tree_b.set_conflicts(conflicts.ConflictList())
128
        except errors.UnsupportedOperation:
129
            # On WT2, set_conflicts is unsupported, but the rmtree has the same
130
            # effect.
131
            pass
132
        tree_b.commit('autoremove a, without touching xyz/m')
133
        paths = [(path, ie.file_id)
134
                 for path, ie in tree_b.iter_entries_by_dir()]
135
        self.assertEqual([('', root_id),
136
                          ('xyz', 'xyz-id'),
137
                          ('xyz/m', 'm-id'),
138
                         ], paths)
139
3602.1.1 by Robert Collins
Add support for -x or --exclude to bzr commit, fixing bug 3117. (Robert Collins)
140
    def test_commit_exclude_pending_merge_fails(self):
141
        """Excludes are a form of partial commit."""
142
        wt = self.make_branch_and_tree('.')
143
        self.build_tree(['foo'])
144
        wt.add('foo')
145
        wt.commit('commit one')
146
        wt2 = wt.bzrdir.sprout('to').open_workingtree()
147
        wt2.commit('change_right')
148
        wt.merge_from_branch(wt2.branch)
149
        self.assertRaises(errors.CannotCommitSelectedFileMerge,
150
            wt.commit, 'test', exclude=['foo'])
151
3602.1.2 by Robert Collins
Review feedback : test for PointlessCommit and that the example given in the help (excluding a subtree of a specified tree) does in fact work.
152
    def test_commit_exclude_exclude_changed_is_pointless(self):
153
        tree = self.make_branch_and_tree('.')
154
        self.build_tree(['a'])
155
        tree.smart_add(['.'])
156
        tree.commit('setup test')
157
        self.build_tree_contents([('a', 'new contents for "a"\n')])
158
        self.assertRaises(errors.PointlessCommit, tree.commit, 'test',
159
            exclude=['a'], allow_pointless=False)
160
3602.1.1 by Robert Collins
Add support for -x or --exclude to bzr commit, fixing bug 3117. (Robert Collins)
161
    def test_commit_exclude_excludes_modified_files(self):
162
        tree = self.make_branch_and_tree('.')
163
        self.build_tree(['a', 'b', 'c'])
164
        tree.smart_add(['.'])
165
        tree.commit('test', exclude=['b', 'c'])
3602.1.4 by Robert Collins
Andrew's review feedback.
166
        # If b was excluded it will still be 'added' in status.
3602.1.1 by Robert Collins
Add support for -x or --exclude to bzr commit, fixing bug 3117. (Robert Collins)
167
        tree.lock_read()
168
        self.addCleanup(tree.unlock)
169
        changes = list(tree.iter_changes(tree.basis_tree()))
170
        self.assertEqual(2, len(changes))
171
        self.assertEqual((None, 'b'), changes[0][1])
172
        self.assertEqual((None, 'c'), changes[1][1])
173
3602.1.2 by Robert Collins
Review feedback : test for PointlessCommit and that the example given in the help (excluding a subtree of a specified tree) does in fact work.
174
    def test_commit_exclude_subtree_of_selected(self):
175
        tree = self.make_branch_and_tree('.')
176
        self.build_tree(['a/', 'a/b'])
177
        tree.smart_add(['.'])
3603.1.1 by Robert Collins
Further tweaks to tests and comments in the commit excludes feature.
178
        tree.commit('test', specific_files=['a'], exclude=['a/b'])
3602.1.4 by Robert Collins
Andrew's review feedback.
179
        # If a/b was excluded it will still be 'added' in status.
3602.1.2 by Robert Collins
Review feedback : test for PointlessCommit and that the example given in the help (excluding a subtree of a specified tree) does in fact work.
180
        tree.lock_read()
181
        self.addCleanup(tree.unlock)
182
        changes = list(tree.iter_changes(tree.basis_tree()))
183
        self.assertEqual(1, len(changes))
184
        self.assertEqual((None, 'a/b'), changes[0][1])
185
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
186
    def test_commit_sets_last_revision(self):
187
        tree = self.make_branch_and_tree('tree')
2825.5.2 by Robert Collins
Review feedback, and fix pointless commits with nested trees to raise PointlessCommit appropriately.
188
        committed_id = tree.commit('foo', rev_id='foo')
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
189
        self.assertEqual(['foo'], tree.get_parent_ids())
1773.1.1 by Robert Collins
Teach WorkingTree.commit to return the committed revision id.
190
        # the commit should have returned the same id we asked for.
191
        self.assertEqual('foo', committed_id)
192
193
    def test_commit_returns_revision_id(self):
194
        tree = self.make_branch_and_tree('.')
2825.5.2 by Robert Collins
Review feedback, and fix pointless commits with nested trees to raise PointlessCommit appropriately.
195
        committed_id = tree.commit('message')
1773.1.1 by Robert Collins
Teach WorkingTree.commit to return the committed revision id.
196
        self.assertTrue(tree.branch.repository.has_revision(committed_id))
197
        self.assertNotEqual(None, committed_id)
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
198
199
    def test_commit_local_unbound(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
200
        # using the library api to do a local commit on unbound branches is
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
201
        # also an error
202
        tree = self.make_branch_and_tree('tree')
203
        self.assertRaises(errors.LocalRequiresBoundBranch,
204
                          tree.commit,
205
                          'foo',
206
                          local=True)
2374.2.1 by John Arbash Meinel
(broken) merge a test case showing that commiting a merge of a kind change fails.
207
208
    def test_commit_merged_kind_change(self):
209
        """Test merging a kind change.
210
211
        Test making a kind change in a working tree, and then merging that
212
        from another. When committed it should commit the new kind.
213
        """
214
        wt = self.make_branch_and_tree('.')
215
        self.build_tree(['a'])
216
        wt.add(['a'])
217
        wt.commit('commit one')
218
        wt2 = wt.bzrdir.sprout('to').open_workingtree()
219
        os.remove('a')
220
        os.mkdir('a')
221
        wt.commit('changed kind')
222
        wt2.merge_from_branch(wt.branch)
223
        wt2.commit('merged kind change')
224
4536.3.1 by Robert Collins
Defer doing unversioning of file ids during commit to after completing branch operations. (Robert Collins, bug 282402)
225
    def test_commit_aborted_does_not_apply_automatic_changes_bug_282402(self):
226
        wt = self.make_branch_and_tree('.')
227
        wt.add(['a'], ['a-id'], ['file'])
228
        def fail_message(obj):
229
            raise errors.BzrCommandError("empty commit message")
230
        self.assertRaises(errors.BzrCommandError, wt.commit,
231
            message_callback=fail_message)
232
        self.assertEqual('a', wt.id2path('a-id'))
233
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
234
    def test_local_commit_ignores_master(self):
235
        # a --local commit does not require access to the master branch
236
        # at all, or even for it to exist.
237
        # we test this by setting up a bound branch and then corrupting
238
        # the master.
239
        master = self.make_branch('master')
240
        tree = self.make_branch_and_tree('tree')
241
        try:
242
            tree.branch.bind(master)
243
        except errors.UpgradeRequired:
244
            # older format.
245
            return
1955.3.14 by John Arbash Meinel
Correctly fix the workingtree put() test fixes
246
        master.bzrdir.transport.put_bytes('branch-format', 'garbage')
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
247
        del master
248
        # check its corrupted.
249
        self.assertRaises(errors.UnknownFormatError,
250
                          bzrdir.BzrDir.open,
251
                          'master')
252
        tree.commit('foo', rev_id='foo', local=True)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
253
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
254
    def test_local_commit_does_not_push_to_master(self):
255
        # a --local commit does not require access to the master branch
256
        # at all, or even for it to exist.
257
        # we test that even when its available it does not push to it.
258
        master = self.make_branch('master')
259
        tree = self.make_branch_and_tree('tree')
260
        try:
261
            tree.branch.bind(master)
262
        except errors.UpgradeRequired:
263
            # older format.
264
            return
265
        tree.commit('foo', rev_id='foo', local=True)
266
        self.failIf(master.repository.has_revision('foo'))
2598.5.7 by Aaron Bentley
Updates from review
267
        self.assertEqual(_mod_revision.NULL_REVISION,
268
                         (_mod_revision.ensure_null(master.last_revision())))
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
269
270
    def test_record_initial_ghost(self):
271
        """The working tree needs to record ghosts during commit."""
272
        wt = self.make_branch_and_tree('.')
1908.6.7 by Robert Collins
Remove all users of set_pending_merges and add_pending_merge except tests that they work correctly.
273
        wt.set_parent_ids(['non:existent@rev--ision--0--2'],
274
            allow_leftmost_as_ghost=True)
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
275
        rev_id = wt.commit('commit against a ghost first parent.')
276
        rev = wt.branch.repository.get_revision(rev_id)
277
        self.assertEqual(rev.parent_ids, ['non:existent@rev--ision--0--2'])
278
        # parent_sha1s is not populated now, WTF. rbc 20051003
279
        self.assertEqual(len(rev.parent_sha1s), 0)
280
281
    def test_record_two_ghosts(self):
282
        """The working tree should preserve all the parents during commit."""
283
        wt = self.make_branch_and_tree('.')
1908.6.7 by Robert Collins
Remove all users of set_pending_merges and add_pending_merge except tests that they work correctly.
284
        wt.set_parent_ids([
285
                'foo@azkhazan-123123-abcabc',
286
                'wibble@fofof--20050401--1928390812',
287
            ],
288
            allow_leftmost_as_ghost=True)
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
289
        rev_id = wt.commit("commit from ghost base with one merge")
290
        # the revision should have been committed with two parents
291
        rev = wt.branch.repository.get_revision(rev_id)
292
        self.assertEqual(['foo@azkhazan-123123-abcabc',
293
            'wibble@fofof--20050401--1928390812'],
294
            rev.parent_ids)
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
295
1988.3.1 by Robert Collins
Add test case to ensure that the working tree inventory and disk state is correctly update when commit is removing directory entries.
296
    def test_commit_deleted_subtree_and_files_updates_workingtree(self):
297
        """The working trees inventory may be adjusted by commit."""
298
        wt = self.make_branch_and_tree('.')
299
        wt.lock_write()
300
        self.build_tree(['a', 'b/', 'b/c', 'd'])
301
        wt.add(['a', 'b', 'b/c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])
302
        this_dir = self.get_transport()
303
        this_dir.delete_tree('b')
304
        this_dir.delete('d')
305
        # now we have a tree with a through d in the inventory, but only
306
        # a present on disk. After commit b-id, c-id and d-id should be
307
        # missing from the inventory, within the same tree transaction.
308
        wt.commit('commit stuff')
309
        self.assertTrue(wt.has_id('a-id'))
310
        self.assertFalse(wt.has_or_had_id('b-id'))
311
        self.assertFalse(wt.has_or_had_id('c-id'))
312
        self.assertFalse(wt.has_or_had_id('d-id'))
313
        self.assertTrue(wt.has_filename('a'))
314
        self.assertFalse(wt.has_filename('b'))
315
        self.assertFalse(wt.has_filename('b/c'))
316
        self.assertFalse(wt.has_filename('d'))
317
        wt.unlock()
318
        # the changes should have persisted to disk - reopen the workingtree
319
        # to be sure.
320
        wt = wt.bzrdir.open_workingtree()
321
        wt.lock_read()
322
        self.assertTrue(wt.has_id('a-id'))
323
        self.assertFalse(wt.has_or_had_id('b-id'))
324
        self.assertFalse(wt.has_or_had_id('c-id'))
325
        self.assertFalse(wt.has_or_had_id('d-id'))
326
        self.assertTrue(wt.has_filename('a'))
327
        self.assertFalse(wt.has_filename('b'))
328
        self.assertFalse(wt.has_filename('b/c'))
329
        self.assertFalse(wt.has_filename('d'))
330
        wt.unlock()
1731.2.4 by Aaron Bentley
Ensure subsume works with Knit2 repos
331
2363.2.2 by John Arbash Meinel
Simplify the test even further....
332
    def test_commit_deleted_subtree_with_removed(self):
2363.2.1 by John Arbash Meinel
(broken) Add a simplified test which exposes the bug.
333
        wt = self.make_branch_and_tree('.')
334
        self.build_tree(['a', 'b/', 'b/c', 'd'])
335
        wt.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
336
        wt.commit('first')
2363.2.2 by John Arbash Meinel
Simplify the test even further....
337
        wt.remove('b/c')
2363.2.1 by John Arbash Meinel
(broken) Add a simplified test which exposes the bug.
338
        this_dir = self.get_transport()
339
        this_dir.delete_tree('b')
340
        wt.lock_write()
341
        wt.commit('commit deleted rename')
342
        self.assertTrue(wt.has_id('a-id'))
343
        self.assertFalse(wt.has_or_had_id('b-id'))
344
        self.assertFalse(wt.has_or_had_id('c-id'))
345
        self.assertTrue(wt.has_filename('a'))
346
        self.assertFalse(wt.has_filename('b'))
347
        self.assertFalse(wt.has_filename('b/c'))
348
        wt.unlock()
349
1731.2.4 by Aaron Bentley
Ensure subsume works with Knit2 repos
350
    def test_commit_move_new(self):
351
        wt = self.make_branch_and_tree('first')
352
        wt.commit('first')
353
        wt2 = wt.bzrdir.sprout('second').open_workingtree()
354
        self.build_tree(['second/name1'])
355
        wt2.add('name1', 'name1-id')
356
        wt2.commit('second')
357
        wt.merge_from_branch(wt2.branch)
358
        wt.rename_one('name1', 'name2')
359
        wt.commit('third')
360
        wt.path2id('name1-id')
2255.2.218 by Robert Collins
Make the nested tree commit smoke test be more rigourous.
361
362
    def test_nested_commit(self):
363
        """Commit in multiply-nested trees"""
364
        tree = self.make_branch_and_tree('.')
365
        if not tree.supports_tree_reference():
366
            # inapplicable test.
367
            return
368
        subtree = self.make_branch_and_tree('subtree')
369
        subsubtree = self.make_branch_and_tree('subtree/subtree')
370
        subtree.add(['subtree'])
371
        tree.add(['subtree'])
372
        # use allow_pointless=False to ensure that the deepest tree, which
373
        # has no commits made to it, does not get a pointless commit.
374
        rev_id = tree.commit('added reference', allow_pointless=False)
375
        tree.lock_read()
376
        self.addCleanup(tree.unlock)
377
        # the deepest subtree has not changed, so no commit should take place.
2598.5.10 by Aaron Bentley
Return NULL_REVISION instead of None for the null revision
378
        self.assertEqual('null:', subsubtree.last_revision())
2255.2.218 by Robert Collins
Make the nested tree commit smoke test be more rigourous.
379
        # the intermediate tree should have committed a pointer to the current
380
        # subtree revision.
381
        sub_basis = subtree.basis_tree()
382
        sub_basis.lock_read()
383
        self.addCleanup(sub_basis.unlock)
384
        self.assertEqual(subsubtree.last_revision(),
2255.2.227 by Robert Collins
Make all test_commit tests pass.
385
            sub_basis.get_reference_revision(sub_basis.path2id('subtree')))
2255.2.218 by Robert Collins
Make the nested tree commit smoke test be more rigourous.
386
        # the intermediate tree has changed, so should have had a commit
387
        # take place.
388
        self.assertNotEqual(None, subtree.last_revision())
389
        # the outer tree should have committed a pointer to the current
390
        # subtree revision.
391
        basis = tree.basis_tree()
392
        basis.lock_read()
393
        self.addCleanup(basis.unlock)
394
        self.assertEqual(subtree.last_revision(),
2255.2.226 by Robert Collins
Get merge_nested finally working: change nested tree iterators to take file_ids, and ensure the right branch is connected to in the merge logic. May not be suitable for shared repositories yet.
395
            basis.get_reference_revision(basis.path2id('subtree')))
2255.2.218 by Robert Collins
Make the nested tree commit smoke test be more rigourous.
396
        # the outer tree must have have changed too.
397
        self.assertNotEqual(None, rev_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
398
2255.2.220 by Robert Collins
Fix failing detection of changes restricted to subtrees causing spurious pointless commit errors.
399
    def test_nested_commit_second_commit_detects_changes(self):
400
        """Commit with a nested tree picks up the correct child revid."""
401
        tree = self.make_branch_and_tree('.')
402
        if not tree.supports_tree_reference():
403
            # inapplicable test.
404
            return
405
        subtree = self.make_branch_and_tree('subtree')
406
        tree.add(['subtree'])
407
        self.build_tree(['subtree/file'])
408
        subtree.add(['file'], ['file-id'])
409
        rev_id = tree.commit('added reference', allow_pointless=False)
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
410
        tree.get_reference_revision(tree.path2id('subtree'))
2255.2.220 by Robert Collins
Fix failing detection of changes restricted to subtrees causing spurious pointless commit errors.
411
        child_revid = subtree.last_revision()
412
        # now change the child tree
413
        self.build_tree_contents([('subtree/file', 'new-content')])
414
        # and commit in the parent should commit the child and grab its revid,
415
        # we test with allow_pointless=False here so that we are simulating
416
        # what users will see.
417
        rev_id2 = tree.commit('changed subtree only', allow_pointless=False)
418
        # the child tree has changed, so should have had a commit
419
        # take place.
420
        self.assertNotEqual(None, subtree.last_revision())
421
        self.assertNotEqual(child_revid, subtree.last_revision())
422
        # the outer tree should have committed a pointer to the current
423
        # subtree revision.
424
        basis = tree.basis_tree()
425
        basis.lock_read()
426
        self.addCleanup(basis.unlock)
427
        self.assertEqual(subtree.last_revision(),
2255.2.226 by Robert Collins
Get merge_nested finally working: change nested tree iterators to take file_ids, and ensure the right branch is connected to in the merge logic. May not be suitable for shared repositories yet.
428
            basis.get_reference_revision(basis.path2id('subtree')))
2255.2.220 by Robert Collins
Fix failing detection of changes restricted to subtrees causing spurious pointless commit errors.
429
        self.assertNotEqual(rev_id, rev_id2)
430
2825.5.2 by Robert Collins
Review feedback, and fix pointless commits with nested trees to raise PointlessCommit appropriately.
431
    def test_nested_pointless_commits_are_pointless(self):
432
        tree = self.make_branch_and_tree('.')
433
        if not tree.supports_tree_reference():
434
            # inapplicable test.
435
            return
436
        subtree = self.make_branch_and_tree('subtree')
437
        tree.add(['subtree'])
438
        # record the reference.
439
        rev_id = tree.commit('added reference')
440
        child_revid = subtree.last_revision()
441
        # now do a no-op commit with allow_pointless=False
442
        self.assertRaises(errors.PointlessCommit, tree.commit, '',
443
            allow_pointless=False)
444
        self.assertEqual(child_revid, subtree.last_revision())
445
        self.assertEqual(rev_id, tree.last_revision())
446
1988.3.1 by Robert Collins
Add test case to ensure that the working tree inventory and disk state is correctly update when commit is removing directory entries.
447
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
448
class TestCommitProgress(TestCaseWithWorkingTree):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
449
4985.2.1 by Vincent Ladeuil
Deploy addAttrCleanup on the whole test suite.
450
    def setUp(self):
451
        super(TestCommitProgress, self).setUp()
5422.1.4 by Martin Pool
Rename CapturingUIFactory to ProgressRecordingUIFactory
452
        ui.ui_factory = ProgressRecordingUIFactory()
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
453
454
    def test_commit_progress_steps(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
455
        # during commit we one progress update for every entry in the
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
456
        # inventory, and then one for the inventory, and one for the
457
        # inventory, and one for the revision insertions.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
458
        # first we need a test commit to do. Lets setup a branch with
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
459
        # 3 files, and alter one in a selected-file commit. This exercises
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
460
        # a number of cases quickly. We should also test things like
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
461
        # selective commits which excludes newly added files.
462
        tree = self.make_branch_and_tree('.')
463
        self.build_tree(['a', 'b', 'c'])
464
        tree.add(['a', 'b', 'c'])
465
        tree.commit('first post')
466
        f = file('b', 'wt')
467
        f.write('new content')
468
        f.close()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
469
        # set a progress bar that captures the calls so we can see what is
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
470
        # emitted
5422.1.4 by Martin Pool
Rename CapturingUIFactory to ProgressRecordingUIFactory
471
        factory = ProgressRecordingUIFactory()
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
472
        ui.ui_factory = factory
473
        # TODO RBC 20060421 it would be nice to merge the reporter output
474
        # into the factory for this test - just make the test ui factory
475
        # pun as a reporter. Then we can check the ordering is right.
476
        tree.commit('second post', specific_files=['b'])
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
477
        # 5 steps, the first of which is reported 2 times, once per dir
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
478
        self.assertEqual(
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
479
            [('update', 1, 5, 'Collecting changes [0] - Stage'),
480
             ('update', 1, 5, 'Collecting changes [1] - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
481
             ('update', 2, 5, 'Saving data locally - Stage'),
2659.3.9 by NamNguyen
branch.py:
482
             ('update', 3, 5, 'Running pre_commit hooks - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
483
             ('update', 4, 5, 'Updating the working tree - Stage'),
2659.3.9 by NamNguyen
branch.py:
484
             ('update', 5, 5, 'Running post_commit hooks - Stage')],
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
485
            factory._calls
486
           )
2553.1.2 by Robert Collins
Show hook names during commit.
487
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
488
    def test_commit_progress_shows_post_hook_names(self):
2553.1.2 by Robert Collins
Show hook names during commit.
489
        tree = self.make_branch_and_tree('.')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
490
        # set a progress bar that captures the calls so we can see what is
2553.1.2 by Robert Collins
Show hook names during commit.
491
        # emitted
5422.1.4 by Martin Pool
Rename CapturingUIFactory to ProgressRecordingUIFactory
492
        factory = ProgressRecordingUIFactory()
2553.1.2 by Robert Collins
Show hook names during commit.
493
        ui.ui_factory = factory
494
        def a_hook(_, _2, _3, _4, _5, _6):
495
            pass
3256.2.19 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.workingtree_implementations.test_commit.
496
        branch.Branch.hooks.install_named_hook('post_commit', a_hook,
497
                                               'hook name')
2553.1.2 by Robert Collins
Show hook names during commit.
498
        tree.commit('first post')
499
        self.assertEqual(
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
500
            [('update', 1, 5, 'Collecting changes [0] - Stage'),
501
             ('update', 1, 5, 'Collecting changes [1] - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
502
             ('update', 2, 5, 'Saving data locally - Stage'),
2659.3.9 by NamNguyen
branch.py:
503
             ('update', 3, 5, 'Running pre_commit hooks - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
504
             ('update', 4, 5, 'Updating the working tree - Stage'),
2659.3.9 by NamNguyen
branch.py:
505
             ('update', 5, 5, 'Running post_commit hooks - Stage'),
506
             ('update', 5, 5, 'Running post_commit hooks [hook name] - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
507
             ],
508
            factory._calls
509
           )
510
511
    def test_commit_progress_shows_pre_hook_names(self):
512
        tree = self.make_branch_and_tree('.')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
513
        # set a progress bar that captures the calls so we can see what is
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
514
        # emitted
5422.1.4 by Martin Pool
Rename CapturingUIFactory to ProgressRecordingUIFactory
515
        factory = ProgressRecordingUIFactory()
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
516
        ui.ui_factory = factory
2659.3.3 by NamNguyen
Changed ``pre_commit`` hook signature.
517
        def a_hook(_, _2, _3, _4, _5, _6, _7, _8):
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
518
            pass
3256.2.19 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.workingtree_implementations.test_commit.
519
        branch.Branch.hooks.install_named_hook('pre_commit', a_hook,
520
                                               'hook name')
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
521
        tree.commit('first post')
522
        self.assertEqual(
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
523
            [('update', 1, 5, 'Collecting changes [0] - Stage'),
524
             ('update', 1, 5, 'Collecting changes [1] - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
525
             ('update', 2, 5, 'Saving data locally - Stage'),
2659.3.9 by NamNguyen
branch.py:
526
             ('update', 3, 5, 'Running pre_commit hooks - Stage'),
527
             ('update', 3, 5, 'Running pre_commit hooks [hook name] - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
528
             ('update', 4, 5, 'Updating the working tree - Stage'),
2659.3.9 by NamNguyen
branch.py:
529
             ('update', 5, 5, 'Running post_commit hooks - Stage'),
2659.3.1 by NamNguyen
``Branch.hooks`` now supports ``pre_commit`` hook.
530
             ],
531
            factory._calls
532
           )
3335.1.3 by Jelmer Vernooij
Add tests for start_commit hook.
533
534
    def test_start_commit_hook(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
535
        """Make sure a start commit hook can modify the tree that is
3335.1.3 by Jelmer Vernooij
Add tests for start_commit hook.
536
        committed."""
537
        def start_commit_hook_adds_file(tree):
538
            open(tree.abspath("newfile"), 'w').write("data")
539
            tree.add(["newfile"])
540
        def restoreDefaults():
541
            mutabletree.MutableTree.hooks['start_commit'] = []
542
        self.addCleanup(restoreDefaults)
543
        tree = self.make_branch_and_tree('.')
3256.2.26 by Daniel Watkins
Updated tests to use install_named_hook.
544
        mutabletree.MutableTree.hooks.install_named_hook(
545
            'start_commit',
546
            start_commit_hook_adds_file,
547
            None)
3335.1.3 by Jelmer Vernooij
Add tests for start_commit hook.
548
        revid = tree.commit('first post')
549
        committed_tree = tree.basis_tree()
550
        self.assertTrue(committed_tree.has_filename("newfile"))
4634.33.1 by Ian Clatworthy
original finish_commit hook patch
551
4634.33.3 by Ian Clatworthy
review feedback from Robert: rename finish_commit to post_commit
552
    def test_post_commit_hook(self):
553
        """Make sure a post_commit hook is called after a commit."""
554
        def post_commit_hook_test_params(params):
4634.33.2 by Ian Clatworthy
review feedback from jam
555
            self.assertTrue(isinstance(params,
4634.33.3 by Ian Clatworthy
review feedback from Robert: rename finish_commit to post_commit
556
                mutabletree.PostCommitHookParams))
4634.33.2 by Ian Clatworthy
review feedback from jam
557
            self.assertTrue(isinstance(params.mutable_tree,
558
                mutabletree.MutableTree))
4634.33.1 by Ian Clatworthy
original finish_commit hook patch
559
            open(tree.abspath("newfile"), 'w').write("data")
4634.33.2 by Ian Clatworthy
review feedback from jam
560
            params.mutable_tree.add(["newfile"])
4634.33.1 by Ian Clatworthy
original finish_commit hook patch
561
        tree = self.make_branch_and_tree('.')
562
        mutabletree.MutableTree.hooks.install_named_hook(
4634.33.3 by Ian Clatworthy
review feedback from Robert: rename finish_commit to post_commit
563
            'post_commit',
564
            post_commit_hook_test_params,
4634.33.1 by Ian Clatworthy
original finish_commit hook patch
565
            None)
566
        self.assertFalse(tree.has_filename("newfile"))
567
        revid = tree.commit('first post')
568
        self.assertTrue(tree.has_filename("newfile"))
569
        committed_tree = tree.basis_tree()
570
        self.assertFalse(committed_tree.has_filename("newfile"))