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