~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/test_commit.py

  • Committer: Aaron Bentley
  • Date: 2005-10-20 02:57:55 UTC
  • mto: (1185.25.1)
  • mto: This revision was merged to the branch mainline in revision 1474.
  • Revision ID: aaron.bentley@utoronto.ca-20051020025755-e03df41c52aa3156
tweaked spacing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
22
from bzrlib.workingtree import WorkingTree
 
23
from bzrlib.commit import Commit
 
24
from bzrlib.config import BranchConfig
 
25
from bzrlib.errors import PointlessCommit, BzrError, SigningFailed
 
26
 
 
27
 
 
28
# TODO: Test commit with some added, and added-but-missing files
 
29
 
 
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
 
 
39
class TestCommit(TestCaseInTempDir):
 
40
 
 
41
    def test_simple_commit(self):
 
42
        """Commit and check two versions of a single file."""
 
43
        b = Branch.initialize('.')
 
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"""
 
67
        b = Branch.initialize('.')
 
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
 
 
78
 
 
79
    def test_pointless_commit(self):
 
80
        """Commit refuses unless there are changes or it's forced."""
 
81
        b = Branch.initialize('.')
 
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
 
 
94
    def test_commit_empty(self):
 
95
        """Commiting an empty tree works."""
 
96
        b = Branch.initialize('.')
 
97
        b.commit(message='empty tree', allow_pointless=True)
 
98
        self.assertRaises(PointlessCommit,
 
99
                          b.commit,
 
100
                          message='empty tree',
 
101
                          allow_pointless=False)
 
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"""
 
108
        b = Branch.initialize('.')
 
109
        file('hello', 'w').write('hello')
 
110
        file('buongia', 'w').write('buongia')
 
111
        b.add(['hello', 'buongia'],
 
112
              ['hello-id', 'buongia-id'])
 
113
        b.commit(message='add files',
 
114
                 rev_id='test@rev-1')
 
115
        
 
116
        os.remove('hello')
 
117
        file('buongia', 'w').write('new text')
 
118
        b.commit(message='update text',
 
119
                 specific_files=['buongia'],
 
120
                 allow_pointless=False,
 
121
                 rev_id='test@rev-2')
 
122
 
 
123
        b.commit(message='remove hello',
 
124
                 specific_files=['hello'],
 
125
                 allow_pointless=False,
 
126
                 rev_id='test@rev-3')
 
127
 
 
128
        eq = self.assertEquals
 
129
        eq(b.revno(), 3)
 
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')
 
139
 
 
140
 
 
141
    def test_commit_rename(self):
 
142
        """Test commit of a revision where a file is renamed."""
 
143
        b = Branch.initialize('.')
 
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
 
 
151
        eq = self.assertEquals
 
152
        tree1 = b.revision_tree('test@rev-1')
 
153
        eq(tree1.id2path('hello-id'), 'hello')
 
154
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
 
155
        self.assertFalse(tree1.has_filename('fruity'))
 
156
        self.check_inventory_shape(tree1.inventory, ['hello'])
 
157
        ie = tree1.inventory['hello-id']
 
158
        eq(ie.revision, 'test@rev-1')
 
159
 
 
160
        tree2 = b.revision_tree('test@rev-2')
 
161
        eq(tree2.id2path('hello-id'), 'fruity')
 
162
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
 
163
        self.check_inventory_shape(tree2.inventory, ['fruity'])
 
164
        ie = tree2.inventory['hello-id']
 
165
        eq(ie.revision, 'test@rev-2')
 
166
 
 
167
 
 
168
    def test_reused_rev_id(self):
 
169
        """Test that a revision id cannot be reused in a branch"""
 
170
        b = Branch.initialize('.')
 
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
                          
 
178
 
 
179
 
 
180
    def test_commit_move(self):
 
181
        """Test commit of revisions with moved files and directories"""
 
182
        eq = self.assertEquals
 
183
        b = Branch.initialize('.')
 
184
        r1 = 'test@rev-1'
 
185
        self.build_tree(['hello', 'a/', 'b/'])
 
186
        b.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
 
187
        b.commit('initial', rev_id=r1, allow_pointless=False)
 
188
 
 
189
        b.move(['hello'], 'a')
 
190
        r2 = 'test@rev-2'
 
191
        b.commit('two', rev_id=r2, allow_pointless=False)
 
192
        self.check_inventory_shape(b.inventory,
 
193
                                   ['a', 'a/hello', 'b'])
 
194
 
 
195
        b.move(['b'], 'a')
 
196
        r3 = 'test@rev-3'
 
197
        b.commit('three', rev_id=r3, allow_pointless=False)
 
198
        self.check_inventory_shape(b.inventory,
 
199
                                   ['a', 'a/hello', 'a/b'])
 
200
        self.check_inventory_shape(b.get_revision_inventory(r3),
 
201
                                   ['a', 'a/hello', 'a/b'])
 
202
 
 
203
        b.move([os.sep.join(['a', 'hello'])],
 
204
               os.sep.join(['a', 'b']))
 
205
        r4 = 'test@rev-4'
 
206
        b.commit('four', rev_id=r4, allow_pointless=False)
 
207
        self.check_inventory_shape(b.inventory,
 
208
                                   ['a', 'a/b/hello', 'a/b'])
 
209
 
 
210
        inv = b.get_revision_inventory(r4)
 
211
        eq(inv['hello-id'].revision, r4)
 
212
        eq(inv['a-id'].revision, r1)
 
213
        eq(inv['b-id'].revision, r3)
 
214
 
 
215
        
 
216
    def test_removed_commit(self):
 
217
        """Commit with a removed file"""
 
218
        b = Branch.initialize('.')
 
219
        wt = b.working_tree()
 
220
        file('hello', 'w').write('hello world')
 
221
        b.add(['hello'], ['hello-id'])
 
222
        b.commit(message='add hello')
 
223
 
 
224
        wt = b.working_tree()  # FIXME: kludge for aliasing of working inventory
 
225
        wt.remove('hello')
 
226
        b.commit('removed hello', rev_id='rev2')
 
227
 
 
228
        tree = b.revision_tree('rev2')
 
229
        self.assertFalse(tree.has_id('hello-id'))
 
230
 
 
231
 
 
232
    def test_committed_ancestry(self):
 
233
        """Test commit appends revisions to ancestry."""
 
234
        b = Branch.initialize('.')
 
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])
 
248
            eq(anc, [None] + rev_ids[:i+1])
 
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')
 
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)
 
279
 
 
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
 
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