~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
2789.2.1 by Ian Clatworthy
Make commit less verbose by default
73
    def is_verbose(self):
74
        return True
75
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
76
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
77
class TestCommit(TestCaseWithTransport):
1390 by Robert Collins
pair programming worx... merge integration and weave
78
1246 by Martin Pool
- add very simple commit tests
79
    def test_simple_commit(self):
80
        """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.
81
        wt = self.make_branch_and_tree('.')
82
        b = wt.branch
1246 by Martin Pool
- add very simple commit tests
83
        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.
84
        wt.add('hello')
85
        wt.commit(message='add hello')
86
        file_id = wt.path2id('hello')
1246 by Martin Pool
- add very simple commit tests
87
88
        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.
89
        wt.commit(message='commit 2')
1246 by Martin Pool
- add very simple commit tests
90
91
        eq = self.assertEquals
92
        eq(b.revno(), 2)
93
        rh = b.revision_history()
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
94
        rev = b.repository.get_revision(rh[0])
1246 by Martin Pool
- add very simple commit tests
95
        eq(rev.message, 'add hello')
96
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
97
        tree1 = b.repository.revision_tree(rh[0])
1246 by Martin Pool
- add very simple commit tests
98
        text = tree1.get_file_text(file_id)
99
        eq(text, 'hello world')
100
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
101
        tree2 = b.repository.revision_tree(rh[1])
1246 by Martin Pool
- add very simple commit tests
102
        eq(tree2.get_file_text(file_id), 'version 2')
103
104
    def test_delete_commit(self):
105
        """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.
106
        wt = self.make_branch_and_tree('.')
107
        b = wt.branch
1247 by Martin Pool
- tests for deletion and removal of files in commits
108
        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.
109
        wt.add(['hello'], ['hello-id'])
110
        wt.commit(message='add hello')
1247 by Martin Pool
- tests for deletion and removal of files in commits
111
112
        os.remove('hello')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
