~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.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
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.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
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.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
101
        rev = b.repository.get_revision(rev1)
1246 by Martin Pool
- add very simple commit tests
102
        eq(rev.message, 'add hello')
103
6165.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
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.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
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
        eq = self.assertEquals
368
        eq(b.revision_history(), rev_ids)
369
        for i in range(4):
5972.3.15 by Jelmer Vernooij
Use matchers.
370
            self.assertThat(rev_ids[:i+1],
371
                MatchesAncestry(b.repository, rev_ids[i]))
1416 by Robert Collins
when committing a specific file, include all its parents
372
373
    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.
374
        wt = self.make_branch_and_tree('.')
375
        b = wt.branch
1416 by Robert Collins
when committing a specific file, include all its parents
376
        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.
377
        wt.add(['dir', 'dir/file1', 'dir/file2'],
1416 by Robert Collins
when committing a specific file, include all its parents
378
              ['dirid', 'file1id', 'file2id'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
379
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
380
        inv = b.repository.get_inventory('1')
1416 by Robert Collins
when committing a specific file, include all its parents
381
        self.assertEqual('1', inv['dirid'].revision)
382
        self.assertEqual('1', inv['file1id'].revision)
383
        # FIXME: This should raise a KeyError I think, rbc20051006
384
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
385
386
    def test_strict_commit(self):
387
        """Try and commit with unknown files and strict = True, should fail."""
388
        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.
389
        wt = self.make_branch_and_tree('.')
390
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
391
        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.
392
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
393
        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()
394
        self.assertRaises(StrictCommitFailed, wt.commit,
1185.16.65 by mbp at sourcefrog
- new commit --strict option
395
            message='add hello but not goodbye', strict=True)
396
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
397
    def test_strict_commit_without_unknowns(self):
398
        """Try and commit with no unknown files and strict = True,
399
        should work."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
400
        wt = self.make_branch_and_tree('.')
401
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
402
        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.
403
        wt.add('hello')
404
        wt.commit(message='add hello', strict=True)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
405
1185.16.65 by mbp at sourcefrog
- new commit --strict option
406
    def test_nonstrict_commit(self):
407
        """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.
408
        wt = self.make_branch_and_tree('.')
409
        b = wt.branch
1185.16.65 by mbp at sourcefrog
- new commit --strict option
410
        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.
411
        wt.add('hello')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
412
        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.
413
        wt.commit(message='add hello but not goodbye', strict=False)
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
414
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
415
    def test_nonstrict_commit_without_unknowns(self):
416
        """Try and commit with no unknown files and strict = False,
417
        should work."""
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
418
        wt = self.make_branch_and_tree('.')
419
        b = wt.branch
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
420
        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.
421
        wt.add('hello')
422
        wt.commit(message='add hello', strict=False)
1185.22.4 by Michael Ellerman
Strict commit was a little .. ah .. too strict, oops :}
423
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
424
    def test_signed_commit(self):
425
        import bzrlib.gpg
426
        import bzrlib.commit as commit
427
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
428
        wt = self.make_branch_and_tree('.')
429
        branch = wt.branch
430
        wt.commit("base", allow_pointless=True, rev_id='A')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
431
        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
432
        try:
433
            from bzrlib.testament import Testament
434
            # monkey patch gpg signing mechanism
435
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
2149.1.3 by Aaron Bentley
Updates from review comments
436
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
437
                                                      allow_pointless=True,
438
                                                      rev_id='B',
439
                                                      working_tree=wt)
1551.12.15 by Aaron Bentley
add header/trailer to fake clearsigned texts
440
            def sign(text):
441
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
442
            self.assertEqual(sign(Testament.from_revision(branch.repository,
443
                             'B').as_short_text()),
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
444
                             branch.repository.get_signature_text('B'))
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
445
        finally:
446
            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.
447
448
    def test_commit_failed_signature(self):
449
        import bzrlib.gpg
450
        import bzrlib.commit as commit
451
        oldstrategy = bzrlib.gpg.GPGStrategy
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
452
        wt = self.make_branch_and_tree('.')
453
        branch = wt.branch
454
        wt.commit("base", allow_pointless=True, rev_id='A')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
455
        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.
456
        try:
457
            # monkey patch gpg signing mechanism
458
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
459
            config = MustSignConfig(branch)
