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