~bzr-pqm/bzr/bzr.dev

1246 by Martin Pool
- add very simple commit tests
1
# Copyright (C) 2005 by Canonical Ltd
2
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.
7
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.
12
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
18
import os
19
20
from bzrlib.selftest import TestCaseInTempDir
21
from bzrlib.branch import Branch
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
22
from bzrlib.workingtree import WorkingTree
1246 by Martin Pool
- add very simple commit tests
23
from bzrlib.commit import Commit
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
24
from bzrlib.config import BranchConfig
1442.1.62 by Robert Collins
Allow creation of testaments from uncommitted data, and use that to get signatures before committing revisions.
25
from bzrlib.errors import PointlessCommit, BzrError, SigningFailed
1246 by Martin Pool
- add very simple commit tests
26
27
1257 by Martin Pool
doc
28
# TODO: Test commit with some added, and added-but-missing files
29
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
30
class MustSignConfig(BranchConfig):
31
32
    def signature_needed(self):
33
        return True
34
35
    def gpg_signing_command(self):
36
        return ['cat', '-']
37
38
1246 by Martin Pool
- add very simple commit tests
39
class TestCommit(TestCaseInTempDir):
1390 by Robert Collins
pair programming worx... merge integration and weave
40
1246 by Martin Pool
- add very simple commit tests
41
    def test_simple_commit(self):
42
        """Commit and check two versions of a single file."""
1390 by Robert Collins
pair programming worx... merge integration and weave
43
        b = Branch.initialize('.')
1246 by Martin Pool
- add very simple commit tests
44
        file('hello', 'w').write('hello world')
45
        b.add('hello')
46
        b.commit(message='add hello')
47
        file_id = b.working_tree().path2id('hello')
48
49
        file('hello', 'w').write('version 2')
50
        b.commit(message='commit 2')
51
52
        eq = self.assertEquals
53
        eq(b.revno(), 2)
54
        rh = b.revision_history()
55
        rev = b.get_revision(rh[0])
56
        eq(rev.message, 'add hello')
57
58
        tree1 = b.revision_tree(rh[0])
59
        text = tree1.get_file_text(file_id)
60
        eq(text, 'hello world')
61
62
        tree2 = b.revision_tree(rh[1])
63
        eq(tree2.get_file_text(file_id), 'version 2')
64
65
    def test_delete_commit(self):
66
        """Test a commit with a deleted file"""
1390 by Robert Collins
pair programming worx... merge integration and weave
67
        b = Branch.initialize('.')
1247 by Martin Pool
- tests for deletion and removal of files in commits
68
        file('hello', 'w').write('hello world')
69
        b.add(['hello'], ['hello-id'])
70
        b.commit(message='add hello')
71
72
        os.remove('hello')
73
        b.commit('removed hello', rev_id='rev2')
74
75
        tree = b.revision_tree('rev2')
76
        self.assertFalse(tree.has_id('hello-id'))
77
1246 by Martin Pool
- add very simple commit tests
78
1253 by Martin Pool
- test that pointless commits are trapped
79
    def test_pointless_commit(self):
80
        """Commit refuses unless there are changes or it's forced."""
1390 by Robert Collins
pair programming worx... merge integration and weave
81
        b = Branch.initialize('.')
1253 by Martin Pool
- test that pointless commits are trapped
82
        file('hello', 'w').write('hello')
83
        b.add(['hello'])
84
        b.commit(message='add hello')
85
        self.assertEquals(b.revno(), 1)
86
        self.assertRaises(PointlessCommit,
87
                          b.commit,
88
                          message='fails',
89
                          allow_pointless=False)
90
        self.assertEquals(b.revno(), 1)
91
        
92
93
1252 by Martin Pool
- add test for commit of an empty tree
94
    def test_commit_empty(self):
1253 by Martin Pool
- test that pointless commits are trapped
95
        """Commiting an empty tree works."""
1390 by Robert Collins
pair programming worx... merge integration and weave
96
        b = Branch.initialize('.')