460
            self.assertRaises(SigningFailed,
461
                              commit.Commit(config=config).commit,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
462
                              message="base",
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
463
                              allow_pointless=True,
1534.4.34 by Robert Collins
Fix remaining uses of deprecated apis within bzrlib.
464
                              rev_id='B',
465
                              working_tree=wt)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
466
            branch = Branch.open(self.get_url('.'))
6165.2.1 by Jelmer Vernooij
Avoid using revision_history in the testsuite, in preparation of deprecating it.
467
            self.assertEqual(branch.last_revision(), 'A')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
468
            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.
469
        finally:
470
            bzrlib.gpg.GPGStrategy = oldstrategy
1472 by Robert Collins
post commit hook, first pass implementation
471
472
    def test_commit_invokes_hooks(self):
473
        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.
474
        wt = self.make_branch_and_tree('.')
475
        branch = wt.branch
1472 by Robert Collins
post commit hook, first pass implementation
476
        calls = []
477
        def called(branch, rev_id):
478
            calls.append('called')
479
        bzrlib.ahook = called
480
        try:
481
            config = BranchWithHooks(branch)
482
            commit.Commit(config=config).commit(
2149.1.3 by Aaron Bentley
Updates from review comments
483
                            message = "base",
1472 by Robert Collins
post commit hook, first pass implementation
484
                            allow_pointless=True,
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
485
                            rev_id='A', working_tree = wt)
1472 by Robert Collins
post commit hook, first pass implementation
486
            self.assertEqual(['called', 'called'], calls)
487
        finally:
488
            del bzrlib.ahook
1593.1.1 by Robert Collins
Move responsibility for setting branch nickname in commits to the WorkingTree convenience function.
489
490
    def test_commit_object_doesnt_set_nick(self):
491
        # using the Commit object directly does not set the branch nick.
492
        wt = self.make_branch_and_tree('.')
493
        c = Commit()
2149.1.3 by Aaron Bentley
Updates from review comments
494
        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.
495
        self.assertEquals(wt.branch.revno(), 1)
496
        self.assertEqual({},
497
                         wt.branch.repository.get_revision(
498
                            wt.branch.last_revision()).properties)
499
1614.1.1 by Aaron Bentley
Fixed master locking in commit
500
    def test_safe_master_lock(self):
501
        os.mkdir('master')
502
        master = BzrDirMetaFormat1().initialize('master')
503
        master.create_repository()
504
        master_branch = master.create_branch()
505
        master.create_workingtree()
506
        bound = master.sprout('bound')
507
        wt = bound.open_workingtree()
508
        wt.branch.set_bound_location(os.path.realpath('master'))
509
        master_branch.lock_write()
1658.1.5 by Martin Pool
Release more locks taken during test suite
510
        try:
511
            self.assertRaises(LockContention, wt.commit, 'silly')
512
        finally:
513
            master_branch.unlock()
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
514
515
    def test_commit_bound_merge(self):
516
        # see bug #43959; commit of a merge in a bound branch fails to push
517
        # the new commit into the master
518
        master_branch = self.make_branch('master')
519
        bound_tree = self.make_branch_and_tree('bound')
520
        bound_tree.branch.bind(master_branch)
521
522
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
523
        bound_tree.add(['content_file'])
524
        bound_tree.commit(message='woo!')
525
526
        other_bzrdir = master_branch.bzrdir.sprout('other')
527
        other_tree = other_bzrdir.open_workingtree()
528
4775.1.1 by Martin Pool
Remove several 'the the' typos
529
        # 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)
530
        # that our commit after merging will have a merged revision in the
531
        # content file history.
532
        self.build_tree_contents([('other/content_file', 'change in other\n')])
533
        other_tree.commit('change in other')
534
535
        # do a merge into the bound branch from other, and then change the
536
        # content file locally to force a new revision (rather than using the
537
        # 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.
538
        bound_tree.merge_from_branch(other_tree.branch)
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
539
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
540
541
        # before #34959 was fixed, this failed with 'revision not present in
542
        # weave' when trying to implicitly push from the bound branch to the master
543
        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
