~bzr-pqm/bzr/bzr.dev

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