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