1252 by Martin Pool
- add test for commit of an empty tree
97
        b.commit(message='empty tree', allow_pointless=True)
1253 by Martin Pool
- test that pointless commits are trapped
98
        self.assertRaises(PointlessCommit,
99
                          b.commit,
100
                          message='empty tree',
101
                          allow_pointless=False)
1252 by Martin Pool
- add test for commit of an empty tree
102
        b.commit(message='empty tree', allow_pointless=True)
103
        self.assertEquals(b.revno(), 2)
104
105
106
    def test_selective_delete(self):
107
        """Selective commit in tree with deletions"""
1390 by Robert Collins
pair programming worx... merge integration and weave
108
        b = Branch.initialize('.')
1254 by Martin Pool
- fix handling of selective commit with deleted files
109
        file('hello', 'w').write('hello')
110
        file('buongia', 'w').write('buongia')
1255 by Martin Pool
- more tests for selective commit of deletion
111
        b.add(['hello', 'buongia'],
112
              ['hello-id', 'buongia-id'])
113
        b.commit(message='add files',
114
                 rev_id='test@rev-1')
1254 by Martin Pool
- fix handling of selective commit with deleted files
115
        
116
        os.remove('hello')
117
        file('buongia', 'w').write('new text')
118
        b.commit(message='update text',
119
                 specific_files=['buongia'],
1255 by Martin Pool
- more tests for selective commit of deletion
120
                 allow_pointless=False,
121
                 rev_id='test@rev-2')
1254 by Martin Pool
- fix handling of selective commit with deleted files
122
123
        b.commit(message='remove hello',
124
                 specific_files=['hello'],
1255 by Martin Pool
- more tests for selective commit of deletion
125
                 allow_pointless=False,
126
                 rev_id='test@rev-3')
1254 by Martin Pool
- fix handling of selective commit with deleted files
127
128
        eq = self.assertEquals
129
        eq(b.revno(), 3)
1255 by Martin Pool
- more tests for selective commit of deletion
130
131
        tree2 = b.revision_tree('test@rev-2')
132
        self.assertTrue(tree2.has_filename('hello'))
133
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
134
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
135
        
136
        tree3 = b.revision_tree('test@rev-3')
137
        self.assertFalse(tree3.has_filename('hello'))
138
        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
139
140
141
    def test_commit_rename(self):
142
        """Test commit of a revision where a file is renamed."""
1390 by Robert Collins
pair programming worx... merge integration and weave
143
        b = Branch.initialize('.')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
144
        self.build_tree(['hello'])
145
        b.add(['hello'], ['hello-id'])
146
        b.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
147
148
        b.rename_one('hello', 'fruity')
149
        b.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
150
1303 by Martin Pool
- commit updates entry_version
151
        eq = self.assertEquals
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
152
        tree1 = b.revision_tree('test@rev-1')
1303 by Martin Pool
- commit updates entry_version
153
        eq(tree1.id2path('hello-id'), 'hello')
154
        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
155
        self.assertFalse(tree1.has_filename('fruity'))
1291 by Martin Pool
- add test for moving files between directories
156
        self.check_inventory_shape(tree1.inventory, ['hello'])
1303 by Martin Pool
- commit updates entry_version
157
        ie = tree1.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
158
        eq(ie.revision, 'test@rev-1')
1285 by Martin Pool
- fix bug in committing files that are renamed but not modified
159
160
        tree2 = b.revision_tree('test@rev-2')
1303 by Martin Pool
- commit updates entry_version
161
        eq(tree2.id2path('hello-id'), 'fruity')
162
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
1291 by Martin Pool
- add test for moving files between directories
163
        self.check_inventory_shape(tree2.inventory, ['fruity'])
1303 by Martin Pool
- commit updates entry_version
164
        ie = tree2.inventory['hello-id']
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
165
        eq(ie.revision, 'test@rev-2')
1291 by Martin Pool
- add test for moving files between directories
166
167
168
    def test_reused_rev_id(self):
1292 by Martin Pool
- add check that revision ids cannot be committed twice
169
        """Test that a revision id cannot be reused in a branch"""
