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