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