113
        wt.commit('removed hello', rev_id='rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
114
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
115
        tree = b.repository.revision_tree('rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
116
        self.assertFalse(tree.has_id('hello-id'))
117
1253 by Martin Pool
- test that pointless commits are trapped
118
    def test_pointless_commit(self):
119
        """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.
120
        wt = self.make_branch_and_tree('.')
121
        b = wt.branch
1253 by Martin Pool
- test that pointless commits are trapped
122
        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.
123
        wt.add(['hello'])
124
        wt.commit(message='add hello')
1253 by Martin Pool
- test that pointless commits are trapped
125
        self.assertEquals(b.revno(), 1)
126
        self.assertRaises(PointlessCommit,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
127
                          wt.commit,
1253 by Martin Pool
- test that pointless commits are trapped
128
                          message='fails',
129
                          allow_pointless=False)
130
        self.assertEquals(b.revno(), 1)
131
        
1252 by Martin Pool
- add test for commit of an empty tree
132
    def test_commit_empty(self):
1253 by Martin Pool
- test that pointless commits are trapped
133
        """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.
134
        wt = self.make_branch_and_tree('.')
135
        b = wt.branch
136
        wt.commit(message='empty tree', allow_pointless=True)
1253 by Martin Pool
- test that pointless commits are trapped
137
        self.assertRaises(PointlessCommit,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
138
                          wt.commit,
1253 by Martin Pool
- test that pointless commits are trapped
139
                          message='empty tree',
140
                          allow_pointless=False)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
141
        wt.commit(message='empty tree', allow_pointless=True)
1252 by Martin Pool
- add test for commit of an empty tree
142
        self.assertEquals(b.revno(), 2)
143
144
    def test_selective_delete(self):
145
        """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.
146
        wt = self.make_branch_and_tree('.')
147
        b = wt.branch
1254 by Martin Pool
- fix handling of selective commit with deleted files
148
        file('hello', 'w').write('hello')
149
        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.
150
        wt.add(['hello', 'buongia'],
1255 by Martin Pool
- more tests for selective commit of deletion
151
              ['hello-id', 'buongia-id'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
152
        wt.commit(message='add files',
1255 by Martin Pool
- more tests for selective commit of deletion
153
                 rev_id='test@rev-1')
1254 by Martin Pool
- fix handling of selective commit with deleted files
154
        
155
        os.remove('hello')
156
        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.
157
        wt.commit(message='update text',
1254 by Martin Pool
- fix handling of selective commit with deleted files
158
                 specific_files=['buongia'],
1255 by Martin Pool
- more tests for selective commit of deletion
159
                 allow_pointless=False,
160
                 rev_id='test@rev-2')
1254 by Martin Pool
- fix handling of selective commit with deleted files
161
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
162
        wt.commit(message='remove hello',
1254 by Martin Pool
- fix handling of selective commit with deleted files
163
                 specific_files=['hello'],
1255 by Martin Pool
- more tests for selective commit of deletion
164
                 allow_pointless=False,
165
                 rev_id='test@rev-3')
1254 by Martin Pool
- fix handling of selective commit with deleted files
166
167
        eq = self.assertEquals
168
        eq(b.revno(), 3)
1255 by Martin Pool
- more tests for selective commit of deletion
169
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
170
        tree2 = b.repository.revision_tree('test@rev-2')
1255 by Martin Pool
- more tests for selective commit of deletion
171
        self.assertTrue(tree2.has_filename('hello'))
172
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
173
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
174
        
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
175
        tree3 = b.repository.revision_tree('test@rev-3')
1255 by Martin Pool
- more tests for selective commit of deletion
176
        self.assertFalse(tree3.has_filename('hello'))
177
        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
178
179
    def test_commit_rename(self):
180
        """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.
181
        tree = self.make_branch_and_tree('.')
182
        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
183
        self.build_tree(['hello'], line_endings='binary')
1508.1.7 by Robert Collins
Move rename_one from Branch to WorkingTree. (Robert Collins).
184
        tree.add(['hello'], ['hello-id'])
185
        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
186
1508.1.7 by Robert Collins
Move rename_one from Branch to WorkingTree. (Robert Collins).
187
        tree.rename_one('hello', 'fruity')
188
        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
189
1303 by Martin Pool
- commit updates entry_version
190
        eq = self.assertEquals
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
191
        tree1 = b.repository.revision_tree('test@rev-1')
1303 by Martin Pool
- commit updates entry_version
192
        eq(tree1.id2path('hello-id'), 'hello')
193
        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
194
        self.assertFalse(tree1.has_filename('fruity'))
1291 by Martin Pool
- add test for moving files between directories
195
        self.check_inventory_shape(tree1.inventory, ['hello'])
1303 by Martin Pool
- commit updates entry_version
196
        ie = tree1.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
197
        eq(ie.revision, 'test@rev-1')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
198
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
199
        tree2 = b.repository.revision_tree('test@rev-2')
1303 by Martin Pool
- commit updates entry_version
200
        eq(tree2.id2path('hello-id'), 'fruity')
201
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
1291 by Martin Pool
- add test for moving files between directories
202
        self.check_inventory_shape(tree2.inventory, ['fruity'])
1303 by Martin Pool
- commit updates entry_version
203
        ie = tree2.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
204
        eq(ie.revision, 'test@rev-2')
1291 by Martin Pool
- add test for moving files between directories
205
206
    def test_reused_rev_id(self):
1292 by Martin Pool
- add check that revision ids cannot be committed twice
207
        """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.
208
        wt = self.make_branch_and_tree('.')
209
        b = wt.branch
210
        wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
1292 by Martin Pool
- add check that revision ids cannot be committed twice
211
        self.assertRaises(Exception,
1534.4.35 by Robert Collins
Give branch its own basis tree and last_revision methods; deprecated branch.working_tree()
212
                          wt.commit,
1292 by Martin Pool
- add check that revision ids cannot be committed twice
213
                          message='reused id',
214
                          rev_id='test@rev-1',
215
                          allow_pointless=True)
1291 by Martin Pool
- add test for moving files between directories
216
217
    def test_commit_move(self):
218
        """Test commit of revisions with moved files and directories"""
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
219
        eq = self.assertEquals
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
220
        wt = self.make_branch_and_tree('.')
221
        b = wt.branch
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
222
        r1 = 'test@rev-1'
1291 by Martin Pool
- add test for moving files between directories
223
        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.
224
        wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
225
        wt.commit('initial', rev_id=r1, allow_pointless=False)
226
        wt.move(['hello'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
227
        r2 = 'test@rev-2'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
228
        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
229
        wt.lock_read()
230
        try:
231
            self.check_inventory_shape(wt.read_working_inventory(),
2545.3.2 by James Westby
Add a test for check_inventory_shape.
232
                                       ['a/', 'a/hello', 'b/'])
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
233
        finally:
234
            wt.unlock()
1291 by Martin Pool
- add test for moving files between directories
235
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
236
        wt.move(['b'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
237
        r3 = 'test@rev-3'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
238
        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
239
        wt.lock_read()
240
        try:
241
            self.check_inventory_shape(wt.read_working_inventory(),
2545.3.2 by James Westby
Add a test for check_inventory_shape.
242
                                       ['a/', 'a/hello', 'a/b/'])
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
243
            self.check_inventory_shape(b.repository.get_revision_inventory(r3),
2545.3.2 by James Westby
Add a test for check_inventory_shape.
244
                                       ['a/', 'a/hello', 'a/b/'])
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
245
        finally:
246
            wt.unlock()
1291 by Martin Pool
- add test for moving files between directories
247
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
248
        wt.move(['a/hello'], 'a/b')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
249
        r4 = 'test@rev-4'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
250
        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
251
        wt.lock_read()
252
        try:
253
            self.check_inventory_shape(wt.read_working_inventory(),
2545.3.2 by James Westby
Add a test for check_inventory_shape.
254
                                       ['a/', 'a/b/hello', 'a/b/'])
2255.2.136 by John Arbash Meinel
(James Westby) add read locks around read_working_inventory() in test_commit_move
255
        finally:
256
            wt.unlock()
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
257
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
258
        inv = b.repository.get_revision_inventory(r4)
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
259
        eq(inv['hello-id'].revision, r4)
260
        eq(inv['a-id'].revision, r1)
261
        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
262
1246 by Martin Pool
- add very simple commit tests
263
    def test_removed_commit(self):
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
264
        """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.
265
        wt = self.make_branch_and_tree('.')
266
        b = wt.branch
1247 by Martin Pool
- tests for deletion and removal of files in commits
267
        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.
268
        wt.add(['hello'], ['hello-id'])
269
        wt.commit(message='add hello')
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
270
        wt.remove('hello')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
271
        wt.commit('removed hello', rev_id='rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
272
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
273
        tree = b.repository.revision_tree('rev2')
1247 by Martin Pool
- tests for deletion and removal of files in commits
274
        self.assertFalse(tree.has_id('hello-id'))
1246 by Martin Pool
- add very simple commit tests
275
1256 by Martin Pool
- test that commits append to the tree's ancestry
276
    def test_committed_ancestry(self):
277
        """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.
278
        wt = self.make_branch_and_tree('.')
279
        b = wt.branch
1256 by Martin Pool
- test that commits append to the tree's ancestry
280
        rev_ids = []
281
        for i in range(4):
282
            file('hello', 'w').write((str(i) * 4) + '\n')
283
            if i == 0:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
284
                wt.add(['hello'], ['hello-id'])
1256 by Martin Pool
- test that commits append to the tree's ancestry
285
            rev_id = 'test@rev-%d' % (i+1)
286
            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.
287
            wt.commit(message='rev %d' % (i+1),
1256 by Martin Pool
- test that commits append to the tree's ancestry
288
                     rev_id=rev_id)
289
        eq = self.assertEquals
290
        eq(b.revision_history(), rev_ids)
291
        for i in range(4):
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
292
            anc = b.repository.get_ancestry(rev_ids[i])
1390 by Robert Collins
pair programming worx... merge integration and weave
293
            eq(anc, [None] + rev_ids[:i+1])
1416 by Robert Collins
when committing a specific file, include all its parents
294
295
    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.
296
        wt = self.make_branch_and_tree('.')
297
        b = wt.branch
1416 by Robert Collins
when committing a specific file, include all its parents
298
        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.
299
        wt.add(['dir', 'dir/file1', 'dir/file2'],
1416 by Robert Collins
when committing a specific file, include all its parents
300
              ['dirid', 'file1id', 'file2id'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
301
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
302
        inv = b.repository.get_inventory('1')
1416 by Robert Collins
when committing a specific file, include all its parents
303
        self.assertEqual('1', inv['dirid'].revision)
304
        self.assertEqual('1', inv['file1id'].revision)
305
        # FIXME: This should raise a KeyError I think, rbc20051006
306
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
307
308
    def test_strict_commit(self):
309
        """Try and commit with unknown files and strict = True, should fail."""
310
        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.
311
        wt = self.make_branch_and_tree('.')
312
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
313
        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.
314
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
315
        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()
316
        self.assertRaises(StrictCommitFailed, wt.commit,
1185.16.65 by mbp at sourcefrog
- new commit --strict option
317
            message='add hello but not goodbye', strict=True)
318
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
319
    def test_strict_commit_without_unknowns(self):
320
        """Try and commit with no unknown files and strict = True,
321
        should work."""
322
        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.
323
        wt = self.make_branch_and_tree('.')
324
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
325
        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.
326
        wt.add('hello')
327
        wt.commit(message='add hello', strict=True)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
328
1185.16.65 by mbp at sourcefrog
- new commit --strict option
329
    def test_nonstrict_commit(self):
330
        """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.
331
        wt = self.make_branch_and_tree('.')
332
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
333
        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.
334
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
335
        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.
336
        wt.commit(message='add hello but not goodbye', strict=False)
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
337
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
338
    def test_nonstrict_commit_without_unknowns(self):
339
        """Try and commit with no unknown files and strict = False,
340
        should work."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
341
        wt = self.make_branch_and_tree('.')
342
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
343
        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.
344
        wt.add('hello')
345
        wt.commit(message='add hello', strict=False)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
346
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
347
    def test_signed_commit(self):
348
        import bzrlib.gpg
349
        import bzrlib.commit as commit
350
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
351
        wt = self.make_branch_and_tree('.')
352
        branch = wt.branch
353
        wt.commit("base", allow_pointless=True, rev_id='A')
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
354
        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
355
        try:
356
            from bzrlib.testament import Testament
357
            # monkey patch gpg signing mechanism
358
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
2149.1.3 by Aaron Bentley
Updates from review comments
359
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
360
                                                      allow_pointless=True,
361
                                                      rev_id='B',
362
                                                      working_tree=wt)
1551.12.15 by Aaron Bentley
add header/trailer to fake clearsigned texts
363
            def sign(text):
364
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
365
            self.assertEqual(sign(Testament.from_revision(branch.repository,
366
                             'B').as_short_text()),
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
367
                             branch.repository.get_signature_text('B'))
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
368
        finally:
369
            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.
370
371
    def test_commit_failed_signature(self):
372
        import bzrlib.gpg
373
        import bzrlib.commit as commit
374
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
375
        wt = self.make_branch_and_tree('.')
376
        branch = wt.branch
377
        wt.commit("base", allow_pointless=True, rev_id='A')
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
378
        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.
379
        try:
380
            from bzrlib.testament import Testament
381
            # monkey patch gpg signing mechanism
382
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
383
            config = MustSignConfig(branch)
384
            self.assertRaises(SigningFailed,
385
                              commit.Commit(config=config).commit,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
386
                              message="base",
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
387
                              allow_pointless=True,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
388
                              rev_id='B',
389
                              working_tree=wt)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
390
            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.
391
            self.assertEqual(branch.revision_history(), ['A'])
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
392
            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.
393
        finally:
394
            bzrlib.gpg.GPGStrategy = oldstrategy
1472 by Robert Collins
post commit hook, first pass implementation
395
396
    def test_commit_invokes_hooks(self):
397
        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.
398
        wt = self.make_branch_and_tree('.')
399
        branch = wt.branch
1472 by Robert Collins
post commit hook, first pass implementation
400
        calls = []
401
        def called(branch, rev_id):
402
            calls.append('called')
403
        bzrlib.ahook = called
404
        try:
405
            config = BranchWithHooks(branch)
406
            commit.Commit(config=config).commit(
2149.1.3 by Aaron Bentley
Updates from review comments
407
                            message = "base",
1472 by Robert Collins
post commit hook, first pass implementation
408
                            allow_pointless=True,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
409
                            rev_id='A', working_tree = wt)
1472 by Robert Collins
post commit hook, first pass implementation
410
            self.assertEqual(['called', 'called'], calls)
411
        finally:
412
            del bzrlib.ahook
1593.1.1 by Robert Collins
Move responsibility for setting branch nickname in commits to the WorkingTree convenience function.
413
414
    def test_commit_object_doesnt_set_nick(self):
415
        # using the Commit object directly does not set the branch nick.
416
        wt = self.make_branch_and_tree('.')
417
        c = Commit()
2149.1.3 by Aaron Bentley
Updates from review comments
418
        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.
419
        self.assertEquals(wt.branch.revno(), 1)
420
        self.assertEqual({},
421
                         wt.branch.repository.get_revision(
422
                            wt.branch.last_revision()).properties)
423
1614.1.1 by Aaron Bentley
Fixed master locking in commit
424
    def test_safe_master_lock(self):
425
        os.mkdir('master')
426
        master = BzrDirMetaFormat1().initialize('master')
427
        master.create_repository()
428
        master_branch = master.create_branch()
429
        master.create_workingtree()
430
        bound = master.sprout('bound')
431
        wt = bound.open_workingtree()
432
        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.
433
434
        orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
1614.1.1 by Aaron Bentley
Fixed master locking in commit
435
        master_branch.lock_write()
1658.1.5 by Martin Pool
Release more locks taken during test suite
436
        try:
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
437
            lockdir._DEFAULT_TIMEOUT_SECONDS = 1
1658.1.5 by Martin Pool
Release more locks taken during test suite
438
            self.assertRaises(LockContention, wt.commit, 'silly')
439
        finally:
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
440
            lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
1658.1.5 by Martin Pool
Release more locks taken during test suite
441
            master_branch.unlock()
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
442
443
    def test_commit_bound_merge(self):
444
        # see bug #43959; commit of a merge in a bound branch fails to push
445
        # the new commit into the master
446
        master_branch = self.make_branch('master')
447
        bound_tree = self.make_branch_and_tree('bound')
448
        bound_tree.branch.bind(master_branch)
449
450
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
451
        bound_tree.add(['content_file'])
452
        bound_tree.commit(message='woo!')
453
454
        other_bzrdir = master_branch.bzrdir.sprout('other')
455
        other_tree = other_bzrdir.open_workingtree()
456
457
        # do a commit to the the other branch changing the content file so
458
        # that our commit after merging will have a merged revision in the
459
        # content file history.
460
        self.build_tree_contents([('other/content_file', 'change in other\n')])
461
        other_tree.commit('change in other')
462
463
        # do a merge into the bound branch from other, and then change the
464
        # content file locally to force a new revision (rather than using the
465
        # 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.
466
        bound_tree.merge_from_branch(other_tree.branch)
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
467
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
468
469
        # before #34959 was fixed, this failed with 'revision not present in
470
        # weave' when trying to implicitly push from the bound branch to the master
471
        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
472
473
    def test_commit_reporting_after_merge(self):
474
        # when doing a commit of a merge, the reporter needs to still 
475
        # be called for each item that is added/removed/deleted.
476
        this_tree = self.make_branch_and_tree('this')
477
        # we need a bunch of files and dirs, to perform one action on each.
478
        self.build_tree([
479
            'this/dirtorename/',
480
            'this/dirtoreparent/',
481
            'this/dirtoleave/',
482
            'this/dirtoremove/',
483
            'this/filetoreparent',
484
            'this/filetorename',
485
            'this/filetomodify',
486
            'this/filetoremove',
487
            'this/filetoleave']
488
            )
489
        this_tree.add([
490
            'dirtorename',
491
            'dirtoreparent',
492
            'dirtoleave',
493
            'dirtoremove',
494
            'filetoreparent',
495
            'filetorename',
496
            'filetomodify',
497
            'filetoremove',
498
            'filetoleave']
499
            )
500
        this_tree.commit('create_files')
501
        other_dir = this_tree.bzrdir.sprout('other')
502
        other_tree = other_dir.open_workingtree()
503
        other_tree.lock_write()
504
        # perform the needed actions on the files and dirs.
505
        try:
506
            other_tree.rename_one('dirtorename', 'renameddir')
507
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
508
            other_tree.rename_one('filetorename', 'renamedfile')
509
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
510
            other_tree.remove(['dirtoremove', 'filetoremove'])
511
            self.build_tree_contents([
512
                ('other/newdir/', ),
513
                ('other/filetomodify', 'new content'),
514
                ('other/newfile', 'new file content')])
515
            other_tree.add('newfile')
516
            other_tree.add('newdir/')
517
            other_tree.commit('modify all sample files and dirs.')
518
        finally:
519
            other_tree.unlock()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
520
        this_tree.merge_from_branch(other_tree.branch)
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
521
        reporter = CapturingReporter()
522
        this_tree.commit('do the commit', reporter=reporter)
523
        self.assertEqual([
1910.2.3 by Aaron Bentley
All tests pass
524
            ('change', 'unchanged', ''),
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
525
            ('change', 'unchanged', 'dirtoleave'),
526
            ('change', 'unchanged', 'filetoleave'),
527
            ('change', 'modified', 'filetomodify'),
528
            ('change', 'added', 'newdir'),
529
            ('change', 'added', 'newfile'),
530
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
2829.1.1 by Ian Clatworthy
re-apply Aaron's fix for #94975 (Ian Clatworthy)
531
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
532
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
533
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
534
            ('deleted', 'dirtoremove'),
535
            ('deleted', 'filetoremove'),
536
            ],
537
            reporter.calls)
1551.7.24 by Aaron Bentley
Ensure commit respects file spec when committing removals
538
539
    def test_commit_removals_respects_filespec(self):
540
        """Commit respects the specified_files for removals."""
541
        tree = self.make_branch_and_tree('.')
542
        self.build_tree(['a', 'b'])
543
        tree.add(['a', 'b'])
544
        tree.commit('added a, b')
545
        tree.remove(['a', 'b'])
1906.1.1 by Robert Collins
(robertc) Trivial change to test_commit_removals_respects_filespec to be easir to read.
546
        tree.commit('removed a', specific_files='a')
2255.2.148 by John Arbash Meinel
lock a basis tree during a commit test.
547
        basis = tree.basis_tree()
548
        tree.lock_read()
549
        try:
550
            self.assertIs(None, basis.path2id('a'))
551
            self.assertFalse(basis.path2id('b') is None)
552
        finally:
553
            tree.unlock()
1864.2.1 by John Arbash Meinel
Commit timestamp restricted to 1ms precision.
554
555
    def test_commit_saves_1ms_timestamp(self):
556
        """Passing in a timestamp is saved with 1ms resolution"""
557
        tree = self.make_branch_and_tree('.')
558
        self.build_tree(['a'])
559
        tree.add('a')
560
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
561
                    rev_id='a1')
562
563
        rev = tree.branch.repository.get_revision('a1')
564
        self.assertEqual(1153248633.419, rev.timestamp)
565
566
    def test_commit_has_1ms_resolution(self):
567
        """Allowing commit to generate the timestamp also has 1ms resolution"""
568
        tree = self.make_branch_and_tree('.')
569
        self.build_tree(['a'])
570
        tree.add('a')
571
        tree.commit('added a', rev_id='a1')
572
573
        rev = tree.branch.repository.get_revision('a1')
574
        timestamp = rev.timestamp
575
        timestamp_1ms = round(timestamp, 3)
576
        self.assertEqual(timestamp_1ms, timestamp)
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
577
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
578
    def assertBasisTreeKind(self, kind, tree, file_id):
579
        basis = tree.basis_tree()
580
        basis.lock_read()
581
        try:
582
            self.assertEqual(kind, basis.kind(file_id))
583
        finally:
584
            basis.unlock()
585
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
586
    def test_commit_kind_changes(self):
587
        if not osutils.has_symlinks():
588
            raise tests.TestSkipped('Test requires symlink support')
589
        tree = self.make_branch_and_tree('.')
590
        os.symlink('target', 'name')
591
        tree.add('name', 'a-file-id')
592
        tree.commit('Added a symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
593
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
594
595
        os.unlink('name')
596
        self.build_tree(['name'])
597
        tree.commit('Changed symlink to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
598
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
599
600
        os.unlink('name')
601
        os.symlink('target', 'name')
602
        tree.commit('file to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
603
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
604
605
        os.unlink('name')
606
        os.mkdir('name')
607
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
608
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
609
610
        os.rmdir('name')
611
        os.symlink('target', 'name')
612
        tree.commit('directory to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
613
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
614
615
        # prepare for directory <-> file tests
616
        os.unlink('name')
617
        os.mkdir('name')
618
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
619
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
620
621
        os.rmdir('name')
622
        self.build_tree(['name'])
623
        tree.commit('Changed directory to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
624
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
625
626
        os.unlink('name')
627
        os.mkdir('name')
628
        tree.commit('file to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
629
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.2 by Aaron Bentley
Merge bzr.dev
630
1551.8.29 by Aaron Bentley
Stop accepting non-existant files in commit (#50793)
631
    def test_commit_unversioned_specified(self):
632
        """Commit should raise if specified files isn't in basis or worktree"""
633
        tree = self.make_branch_and_tree('.')
634
        self.assertRaises(errors.PathsNotVersionedError, tree.commit, 
635
                          'message', specific_files=['bogus'])
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
636
637
    class Callback(object):
638
        
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
639
        def __init__(self, message, testcase):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
640
            self.called = False
641
            self.message = message
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
642
            self.testcase = testcase
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
643
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
644
        def __call__(self, commit_obj):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
645
            self.called = True
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
646
            self.testcase.assertTrue(isinstance(commit_obj, Commit))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
647
            return self.message
648
649
    def test_commit_callback(self):
650
        """Commit should invoke a callback to get the message"""
651
652
        tree = self.make_branch_and_tree('.')
653
        try:
654
            tree.commit()
655
        except Exception, e:
656
            self.assertTrue(isinstance(e, BzrError))
2149.1.3 by Aaron Bentley
Updates from review comments
657
            self.assertEqual('The message or message_callback keyword'
658
                             ' parameter is required for commit().', str(e))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
659
        else:
660
            self.fail('exception not raised')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
661
        cb = self.Callback(u'commit 1', self)
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
662
        tree.commit(message_callback=cb)
663
        self.assertTrue(cb.called)
664
        repository = tree.branch.repository
665
        message = repository.get_revision(tree.last_revision()).message
666
        self.assertEqual('commit 1', message)
667
668
    def test_no_callback_pointless(self):
669
        """Callback should not be invoked for pointless commit"""
670
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
671
        cb = self.Callback(u'commit 2', self)
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
672
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb, 
673
                          allow_pointless=False)
674
        self.assertFalse(cb.called)
675
676
    def test_no_callback_netfailure(self):
677
        """Callback should not be invoked if connectivity fails"""
2149.1.3 by Aaron Bentley
Updates from review comments
678
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
679
        cb = self.Callback(u'commit 2', self)
2149.1.3 by Aaron Bentley
Updates from review comments
680
        repository = tree.branch.repository
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
681
        # simulate network failure
682
        def raise_(self, arg, arg2):
683
            raise errors.NoSuchFile('foo')
684
        repository.add_inventory = raise_
685
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
686
        self.assertFalse(cb.called)
1551.15.9 by Aaron Bentley
Better error for selected-file commit of merges
687
688
    def test_selected_file_merge_commit(self):
689
        """Ensure the correct error is raised"""
690
        tree = self.make_branch_and_tree('foo')
691
        # pending merge would turn into a left parent
692
        tree.commit('commit 1')
693
        tree.add_parent_tree_id('example')
694
        self.build_tree(['foo/bar', 'foo/baz'])
695
        tree.add(['bar', 'baz'])
696
        err = self.assertRaises(errors.CannotCommitSelectedFileMerge,
697
            tree.commit, 'commit 2', specific_files=['bar', 'baz'])
698
        self.assertEqual(['bar', 'baz'], err.files)
699
        self.assertEqual('Selected-file commit of merges is not supported'
700
                         ' yet: files bar, baz', str(err))
2671.2.2 by Lukáš Lalinský
Move setting of the author revision property to MutableTree.commit. Don't use try/except KeyError in LongLogFormatter to display authors and branch-nicks. Removed warning about missing e-mail in the authors name.
701
2829.1.1 by Ian Clatworthy
re-apply Aaron's fix for #94975 (Ian Clatworthy)
702
    def test_commit_ordering(self):
703
        """Test of corner-case commit ordering error"""
704
        tree = self.make_branch_and_tree('.')
705
        self.build_tree(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
706
        tree.add(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
707
        tree.commit('setup')
708
        self.build_tree(['a/c/d/'])
709
        tree.add('a/c/d')
710
        tree.rename_one('a/z/x', 'a/c/d/x')
711
        tree.commit('test', specific_files=['a/z/y'])
712
 
2671.2.2 by Lukáš Lalinský
Move setting of the author revision property to MutableTree.commit. Don't use try/except KeyError in LongLogFormatter to display authors and branch-nicks. Removed warning about missing e-mail in the authors name.
713
    def test_commit_no_author(self):
714
        """The default kwarg author in MutableTree.commit should not add
715
        the 'author' revision property.
716
        """
717
        tree = self.make_branch_and_tree('foo')
718
        rev_id = tree.commit('commit 1')
719
        rev = tree.branch.repository.get_revision(rev_id)
720
        self.assertFalse('author' in rev.properties)
721
722
    def test_commit_author(self):
723
        """Passing a non-empty author kwarg to MutableTree.commit should add
724
        the 'author' revision property.
725
        """
726
        tree = self.make_branch_and_tree('foo')
727
        rev_id = tree.commit('commit 1', author='John Doe <jdoe@example.com>')
728
        rev = tree.branch.repository.get_revision(rev_id)
729
        self.assertEqual('John Doe <jdoe@example.com>',
730
                         rev.properties['author'])