544
545
    def test_commit_reporting_after_merge(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
546
        # 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
547
        # be called for each item that is added/removed/deleted.
548
        this_tree = self.make_branch_and_tree('this')
549
        # we need a bunch of files and dirs, to perform one action on each.
550
        self.build_tree([
551
            'this/dirtorename/',
552
            'this/dirtoreparent/',
553
            'this/dirtoleave/',
554
            'this/dirtoremove/',
555
            'this/filetoreparent',
556
            'this/filetorename',
557
            'this/filetomodify',
558
            'this/filetoremove',
559
            'this/filetoleave']
560
            )
561
        this_tree.add([
562
            'dirtorename',
563
            'dirtoreparent',
564
            'dirtoleave',
565
            'dirtoremove',
566
            'filetoreparent',
567
            'filetorename',
568
            'filetomodify',
569
            'filetoremove',
570
            'filetoleave']
571
            )
572
        this_tree.commit('create_files')
573
        other_dir = this_tree.bzrdir.sprout('other')
574
        other_tree = other_dir.open_workingtree()
575
        other_tree.lock_write()
576
        # perform the needed actions on the files and dirs.
577
        try:
578
            other_tree.rename_one('dirtorename', 'renameddir')
579
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
580
            other_tree.rename_one('filetorename', 'renamedfile')
581
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
582
            other_tree.remove(['dirtoremove', 'filetoremove'])
583
            self.build_tree_contents([
584
                ('other/newdir/', ),
585
                ('other/filetomodify', 'new content'),
586
                ('other/newfile', 'new file content')])
587
            other_tree.add('newfile')
588
            other_tree.add('newdir/')
589
            other_tree.commit('modify all sample files and dirs.')
590
        finally:
591
            other_tree.unlock()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
592
        this_tree.merge_from_branch(other_tree.branch)
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
593
        reporter = CapturingReporter()
594
        this_tree.commit('do the commit', reporter=reporter)
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
595
        expected = set([
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
596
            ('change', 'modified', 'filetomodify'),
597
            ('change', 'added', 'newdir'),
598
            ('change', 'added', 'newfile'),
599
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
2829.1.1 by Ian Clatworthy
re-apply Aaron's fix for #94975 (Ian Clatworthy)
600
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
1668.1.5 by Martin Pool
[broken] fix up display of files changed by a commit
601
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
602
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
603
            ('deleted', 'dirtoremove'),
604
            ('deleted', 'filetoremove'),
4183.5.5 by Robert Collins
Enable record_iter_changes for cases where it can work.
605
            ])
606
        result = set(reporter.calls)
607
        missing = expected - result
608
        new = result - expected
609
        self.assertEqual((set(), set()), (missing, new))
1551.7.24 by Aaron Bentley
Ensure commit respects file spec when committing removals
610
611
    def test_commit_removals_respects_filespec(self):
612
        """Commit respects the specified_files for removals."""
613
        tree = self.make_branch_and_tree('.')
614
        self.build_tree(['a', 'b'])
615
        tree.add(['a', 'b'])
616
        tree.commit('added a, b')
617
        tree.remove(['a', 'b'])
1906.1.1 by Robert Collins
(robertc) Trivial change to test_commit_removals_respects_filespec to be easir to read.
618
        tree.commit('removed a', specific_files='a')
2255.2.148 by John Arbash Meinel
lock a basis tree during a commit test.
619
        basis = tree.basis_tree()
620
        tree.lock_read()
621
        try:
622
            self.assertIs(None, basis.path2id('a'))
623
            self.assertFalse(basis.path2id('b') is None)
624
        finally:
625
            tree.unlock()
1864.2.1 by John Arbash Meinel
Commit timestamp restricted to 1ms precision.
626
627
    def test_commit_saves_1ms_timestamp(self):
628
        """Passing in a timestamp is saved with 1ms resolution"""
629
        tree = self.make_branch_and_tree('.')
630
        self.build_tree(['a'])
631
        tree.add('a')
632
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
633
                    rev_id='a1')
634
635
        rev = tree.branch.repository.get_revision('a1')
636
        self.assertEqual(1153248633.419, rev.timestamp)
637
638
    def test_commit_has_1ms_resolution(self):
639
        """Allowing commit to generate the timestamp also has 1ms resolution"""
640
        tree = self.make_branch_and_tree('.')
641
        self.build_tree(['a'])
642
        tree.add('a')
643
        tree.commit('added a', rev_id='a1')
644
645
        rev = tree.branch.repository.get_revision('a1')
646
        timestamp = rev.timestamp
647
        timestamp_1ms = round(timestamp, 3)
648
        self.assertEqual(timestamp_1ms, timestamp)
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
649
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
650
    def assertBasisTreeKind(self, kind, tree, file_id):
651
        basis = tree.basis_tree()
652
        basis.lock_read()
653
        try:
654
            self.assertEqual(kind, basis.kind(file_id))
