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