~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1246 by Martin Pool
- add very simple commit tests
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1246 by Martin Pool
- add very simple commit tests
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1246 by Martin Pool
- add very simple commit tests
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
18
import os
19
1472 by Robert Collins
post commit hook, first pass implementation
20
import bzrlib
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
21
from bzrlib import (
22
    errors,
23
    lockdir,
1959.4.3 by Aaron Bentley
Merge bzr.dev
24
    osutils,
25
    tests,
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
26
    )
1246 by Martin Pool
- add very simple commit tests
27
from bzrlib.branch import Branch
1614.1.1 by Aaron Bentley
Fixed master locking in commit
28
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
29
from bzrlib.commit import Commit, NullCommitReporter
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
30
from bzrlib.config import BranchConfig
1614.1.1 by Aaron Bentley
Fixed master locking in commit
31
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed, 
32
                           LockContention)
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
33
from bzrlib.tests import TestCaseWithTransport
34
from bzrlib.workingtree import WorkingTree
1246 by Martin Pool
- add very simple commit tests
35
36
1257 by Martin Pool
doc
37
# TODO: Test commit with some added, and added-but-missing files
38
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
39
class MustSignConfig(BranchConfig):
40
41
    def signature_needed(self):
42
        return True
43
44
    def gpg_signing_command(self):
45
        return ['cat', '-']
46
47
1472 by Robert Collins
post commit hook, first pass implementation
48
class BranchWithHooks(BranchConfig):
49
50
    def post_commit(self):
51
        return "bzrlib.ahook bzrlib.ahook"
52
53
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
54
class CapturingReporter(NullCommitReporter):
55
    """This reporter captures the calls made to it for evaluation later."""
56
57
    def __init__(self):
58
        # a list of the calls this received
59
        self.calls = []
60
61
    def snapshot_change(self, change, path):
62
        self.calls.append(('change', change, path))
63
64
    def deleted(self, file_id):
65
        self.calls.append(('deleted', file_id))
66
67
    def missing(self, path):
68
        self.calls.append(('missing', path))
69
70
    def renamed(self, change, old_path, new_path):
71
        self.calls.append(('renamed', change, old_path, new_path))
72
73
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
74
class TestCommit(TestCaseWithTransport):
1390 by Robert Collins
pair programming worx... merge integration and weave
75
1246 by Martin Pool
- add very simple commit tests
76
    def test_simple_commit(self):
77
        """Commit and check two versions of a single file."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
78
        wt = self.make_branch_and_tree('.')
79
        b = wt.branch
1246 by Martin Pool
- add very simple commit tests
80
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
81
        wt.add('hello')
82
        wt.commit(message='add hello')
83
        file_id = wt.path2id('hello')
1246 by Martin Pool
- add very simple commit tests
84
85
        file('hello', 'w').write('version 2')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
86
        wt.commit(message='commit 2')
1246 by Martin Pool
- add very simple commit tests
87
88
        eq = self.assertEquals
89
        eq(b.revno(), 2)
90
        rh = b.revision_history()
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
91
        rev = b.repository.get_revision(rh[0])
1246 by Martin Pool
- add very simple commit tests
92
        eq(rev.message, 'add hello')
93
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
94
        tree1 = b.repository.revision_tree(rh[0])
1246 by Martin Pool
- add very simple commit tests
95
        text = tree1.get_file_text(file_id)
96
        eq(text, 'hello world')
97
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
98
        tree2 = b.repository.revision_tree(rh[1])
1246 by Martin Pool
- add very simple commit tests
99
        eq(tree2.get_file_text(file_id), 'version 2')
100
101
    def test_delete_commit(self):
102
        """Test a commit with a deleted file"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
103
        wt = self.make_branch_and_tree('.')
104
        b = wt.branch
1247 by Martin Pool
- tests for deletion and removal of files in commits
105
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
106
        wt.add(['hello'], ['hello-id'])
107
        wt.commit(message='add hello')
1247 by Martin Pool
- tests for deletion and removal of files in commits
108
109
        os.remove('hello')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