655
        finally:
656
            basis.unlock()
657
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
658
    def test_commit_kind_changes(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
659
        self.requireFeature(SymlinkFeature)
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
660
        tree = self.make_branch_and_tree('.')
661
        os.symlink('target', 'name')
662
        tree.add('name', 'a-file-id')
663
        tree.commit('Added a symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
664
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
665
666
        os.unlink('name')
667
        self.build_tree(['name'])
668
        tree.commit('Changed symlink to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
669
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
670
671
        os.unlink('name')
672
        os.symlink('target', 'name')
673
        tree.commit('file to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
674
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
675
676
        os.unlink('name')
677
        os.mkdir('name')
678
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
679
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
680
681
        os.rmdir('name')
682
        os.symlink('target', 'name')
683
        tree.commit('directory to symlink')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
684
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
685
686
        # prepare for directory <-> file tests
687
        os.unlink('name')
688
        os.mkdir('name')
689
        tree.commit('symlink to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
690
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
691
692
        os.rmdir('name')
693
        self.build_tree(['name'])
694
        tree.commit('Changed directory to file')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
695
        self.assertBasisTreeKind('file', tree, 'a-file-id')
1959.4.1 by Aaron Bentley
Correctly handle all file kind changes
696
697
        os.unlink('name')
698
        os.mkdir('name')
699
        tree.commit('file to directory')
2255.2.135 by John Arbash Meinel
Add locking in the test_commit_kind_changes test.
700
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
1959.4.2 by Aaron Bentley
Merge bzr.dev
701
1551.8.29 by Aaron Bentley
Stop accepting non-existant files in commit (#50793)
702
    def test_commit_unversioned_specified(self):
703
        """Commit should raise if specified files isn't in basis or worktree"""
704
        tree = self.make_branch_and_tree('.')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
705
        self.assertRaises(errors.PathsNotVersionedError, tree.commit,
1551.8.29 by Aaron Bentley
Stop accepting non-existant files in commit (#50793)
706
                          'message', specific_files=['bogus'])
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
707
708
    class Callback(object):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
709
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
710
        def __init__(self, message, testcase):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
711
            self.called = False
712
            self.message = message
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
713
            self.testcase = testcase
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
714
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
715
        def __call__(self, commit_obj):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
716
            self.called = True
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
717
            self.testcase.assertTrue(isinstance(commit_obj, Commit))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
718
            return self.message
719
720
    def test_commit_callback(self):
721
        """Commit should invoke a callback to get the message"""
722
723
        tree = self.make_branch_and_tree('.')
724
        try:
725
            tree.commit()
726
        except Exception, e:
727
            self.assertTrue(isinstance(e, BzrError))
2149.1.3 by Aaron Bentley
Updates from review comments
728
            self.assertEqual('The message or message_callback keyword'
729
                             ' parameter is required for commit().', str(e))
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
730
        else:
731
            self.fail('exception not raised')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
732
        cb = self.Callback(u'commit 1', self)
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
733
        tree.commit(message_callback=cb)
734
        self.assertTrue(cb.called)
735
        repository = tree.branch.repository
736
        message = repository.get_revision(tree.last_revision()).message
737
        self.assertEqual('commit 1', message)
738
739
    def test_no_callback_pointless(self):
740
        """Callback should not be invoked for pointless commit"""
741
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
742
        cb = self.Callback(u'commit 2', self)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
743
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
744
                          allow_pointless=False)
745
        self.assertFalse(cb.called)
746
747
    def test_no_callback_netfailure(self):
748
        """Callback should not be invoked if connectivity fails"""
2149.1.3 by Aaron Bentley
Updates from review comments
749
        tree = self.make_branch_and_tree('.')
2149.1.4 by Aaron Bentley
Add additional test that callback is called with a Commit instance
750
        cb = self.Callback(u'commit 2', self)
2149.1.3 by Aaron Bentley
Updates from review comments
751
        repository = tree.branch.repository
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
752
        # simulate network failure
4617.2.1 by Robert Collins
Fix test_commit for use with 2a as the default repository.
753
        def raise_(self, arg, arg2, arg3=None, arg4=None):
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
754
            raise errors.NoSuchFile('foo')
755
        repository.add_inventory = raise_
4617.2.1 by Robert Collins
Fix test_commit for use with 2a as the default repository.
756
        repository.add_inventory_by_delta = raise_
2149.1.1 by Aaron Bentley
Provide a message_callback parameter to tree.commit
757
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
758
        self.assertFalse(cb.called)
1551.15.9 by Aaron Bentley
Better error for selected-file commit of merges
759
760
    def test_selected_file_merge_commit(self):
761
        """Ensure the correct error is raised"""
762
        tree = self.make_branch_and_tree('foo')
763
        # pending merge would turn into a left parent
764
        tree.commit('commit 1')
765
        tree.add_parent_tree_id('example')
766
        self.build_tree(['foo/bar', 'foo/baz'])
767
        tree.add(['bar', 'baz'])
768
        err = self.assertRaises(errors.CannotCommitSelectedFileMerge,
769
            tree.commit, 'commit 2', specific_files=['bar', 'baz'])
770
        self.assertEqual(['bar', 'baz'], err.files)
771
        self.assertEqual('Selected-file commit of merges is not supported'
772
                         ' 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.
773
2829.1.1 by Ian Clatworthy
re-apply Aaron's fix for #94975 (Ian Clatworthy)
774
    def test_commit_ordering(self):
775
        """Test of corner-case commit ordering error"""
776
        tree = self.make_branch_and_tree('.')
777
        self.build_tree(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
778
        tree.add(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
779
        tree.commit('setup')
780
        self.build_tree(['a/c/d/'])
781
        tree.add('a/c/d')
782
        tree.rename_one('a/z/x', 'a/c/d/x')
783
        tree.commit('test', specific_files=['a/z/y'])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
784
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.
785
    def test_commit_no_author(self):
786
        """The default kwarg author in MutableTree.commit should not add
787
        the 'author' revision property.
788
        """
789
        tree = self.make_branch_and_tree('foo')
790
        rev_id = tree.commit('commit 1')
791
        rev = tree.branch.repository.get_revision(rev_id)
792
        self.assertFalse('author' in rev.properties)
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
793
        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.
794
795
    def test_commit_author(self):
796
        """Passing a non-empty author kwarg to MutableTree.commit should add
797
        the 'author' revision property.
798
        """
799
        tree = self.make_branch_and_tree('foo')
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
800
        rev_id = self.callDeprecated(['The parameter author was '
801
                'deprecated in version 1.13. Use authors instead'],
802
                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.
803
        rev = tree.branch.repository.get_revision(rev_id)
804
        self.assertEqual('John Doe <jdoe@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
805
                         rev.properties['authors'])
806
        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)
807
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
808
    def test_commit_empty_authors_list(self):
809
        """Passing an empty list to authors shouldn't add the property."""
810
        tree = self.make_branch_and_tree('foo')
811
        rev_id = tree.commit('commit 1', authors=[])
812
        rev = tree.branch.repository.get_revision(rev_id)
813
        self.assertFalse('author' in rev.properties)
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
814
        self.assertFalse('authors' in rev.properties)
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
815
816
    def test_multiple_authors(self):
817
        tree = self.make_branch_and_tree('foo')
818
        rev_id = tree.commit('commit 1',
819
                authors=['John Doe <jdoe@example.com>',
820
                         'Jane Rey <jrey@example.com>'])
821
        rev = tree.branch.repository.get_revision(rev_id)
822
        self.assertEqual('John Doe <jdoe@example.com>\n'
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
823
                'Jane Rey <jrey@example.com>', rev.properties['authors'])
824
        self.assertFalse('author' in rev.properties)
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
825
826
    def test_author_and_authors_incompatible(self):
827
        tree = self.make_branch_and_tree('foo')
828
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
829
                authors=['John Doe <jdoe@example.com>',
830
                         'Jane Rey <jrey@example.com>'],
831
                author="Jack Me <jme@example.com>")
832
833
    def test_author_with_newline_rejected(self):
834
        tree = self.make_branch_and_tree('foo')
835
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
836
                authors=['John\nDoe <jdoe@example.com>'])
837
3113.6.7 by Aaron Bentley
Fix commit for a checkout sharing a repo with its branch (abentley, #177592)
838
    def test_commit_with_checkout_and_branch_sharing_repo(self):
839
        repo = self.make_repository('repo', shared=True)
840
        # make_branch_and_tree ignores shared repos
841
        branch = bzrdir.BzrDir.create_branch_convenience('repo/branch')
842
        tree2 = branch.create_checkout('repo/tree2')
843
        tree2.commit('message', rev_id='rev1')
844
        self.assertTrue(tree2.branch.repository.has_revision('rev1'))