1390 by Robert Collins
pair programming worx... merge integration and weave
170
        b = Branch.initialize('.')
1292 by Martin Pool
- add check that revision ids cannot be committed twice
171
        b.commit('initial', rev_id='test@rev-1', allow_pointless=True)
172
        self.assertRaises(Exception,
173
                          b.commit,
174
                          message='reused id',
175
                          rev_id='test@rev-1',
176
                          allow_pointless=True)
177
                          
1291 by Martin Pool
- add test for moving files between directories
178
179
180
    def test_commit_move(self):
181
        """Test commit of revisions with moved files and directories"""
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
182
        eq = self.assertEquals
1390 by Robert Collins
pair programming worx... merge integration and weave
183
        b = Branch.initialize('.')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
184
        r1 = 'test@rev-1'
1291 by Martin Pool
- add test for moving files between directories
185
        self.build_tree(['hello', 'a/', 'b/'])
186
        b.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
187
        b.commit('initial', rev_id=r1, allow_pointless=False)
1291 by Martin Pool
- add test for moving files between directories
188
189
        b.move(['hello'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
190
        r2 = 'test@rev-2'
191
        b.commit('two', rev_id=r2, allow_pointless=False)
1291 by Martin Pool
- add test for moving files between directories
192
        self.check_inventory_shape(b.inventory,
193
                                   ['a', 'a/hello', 'b'])
194
195
        b.move(['b'], 'a')
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
196
        r3 = 'test@rev-3'
197
        b.commit('three', rev_id=r3, allow_pointless=False)
1291 by Martin Pool
- add test for moving files between directories
198
        self.check_inventory_shape(b.inventory,
199
                                   ['a', 'a/hello', 'a/b'])
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
200
        self.check_inventory_shape(b.get_revision_inventory(r3),
1291 by Martin Pool
- add test for moving files between directories
201
                                   ['a', 'a/hello', 'a/b'])
202
203
        b.move([os.sep.join(['a', 'hello'])],
204
               os.sep.join(['a', 'b']))
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
205
        r4 = 'test@rev-4'
206
        b.commit('four', rev_id=r4, allow_pointless=False)
1291 by Martin Pool
- add test for moving files between directories
207
        self.check_inventory_shape(b.inventory,
208
                                   ['a', 'a/b/hello', 'a/b'])
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
209
210
        inv = b.get_revision_inventory(r4)
1092.2.21 by Robert Collins
convert name_version to revision in inventory entries
211
        eq(inv['hello-id'].revision, r4)
212
        eq(inv['a-id'].revision, r1)
213
        eq(inv['b-id'].revision, r3)
1306 by Martin Pool
- tests that name_version is updated properly in renames/moves
214
215
        
1246 by Martin Pool
- add very simple commit tests
216
    def test_removed_commit(self):
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
217
        """Commit with a removed file"""
1390 by Robert Collins
pair programming worx... merge integration and weave
218
        b = Branch.initialize('.')
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
219
        wt = b.working_tree()
1247 by Martin Pool
- tests for deletion and removal of files in commits
220
        file('hello', 'w').write('hello world')
221
        b.add(['hello'], ['hello-id'])
222
        b.commit(message='add hello')
223
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
224
        wt = b.working_tree()  # FIXME: kludge for aliasing of working inventory
225
        wt.remove('hello')
1247 by Martin Pool
- tests for deletion and removal of files in commits
226
        b.commit('removed hello', rev_id='rev2')
227
228
        tree = b.revision_tree('rev2')
229
        self.assertFalse(tree.has_id('hello-id'))
1246 by Martin Pool
- add very simple commit tests
230
231
1256 by Martin Pool
- test that commits append to the tree's ancestry
232
    def test_committed_ancestry(self):
233
        """Test commit appends revisions to ancestry."""
1390 by Robert Collins
pair programming worx... merge integration and weave
234
        b = Branch.initialize('.')
1256 by Martin Pool
- test that commits append to the tree's ancestry
235
        rev_ids = []
236
        for i in range(4):
237
            file('hello', 'w').write((str(i) * 4) + '\n')
238
            if i == 0:
239
                b.add(['hello'], ['hello-id'])
240
            rev_id = 'test@rev-%d' % (i+1)
241
            rev_ids.append(rev_id)
242
            b.commit(message='rev %d' % (i+1),
243
                     rev_id=rev_id)
244
        eq = self.assertEquals
245
        eq(b.revision_history(), rev_ids)
246
        for i in range(4):
247
            anc = b.get_ancestry(rev_ids[i])
1390 by Robert Collins
pair programming worx... merge integration and weave
248
            eq(anc, [None] + rev_ids[:i+1])
1416 by Robert Collins
when committing a specific file, include all its parents
249
250
    def test_commit_new_subdir_child_selective(self):
251
        b = Branch.initialize('.')
252
        self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
253
        b.add(['dir', 'dir/file1', 'dir/file2'],
254
              ['dirid', 'file1id', 'file2id'])
255
        b.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
256
        inv = b.get_inventory('1')
257
        self.assertEqual('1', inv['dirid'].revision)
258
        self.assertEqual('1', inv['file1id'].revision)
259
        # FIXME: This should raise a KeyError I think, rbc20051006
260
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
1185.16.65 by mbp at sourcefrog
- new commit --strict option
261
262
    def test_strict_commit(self):
263
        """Try and commit with unknown files and strict = True, should fail."""
264
        from bzrlib.errors import StrictCommitFailed
265
        b = Branch.initialize('.')
266
        file('hello', 'w').write('hello world')
267
        b.add('hello')
268
        file('goodbye', 'w').write('goodbye cruel world!')
269
        self.assertRaises(StrictCommitFailed, b.commit,
270
            message='add hello but not goodbye', strict=True)
271
272
    def test_nonstrict_commit(self):
273
        """Try and commit with unknown files and strict = False, should work."""
274
        b = Branch.initialize('.')
275
        file('hello', 'w').write('hello world')
276
        b.add('hello')
277
        file('goodbye', 'w').write('goodbye cruel world!')
278
        b.commit(message='add hello but not goodbye', strict=False)
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
279
1442.1.60 by Robert Collins
gpg sign commits if the policy says we need to
280
    def test_signed_commit(self):
281
        import bzrlib.gpg
282
        import bzrlib.commit as commit
283
        oldstrategy = bzrlib.gpg.GPGStrategy
284
        branch = Branch.initialize('.')
285
        branch.commit("base", allow_pointless=True, rev_id='A')
286
        self.failIf(branch.revision_store.has_id('A', 'sig'))
287
        try:
288
            from bzrlib.testament import Testament
289
            # monkey patch gpg signing mechanism
290
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
291
            commit.Commit(config=MustSignConfig(branch)).commit(branch, "base",
292
                                                      allow_pointless=True,
293
                                                      rev_id='B')
294
            self.assertEqual(Testament.from_revision(branch,'B').as_short_text(),
295
                             branch.revision_store.get('B', 'sig').read())
296
        finally:
297
            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.
298
299
    def test_commit_failed_signature(self):
300
        import bzrlib.gpg
301
        import bzrlib.commit as commit
302
        oldstrategy = bzrlib.gpg.GPGStrategy
303
        branch = Branch.initialize('.')
304
        branch.commit("base", allow_pointless=True, rev_id='A')
305
        self.failIf(branch.revision_store.has_id('A', 'sig'))
306
        try:
307
            from bzrlib.testament import Testament
308
            # monkey patch gpg signing mechanism
309
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
310
            config = MustSignConfig(branch)
311
            self.assertRaises(SigningFailed,
312
                              commit.Commit(config=config).commit,
313
                              branch, "base",
314
                              allow_pointless=True,
315
                              rev_id='B')
316
            branch = Branch.open('.')
317
            self.assertEqual(branch.revision_history(), ['A'])
318
            self.failIf(branch.revision_store.has_id('B'))
319
        finally:
320
            bzrlib.gpg.GPGStrategy = oldstrategy