110
        wt.commit('removed hello', rev_id='rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
111
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
112
        tree = b.repository.revision_tree('rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
113
        self.assertFalse(tree.has_id('hello-id'))
114
1253 by Martin Pool
- test that pointless commits are trapped
115
    def test_pointless_commit(self):
116
        """Commit refuses unless there are changes or it's forced."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
117
        wt = self.make_branch_and_tree('.')
118
        b = wt.branch
1253 by Martin Pool
- test that pointless commits are trapped
119
        file('hello', 'w').write('hello')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
120
        wt.add(['hello'])
121
        wt.commit(message='add hello')
1253 by Martin Pool
- test that pointless commits are trapped
122
        self.assertEquals(b.revno(), 1)
123
        self.assertRaises(PointlessCommit,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
124
                          wt.commit,
1253 by Martin Pool
- test that pointless commits are trapped
125
                          message='fails',
126
                          allow_pointless=False)
127
        self.assertEquals(b.revno(), 1)
128
        
1252 by Martin Pool
- add test for commit of an empty tree
129
    def test_commit_empty(self):
1253 by Martin Pool
- test that pointless commits are trapped
130
        """Commiting an empty tree works."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
131
        wt = self.make_branch_and_tree('.')
132
        b = wt.branch
133
        wt.commit(message='empty tree', allow_pointless=True)
1253 by Martin Pool
- test that pointless commits are trapped
134
        self.assertRaises(PointlessCommit,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
135
                          wt.commit,
1253 by Martin Pool
- test that pointless commits are trapped
136
                          message='empty tree',
137
                          allow_pointless=False)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
138
        wt.commit(message='empty tree', allow_pointless=True)
1252 by Martin Pool
- add test for commit of an empty tree
139
        self.assertEquals(b.revno(), 2)
140
141
    def test_selective_delete(self):
142
        """Selective commit in tree with deletions"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
143
        wt = self.make_branch_and_tree('.')
144
        b = wt.branch
1254 by Martin Pool
- fix handling of selective commit with deleted files
145
        file('hello', 'w').write('hello')
146
        file('buongia', 'w').write('buongia')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
147
        wt.add(['hello', 'buongia'],
1255 by Martin Pool
- more tests for selective commit of deletion
148
              ['hello-id', 'buongia-id'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
149
        wt.commit(message='add files',
1255 by Martin Pool
- more tests for selective commit of deletion
150
                 rev_id='test@rev-1')
1254 by Martin Pool
- fix handling of selective commit with deleted files
151
        
152
        os.remove('hello')
153
        file('buongia', 'w').write('new text')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
154
        wt.commit(message='update text',
1254 by Martin Pool
- fix handling of selective commit with deleted files
155
                 specific_files=['buongia'],
1255 by Martin Pool
- more tests for selective commit of deletion
156
                 allow_pointless=False,
157
                 rev_id='test@rev-2')
1254 by Martin Pool
- fix handling of selective commit with deleted files
158
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
159
        wt.commit(message='remove hello',
1254 by Martin Pool
- fix handling of selective commit with deleted files
160
                 specific_files=['hello'],
1255 by Martin Pool
- more tests for selective commit of deletion
161
                 allow_pointless=False,
162
                 rev_id='test@rev-3')
1254 by Martin Pool
- fix handling of selective commit with deleted files
163
164
        eq = self.assertEquals
165
        eq(b.revno(), 3)
1255 by Martin Pool
- more tests for selective commit of deletion
166
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
167
        tree2 = b.repository.revision_tree('test@rev-2')
1255 by Martin Pool
- more tests for selective commit of deletion
168
        self.assertTrue(tree2.has_filename('hello'))
169
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
170
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
171
        
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
172
        tree3 = b.repository.revision_tree('test@rev-3')
1255 by Martin Pool
- more tests for selective commit of deletion
173
        self.assertFalse(tree3.has_filename('hello'))
174
        self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
175
176
    def test_commit_rename(self):
177
        """Test commit of a revision where a file is renamed."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
178
        tree = self.make_branch_and_tree('.')
179
        b = tree.branch
1185.38.7 by John Arbash Meinel
Updated build_tree to use fixed line-endings for tests which read the file contents and compare
180
        self.build_tree(['hello'], line_endings='binary')
1508.1.7 by Robert Collins
Move rename_one from Branch to WorkingTree. (Robert Collins).
181
        tree.add(['hello'], ['hello-id'])
182
        tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
183
1508.1.7 by Robert Collins
Move rename_one from Branch to WorkingTree. (Robert Collins).
184
        tree.rename_one('hello', 'fruity')
185
        tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
186
1303 by Martin Pool
- commit updates entry_version
187
        eq = self.assertEquals
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
188
        tree1 = b.repository.revision_tree('test@rev-1')
1303 by Martin Pool
- commit updates entry_version
189
        eq(tree1.id2path('hello-id'), 'hello')
190
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
191
        self.assertFalse(tree1.has_filename('fruity'))
1291 by Martin Pool
- add test for moving files between directories
192
        self.check_inventory_shape(tree1.inventory, ['hello'])
1303 by Martin Pool
- commit updates entry_version
193
        ie = tree1.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
194
        eq(ie.revision, 'test@rev-1')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
195
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
196
        tree2 = b.repository.revision_tree('test@rev-2')
1303 by Martin Pool
- commit updates entry_version
197
        eq(tree2.id2path('hello-id'), 'fruity')
198
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
1291 by Martin Pool
- add test for moving files between directories
199
        self.check_inventory_shape(tree2.inventory, ['fruity'])
1303 by Martin Pool
- commit updates entry_version
200
        ie = tree2.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
201
        eq(ie.revision, 'test@rev-2')
1291 by Martin Pool
- add test for moving files between directories
202
203
    def test_reused_rev_id(self):
1292 by Martin Pool
- add check that revision ids cannot be committed twice
204
        """Test that a revision id cannot be reused in a branch"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
205
        wt = self.make_branch_and_tree('.')
206
        b = wt.branch
207
        wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
1292 by Martin Pool
- add check that revision ids cannot be committed twice
208
        self.assertRaises(Exception,
1534.4.35 by Robert Collins
Give branch its own basis tree and last_revision methods; deprecated branch.working_tree()
209
                          wt.commit,
1292 by Martin Pool
- add check that revision ids cannot be committed twice
210
                          message='reused id',
211
                          rev_id='test@rev-1',
212
                          allow_pointless=True)
1291 by Martin Pool
- add test for moving files between directories
213
214
    def test_commit_move(self):
215
        """Test commit of revisions with moved files and directories"""
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
216
        eq = self.assertEquals
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
217
        wt = self.make_branch_and_tree('.')
218
        b = wt.branch
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
219
        r1 = 'test@rev-1'
1291 by Martin Pool
- add test for moving files between directories
220
        self.build_tree(['hello', 'a/', 'b/'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
221
        wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
222
        wt.commit('initial', rev_id=r1, allow_pointless=False)
223
        wt.move(['hello'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
224
        r2 = 'test@rev-2'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
225
        wt.commit('two', rev_id=r2, allow_pointless=False)
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
226
        wt.lock_read()
227
        try:
228
            self.check_inventory_shape(wt.read_working_inventory(),
229
                                       ['a', 'a/hello', 'b'])
230
        finally:
231
            wt.unlock()
1291 by Martin Pool
- add test for moving files between directories
232
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
233
        wt.move(['b'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
234
        r3 = 'test@rev-3'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
235
        wt.commit('three', rev_id=r3, allow_pointless=False)
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
236
        wt.lock_read()
237
        try:
238
            self.check_inventory_shape(wt.read_working_inventory(),
239
                                       ['a', 'a/hello', 'a/b'])
240
            self.check_inventory_shape(b.repository.get_revision_inventory(r3),
241
                                       ['a', 'a/hello', 'a/b'])
242
        finally:
243
            wt.unlock()
1291 by Martin Pool
- add test for moving files between directories
244
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
245
        wt.move(['a/hello'], 'a/b')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
246
        r4 = 'test@rev-4'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
247
        wt.commit('four', rev_id=r4, allow_pointless=False)
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
248
        wt.lock_read()
249
        try:
250
            self.check_inventory_shape(wt.read_working_inventory(),
251
                                       ['a', 'a/b/hello', 'a/b'])
252
        finally:
253
            wt.unlock()
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
254
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
255
        inv = b.repository.get_revision_inventory(r4)
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
256
        eq(inv['hello-id'].revision, r4)
257
        eq(inv['a-id'].revision, r1)
258
        eq(inv['b-id'].revision, r3)
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
259
1246 by Martin Pool
- add very simple commit tests
260
    def test_removed_commit(self):
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
261
        """Commit with a removed file"""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
262
        wt = self.make_branch_and_tree('.')
263
        b = wt.branch
1247 by Martin Pool
- tests for deletion and removal of files in commits
264
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
265
        wt.add(['hello'], ['hello-id'])
266
        wt.commit(message='add hello')
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
267
        wt.remove('hello')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
268
        wt.commit('removed hello', rev_id='rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
269
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
270
        tree = b.repository.revision_tree('rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
271
        self.assertFalse(tree.has_id('hello-id'))
1246 by Martin Pool
- add very simple commit tests
272
1256 by Martin Pool
- test that commits append to the tree's ancestry
273
    def test_committed_ancestry(self):
274
        """Test commit appends revisions to ancestry."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
275
        wt = self.make_branch_and_tree('.')
276
        b = wt.branch
1256 by Martin Pool
- test that commits append to the tree's ancestry
277
        rev_ids = []
278
        for i in range(4):
279
            file('hello', 'w').write((str(i) * 4) + '\n')
280
            if i == 0:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
281
                wt.add(['hello'], ['hello-id'])
1256 by Martin Pool
- test that commits append to the tree's ancestry
282
            rev_id = 'test@rev-%d' % (i+1)
283
            rev_ids.append(rev_id)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
284
            wt.commit(message='rev %d' % (i+1),
1256 by Martin Pool
- test that commits append to the tree's ancestry
285
                     rev_id=rev_id)
286
        eq = self.assertEquals
287
        eq(b.revision_history(), rev_ids)
288
        for i in range(4):
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
289
            anc = b.repository.get_ancestry(rev_ids[i])
1390 by Robert Collins
pair programming worx... merge integration and weave
290
            eq(anc, [None] + rev_ids[:i+1])
1416 by Robert Collins
when committing a specific file, include all its parents
291
292
    def test_commit_new_subdir_child_selective(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
293
        wt = self.make_branch_and_tree('.')
294
        b = wt.branch
1416 by Robert Collins
when committing a specific file, include all its parents
295
        self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
296
        wt.add(['dir', 'dir/file1', 'dir/file2'],
1416 by Robert Collins
when committing a specific file, include all its parents
297
              ['dirid', 'file1id', 'file2id'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
298
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
299
        inv = b.repository.get_inventory('1')
1416 by Robert Collins
when committing a specific file, include all its parents
300
        self.assertEqual('1', inv['dirid'].revision)
301
        self.assertEqual('1', inv['file1id'].revision)
302
        # FIXME: This should raise a KeyError I think, rbc20051006
303
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
304
305
    def test_strict_commit(self):
306
        """Try and commit with unknown files and strict = True, should fail."""
307
        from bzrlib.errors import StrictCommitFailed
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
308
        wt = self.make_branch_and_tree('.')
309
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
310
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
311
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
312
        file('goodbye', 'w').write('goodbye cruel world!')
1534.4.35 by Robert Collins
Give branch its own basis tree and last_revision methods; deprecated branch.working_tree()
313
        self.assertRaises(StrictCommitFailed, wt.commit,
1185.16.65 by mbp at sourcefrog
- new commit --strict option
314
            message='add hello but not goodbye', strict=True)
315
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
316
    def test_strict_commit_without_unknowns(self):
317
        """Try and commit with no unknown files and strict = True,
318
        should work."""
319
        from bzrlib.errors import StrictCommitFailed
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
320
        wt = self.make_branch_and_tree('.')
321
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
322
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
323
        wt.add('hello')
324
        wt.commit(message='add hello', strict=True)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
325
1185.16.65 by mbp at sourcefrog
- new commit --strict option
326
    def test_nonstrict_commit(self):
327
        """Try and commit with unknown files and strict = False, should work."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
328
        wt = self.make_branch_and_tree('.')
329
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
330
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
331
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
332
        file('goodbye', 'w').write('goodbye cruel world!')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
333
        wt.commit(message='add hello but not goodbye', strict=False)
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
334
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
335
    def test_nonstrict_commit_without_unknowns(self):
336
        """Try and commit with no unknown files and strict = False,
337
        should work."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
338
        wt = self.make_branch_and_tree('.')
339
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
340
        file('hello', 'w').write('hello world')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
341
        wt.add('hello')
342
        wt.commit(message='add hello', strict=False)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
343
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
344
    def test_signed_commit(self):
345
        import bzrlib.gpg
346
        import bzrlib.commit as commit
347
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
348
        wt = self.make_branch_and_tree('.')
349
        branch = wt.branch
350
        wt.commit("base", allow_pointless=True, rev_id='A')
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
351
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
352
        try:
353
            from bzrlib.testament import Testament
354
            # monkey patch gpg signing mechanism
355
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
2149.1.3 by Aaron Bentley
Updates from review comments
356
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
357
                                                      allow_pointless=True,
358
                                                      rev_id='B',
359
                                                      working_tree=wt)
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
360
            self.assertEqual(Testament.from_revision(branch.repository,
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
361
                             'B').as_short_text(),
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
362
                             branch.repository.get_signature_text('B'))
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
363
        finally:
364
            bzrlib.gpg.GPGStrategy = oldstrategy
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
365
366
    def test_commit_failed_signature(self):
367
        import bzrlib.gpg
368
        import bzrlib.commit as commit
369
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
370
        wt = self.make_branch_and_tree('.')
371
        branch = wt.branch
372
        wt.commit("base", allow_pointless=True, rev_id='A')
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
373
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
374
        try:
375
            from bzrlib.testament import Testament
376
            # monkey patch gpg signing mechanism
377
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
378
            config = MustSignConfig(branch)
379
            self.assertRaises(SigningFailed,
380
                              commit.Commit(config=config).commit,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
381
                              message="base",
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
382
                              allow_pointless=True,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
383
                              rev_id='B',
384
                              working_tree=wt)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
385
            branch = Branch.open(self.get_url('.'))
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
386
            self.assertEqual(branch.revision_history(), ['A'])
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
387
            self.failIf(branch.repository.has_revision('B'))
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
388
        finally:
389
            bzrlib.gpg.GPGStrategy = oldstrategy
1472 by Robert Collins
post commit hook, first pass implementation
390
391
    def test_commit_invokes_hooks(self):
392
        import bzrlib.commit as commit
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
393
        wt = self.make_branch_and_tree('.')
394
        branch = wt.branch
1472 by Robert Collins
post commit hook, first pass implementation
395
        calls = []
396
        def called(branch, rev_id):
397
            calls.append('called')
398
        bzrlib.ahook = called
399
        try:
400
            config = BranchWithHooks(branch)
401
            commit.Commit(config=config).commit(
2149.1.3 by Aaron Bentley
Updates from review comments
402
                            message = "base",
1472 by Robert Collins
post commit hook, first pass implementation
403
                            allow_pointless=True,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
404
                            rev_id='A', working_tree = wt)
1472 by Robert Collins
post commit hook, first pass implementation
405
            self.assertEqual(['called', 'called'], calls)
406
        finally:
407
            del bzrlib.ahook
1593.1.1 by Robert Collins
Move responsibility for setting branch nickname in commits to the WorkingTree convenience function.
408
409
    def test_commit_object_doesnt_set_nick(self):
410
        # using the Commit object directly does not set the branch nick.
411
        wt = self.make_branch_and_tree('.')
412
        c = Commit()
2149.1.3 by Aaron Bentley
Updates from review comments
413
        c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
1593.1.1 by Robert Collins
Move responsibility for setting branch nickname in commits to the WorkingTree convenience function.
414
        self.assertEquals(wt.branch.revno(), 1)
415
        self.assertEqual({},
416
                         wt.branch.repository.get_revision(
417
                            wt.branch.last_revision()).properties)
418
1614.1.1 by Aaron Bentley
Fixed master locking in commit
419
    def test_safe_master_lock(self):
420
        os.mkdir('master')
421
        master = BzrDirMetaFormat1().initialize('master')
422
        master.create_repository()
423
        master_branch = master.create_branch()
424
        master.create_workingtree()
425
        bound = master.sprout('bound')
426
        wt = bound.open_workingtree()
427
        wt.branch.set_bound_location(os.path.realpath('master'))
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
428
429
        orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
1614.1.1 by Aaron Bentley
Fixed master locking in commit
430
        master_branch.lock_write()
1658.1.5 by Martin Pool
Release more locks taken during test suite
431
        try:
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
432
            lockdir._DEFAULT_TIMEOUT_SECONDS = 1
1658.1.5 by Martin Pool
Release more locks taken during test suite
433
            self.assertRaises(LockContention, wt.commit, 'silly')
434
        finally:
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
435
            lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
1658.1.5 by Martin Pool
Release more locks taken during test suite
436
            master_branch.unlock()
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
437
438
    def test_commit_bound_merge(self):
439
        # see bug #43959; commit of a merge in a bound branch fails to push
440
        # the new commit into the master
441
        master_branch = self.make_branch('master')
442
        bound_tree = self.make_branch_and_tree('bound')
443
        bound_tree.branch.bind(master_branch)
444
445
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
446
        bound_tree.add(['content_file'])
447
        bound_tree.commit(message='woo!')
448
449
        other_bzrdir = master_branch.bzrdir.sprout('other')
450
        other_tree = other_bzrdir.open_workingtree()
451
452
        # do a commit to the the other branch changing the content file so
453
        # that our commit after merging will have a merged revision in the
454
        # content file history.
455
        self.build_tree_contents([('other/content_file', 'change in other\n')])
456
        other_tree.commit('change in other')
457
458
        # do a merge into the bound branch from other, and then change the
459
        # content file locally to force a new revision (rather than using the
460
        # revision from other). This forces extra processing in commit.
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
461
        bound_tree.merge_from_branch(other_tree.branch)
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
462
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
463
464
        # before #34959 was fixed, this failed with 'revision not present in
465
        # weave' when trying to implicitly push from the bound branch to the master
466
        bound_tree.commit(message='commit of merge in bound tree')
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
467
468
    def test_commit_reporting_after_merge(self):
469
        # when doing a commit of a merge, the reporter needs to still 
470
        # be called for each item that is added/removed/deleted.
471
        this_tree = self.make_branch_and_tree('this')
472
        # we need a bunch of files and dirs, to perform one action on each.
473
        self.build_tree([
474
            'this/dirtorename/',
475
            'this/dirtoreparent/',
476
            'this/dirtoleave/',
477
            'this/dirtoremove/',
478
            'this/filetoreparent',
479
            'this/filetorename',
480
            'this/filetomodify',
481
            'this/filetoremove',
482
            'this/filetoleave']
483
            )
484
        this_tree.add([
485
            'dirtorename',
486
            'dirtoreparent',
487
            'dirtoleave',
488
            'dirtoremove',
489
            'filetoreparent',
490
            'filetorename',
491
            'filetomodify',
492
            'filetoremove',
493
            'filetoleave']
494
            )
495
        this_tree.commit('create_files')
496
        other_dir = this_tree.bzrdir.sprout('other')
497
        other_tree = other_dir.open_workingtree()
498
        other_tree.lock_write()
499
        # perform the needed actions on the files and dirs.
500
        try:
501
            other_tree.rename_one('dirtorename', 'renameddir')
502
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
503
            other_tree.rename_one('filetorename', 'renamedfile')
504
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
505
            other_tree.remove(['dirtoremove', 'filetoremove'])
506
            self.build_tree_contents([
507
                ('other/newdir/', ),
508
                ('other/filetomodify', 'new content'),
509
                ('other/newfile', 'new file content')])
510
            other_tree.add('newfile')
511
            other_tree.add('newdir/')
512
            other_tree.commit('modify all sample files and dirs.')
513
        finally:
514
            other_tree.unlock()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
515
        this_tree.merge_from_branch(other_tree.branch)
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
516
        reporter = CapturingReporter()
517
        this_tree.commit('do the commit', reporter=reporter)
518
        self.assertEqual([
1910.2.3 by Aaron Bentley
All tests pass
519
            ('change', 'unchanged', ''),
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
520
            ('change', 'unchanged', 'dirtoleave'),
521
            ('change', 'unchanged', 'filetoleave'),
522
            ('change', 'modified', 'filetomodify'),
523
            ('change', 'added', 'newdir'),
524
            ('change', 'added', 'newfile'),
525
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
526
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
527
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
528
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
529
            ('deleted', 'dirtoremove'),
530
            ('deleted', 'filetoremove'),
531
            ],
532
            reporter.calls)
1551.7.24 by Aaron Bentley
Ensure commit respects file spec when committing removals
533
534
    def test_commit_removals_respects_filespec(self):
535
        """Commit respects the specified_files for removals."""
536
        tree = self.make_branch_and_tree('.')
537
        self.build_tree(['a', 'b'])
538
        tree.add(['a', 'b'])
539
        tree.commit('added a, b')
540
        tree.remove(['a', 'b'])
1906.1.1 by Robert Collins
(robertc) Trivial change to test_commit_removals_respects_filespec to be easir to read.
541
        tree.commit('removed a', specific_files='a')
2255.2.148 by John Arbash Meinel
lock a basis tree during a commit test.
542
        basis = tree.basis_tree()
543
        tree.lock_read()
544
        try:
545
            self.assertIs(None, basis.path2id('a'))
546
            self.assertFalse(basis.path2id('b') is None)
547
        finally:
548
            tree.unlock()
1864.2.1 by John Arbash Meinel
Commit timestamp restricted to 1ms precision.
549
550
    def test_commit_saves_1ms_timestamp(self):
551
        """Passing in a timestamp is saved with 1ms resolution"""
552
        tree = self.make_branch_and_tree('.')
553
        self.build_tree(['a'])
554
        tree.add('a')
555
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
556
                    rev_id='a1')
557
558
        rev = tree.branch.repository.get_revision('a1')
559
        self.assertEqual(1153248633.419, rev.timestamp)
560
561
    def test_commit_has_1ms_resolution(self):
562
        """Allowing commit to generate the timestamp also has 1ms resolution"""
563
        tree = self.make_branch_and_tree('.')
564
        self.build_tree(['a'])
565
        tree.add('a')
566
        tree.commit('added a', rev_id='a1')
567
568
        rev = tree.branch.repository.get_revision('a1')
569
        timestamp = rev.timestamp
570
        timestamp_1ms = round(timestamp, 3)
571
        self.assertEqual(timestamp_1ms, timestamp)
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
572
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
573
    def assertBasisTreeKind(self, kind, tree, file_id):
574
        basis = tree.basis_tree()
575
        basis.lock_read()
576
        try:
577
            self.assertEqual(kind, basis.kind(file_id))
578
        finally:
579
            basis.unlock()
580
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
581
    def test_commit_kind_changes(self):
582
        if not osutils.has_symlinks():
583
            raise tests.TestSkipped('Test requires symlink support')
584
        tree = self.make_branch_and_tree('.')
585
        os.symlink('target', 'name')
586
        tree.add('name', 'a-file-id')
587
        tree.commit('Added a symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
588
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
589
590
        os.unlink('name')
591
        self.build_tree(['name'])
592
        tree.commit('Changed symlink to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
593
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
594
595
        os.unlink('name')
596
        os.symlink('target', 'name')
597
        tree.commit('file to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
598
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
599
600
        os.unlink('name')
601
        os.mkdir('name')
602
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
603
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
604
605
        os.rmdir('name')
606
        os.symlink('target', 'name')
607
        tree.commit('directory to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
608
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
609
610
        # prepare for directory <-> file tests
611
        os.unlink('name')
612
        os.mkdir('name')
613
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
614
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
615
616
        os.rmdir('name')
617
        self.build_tree(['name'])
618
        tree.commit('Changed directory to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
619
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
620
621
        os.unlink('name')
622
        os.mkdir('name')
623
        tree.commit('file to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
624
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.2 by Aaron Bentley
Merge bzr.dev
625
1551.8.29 by Aaron Bentley
Stop accepting non-existant files in commit (#50793)
626
    def test_commit_unversioned_specified(self):
627
        """Commit should raise if specified files isn't in basis or worktree"""
628
        tree = self.make_branch_and_tree('.')
629
        self.assertRaises(errors.PathsNotVersionedError, tree.commit, 
630
                          'message', specific_files=['bogus'])
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
631
632
    class Callback(object):
633
        
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
634
        def __init__(self, message, testcase):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
635
            self.called = False
636
            self.message = message
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
637
            self.testcase = testcase
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
638
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
639
        def __call__(self, commit_obj):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
640
            self.called = True
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
641
            self.testcase.assertTrue(isinstance(commit_obj, Commit))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
642
            return self.message
643
644
    def test_commit_callback(self):
645
        """Commit should invoke a callback to get the message"""
646
647
        tree = self.make_branch_and_tree('.')
648
        try:
649
            tree.commit()
650
        except Exception, e:
651
            self.assertTrue(isinstance(e, BzrError))
2149.1.3 by Aaron Bentley
Updates from review comments
652
            self.assertEqual('The message or message_callback keyword'
653
                             ' parameter is required for commit().', str(e))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
654
        else:
655
            self.fail('exception not raised')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
656
        cb = self.Callback(u'commit 1', self)
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
657
        tree.commit(message_callback=cb)
658
        self.assertTrue(cb.called)
659
        repository = tree.branch.repository
660
        message = repository.get_revision(tree.last_revision()).message
661
        self.assertEqual('commit 1', message)
662
663
    def test_no_callback_pointless(self):
664
        """Callback should not be invoked for pointless commit"""
665
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
666
        cb = self.Callback(u'commit 2', self)
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
667
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb, 
668
                          allow_pointless=False)
669
        self.assertFalse(cb.called)
670
671
    def test_no_callback_netfailure(self):
672
        """Callback should not be invoked if connectivity fails"""
2149.1.3 by Aaron Bentley
Updates from review comments
673
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
674
        cb = self.Callback(u'commit 2', self)
2149.1.3 by Aaron Bentley
Updates from review comments
675
        repository = tree.branch.repository
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
676
        # simulate network failure
677
        def raise_(self, arg, arg2):
678
            raise errors.NoSuchFile('foo')
679
        repository.add_inventory = raise_
680
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
681
        self.assertFalse(cb.called)
2100.3.27 by Aaron Bentley
Enable nested commits
682
683
    def test_nested_commit(self):
684
        """Commit in multiply-nested trees"""
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
685
        tree = self.make_branch_and_tree('.',
686
            format='dirstate-with-subtree')
2100.3.27 by Aaron Bentley
Enable nested commits
687
        subtree = self.make_branch_and_tree('subtree',
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
688
            format='dirstate-with-subtree')
2100.3.27 by Aaron Bentley
Enable nested commits
689
        subsubtree = self.make_branch_and_tree('subtree/subtree',
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
690
            format='dirstate-with-subtree')
2100.3.27 by Aaron Bentley
Enable nested commits
691
        subtree.add_reference(subsubtree)
692
        tree.add_reference(subtree)
693
        tree.commit('added reference', allow_pointless=False)
694
        self.assertIs(subsubtree.last_revision(), None,
695
                      'subsubtree was committed')
696
        self.assertIsNot(subtree.last_revision(), None,
697
                         'subtree was not committed')
698