~bzr-pqm/bzr/bzr.dev

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