21
from bzrlib.tests import TestCaseInTempDir
20
from bzrlib.selftest import TestCaseInTempDir
22
21
from bzrlib.branch import Branch
23
from bzrlib.workingtree import WorkingTree
24
22
from bzrlib.commit import Commit
25
from bzrlib.config import BranchConfig
26
from bzrlib.errors import PointlessCommit, BzrError, SigningFailed
23
from bzrlib.errors import PointlessCommit, BzrError
29
26
# TODO: Test commit with some added, and added-but-missing files
31
class MustSignConfig(BranchConfig):
33
def signature_needed(self):
36
def gpg_signing_command(self):
40
class BranchWithHooks(BranchConfig):
42
def post_commit(self):
43
return "bzrlib.ahook bzrlib.ahook"
46
28
class TestCommit(TestCaseInTempDir):
48
30
def test_simple_commit(self):
49
31
"""Commit and check two versions of a single file."""
50
b = Branch.initialize(u'.')
32
b = Branch.initialize('.')
51
33
file('hello', 'w').write('hello world')
52
b.working_tree().add('hello')
53
b.working_tree().commit(message='add hello')
35
b.commit(message='add hello')
54
36
file_id = b.working_tree().path2id('hello')
56
38
file('hello', 'w').write('version 2')
57
b.working_tree().commit(message='commit 2')
39
b.commit(message='commit 2')
59
41
eq = self.assertEquals
69
51
tree2 = b.revision_tree(rh[1])
70
52
eq(tree2.get_file_text(file_id), 'version 2')
72
55
def test_delete_commit(self):
73
56
"""Test a commit with a deleted file"""
74
b = Branch.initialize(u'.')
57
b = Branch.initialize('.')
75
58
file('hello', 'w').write('hello world')
76
b.working_tree().add(['hello'], ['hello-id'])
77
b.working_tree().commit(message='add hello')
59
b.add(['hello'], ['hello-id'])
60
b.commit(message='add hello')
80
b.working_tree().commit('removed hello', rev_id='rev2')
63
b.commit('removed hello', rev_id='rev2')
82
65
tree = b.revision_tree('rev2')
83
66
self.assertFalse(tree.has_id('hello-id'))
85
69
def test_pointless_commit(self):
86
70
"""Commit refuses unless there are changes or it's forced."""
87
b = Branch.initialize(u'.')
71
b = Branch.initialize('.')
88
72
file('hello', 'w').write('hello')
89
b.working_tree().add(['hello'])
90
b.working_tree().commit(message='add hello')
74
b.commit(message='add hello')
91
75
self.assertEquals(b.revno(), 1)
92
76
self.assertRaises(PointlessCommit,
93
b.working_tree().commit,
95
79
allow_pointless=False)
96
80
self.assertEquals(b.revno(), 1)
98
84
def test_commit_empty(self):
99
85
"""Commiting an empty tree works."""
100
b = Branch.initialize(u'.')
101
b.working_tree().commit(message='empty tree', allow_pointless=True)
86
b = Branch.initialize('.')
87
b.commit(message='empty tree', allow_pointless=True)
102
88
self.assertRaises(PointlessCommit,
103
b.working_tree().commit,
104
90
message='empty tree',
105
91
allow_pointless=False)
106
b.working_tree().commit(message='empty tree', allow_pointless=True)
92
b.commit(message='empty tree', allow_pointless=True)
107
93
self.assertEquals(b.revno(), 2)
110
96
def test_selective_delete(self):
111
97
"""Selective commit in tree with deletions"""
112
b = Branch.initialize(u'.')
98
b = Branch.initialize('.')
113
99
file('hello', 'w').write('hello')
114
100
file('buongia', 'w').write('buongia')
115
b.working_tree().add(['hello', 'buongia'],
101
b.add(['hello', 'buongia'],
116
102
['hello-id', 'buongia-id'])
117
b.working_tree().commit(message='add files',
103
b.commit(message='add files',
118
104
rev_id='test@rev-1')
120
106
os.remove('hello')
121
107
file('buongia', 'w').write('new text')
122
b.working_tree().commit(message='update text',
108
b.commit(message='update text',
123
109
specific_files=['buongia'],
124
110
allow_pointless=False,
125
111
rev_id='test@rev-2')
127
b.working_tree().commit(message='remove hello',
113
b.commit(message='remove hello',
128
114
specific_files=['hello'],
129
115
allow_pointless=False,
130
116
rev_id='test@rev-3')
145
131
def test_commit_rename(self):
146
132
"""Test commit of a revision where a file is renamed."""
147
b = Branch.initialize(u'.')
148
tree = WorkingTree(u'.', b)
149
self.build_tree(['hello'], line_endings='binary')
150
tree.add(['hello'], ['hello-id'])
151
tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
133
b = Branch.initialize('.')
134
self.build_tree(['hello'])
135
b.add(['hello'], ['hello-id'])
136
b.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
153
tree.rename_one('hello', 'fruity')
154
tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
138
b.rename_one('hello', 'fruity')
139
b.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
156
141
eq = self.assertEquals
157
142
tree1 = b.revision_tree('test@rev-1')
169
154
ie = tree2.inventory['hello-id']
170
155
eq(ie.revision, 'test@rev-2')
172
158
def test_reused_rev_id(self):
173
159
"""Test that a revision id cannot be reused in a branch"""
174
b = Branch.initialize(u'.')
175
b.working_tree().commit('initial', rev_id='test@rev-1', allow_pointless=True)
160
b = Branch.initialize('.')
161
b.commit('initial', rev_id='test@rev-1', allow_pointless=True)
176
162
self.assertRaises(Exception,
177
b.working_tree().commit,
178
164
message='reused id',
179
165
rev_id='test@rev-1',
180
166
allow_pointless=True)
182
170
def test_commit_move(self):
183
171
"""Test commit of revisions with moved files and directories"""
184
172
eq = self.assertEquals
185
b = Branch.initialize(u'.')
173
b = Branch.initialize('.')
186
174
r1 = 'test@rev-1'
187
175
self.build_tree(['hello', 'a/', 'b/'])
188
b.working_tree().add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
189
b.working_tree().commit('initial', rev_id=r1, allow_pointless=False)
190
b.working_tree().move(['hello'], 'a')
176
b.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
177
b.commit('initial', rev_id=r1, allow_pointless=False)
179
b.move(['hello'], 'a')
191
180
r2 = 'test@rev-2'
192
b.working_tree().commit('two', rev_id=r2, allow_pointless=False)
193
self.check_inventory_shape(b.working_tree().read_working_inventory(),
181
b.commit('two', rev_id=r2, allow_pointless=False)
182
self.check_inventory_shape(b.inventory,
194
183
['a', 'a/hello', 'b'])
196
b.working_tree().move(['b'], 'a')
197
186
r3 = 'test@rev-3'
198
b.working_tree().commit('three', rev_id=r3, allow_pointless=False)
199
self.check_inventory_shape(b.working_tree().read_working_inventory(),
187
b.commit('three', rev_id=r3, allow_pointless=False)
188
self.check_inventory_shape(b.inventory,
200
189
['a', 'a/hello', 'a/b'])
201
190
self.check_inventory_shape(b.get_revision_inventory(r3),
202
191
['a', 'a/hello', 'a/b'])
204
b.working_tree().move(['a/hello'], 'a/b')
193
b.move([os.sep.join(['a', 'hello'])],
194
os.sep.join(['a', 'b']))
205
195
r4 = 'test@rev-4'
206
b.working_tree().commit('four', rev_id=r4, allow_pointless=False)
207
self.check_inventory_shape(b.working_tree().read_working_inventory(),
196
b.commit('four', rev_id=r4, allow_pointless=False)
197
self.check_inventory_shape(b.inventory,
208
198
['a', 'a/b/hello', 'a/b'])
210
200
inv = b.get_revision_inventory(r4)
211
201
eq(inv['hello-id'].revision, r4)
212
202
eq(inv['a-id'].revision, r1)
213
203
eq(inv['b-id'].revision, r3)
215
206
def test_removed_commit(self):
216
"""Commit with a removed file"""
217
b = Branch.initialize(u'.')
218
wt = b.working_tree()
207
"""Test a commit with a removed file"""
208
b = Branch.initialize('.')
219
209
file('hello', 'w').write('hello world')
220
b.working_tree().add(['hello'], ['hello-id'])
221
b.working_tree().commit(message='add hello')
210
b.add(['hello'], ['hello-id'])
211
b.commit(message='add hello')
223
wt = b.working_tree() # FIXME: kludge for aliasing of working inventory
225
b.working_tree().commit('removed hello', rev_id='rev2')
214
b.commit('removed hello', rev_id='rev2')
227
216
tree = b.revision_tree('rev2')
228
217
self.assertFalse(tree.has_id('hello-id'))
247
236
eq(anc, [None] + rev_ids[:i+1])
249
238
def test_commit_new_subdir_child_selective(self):
250
b = Branch.initialize(u'.')
239
b = Branch.initialize('.')
251
240
self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
252
b.working_tree().add(['dir', 'dir/file1', 'dir/file2'],
241
b.add(['dir', 'dir/file1', 'dir/file2'],
253
242
['dirid', 'file1id', 'file2id'])
254
b.working_tree().commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
243
b.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
255
244
inv = b.get_inventory('1')
256
245
self.assertEqual('1', inv['dirid'].revision)
257
246
self.assertEqual('1', inv['file1id'].revision)
258
247
# FIXME: This should raise a KeyError I think, rbc20051006
259
248
self.assertRaises(BzrError, inv.__getitem__, 'file2id')
261
def test_strict_commit(self):
262
"""Try and commit with unknown files and strict = True, should fail."""
263
from bzrlib.errors import StrictCommitFailed
264
b = Branch.initialize(u'.')
265
file('hello', 'w').write('hello world')
266
b.working_tree().add('hello')
267
file('goodbye', 'w').write('goodbye cruel world!')
268
self.assertRaises(StrictCommitFailed, b.working_tree().commit,
269
message='add hello but not goodbye', strict=True)
271
def test_strict_commit_without_unknowns(self):
272
"""Try and commit with no unknown files and strict = True,
274
from bzrlib.errors import StrictCommitFailed
275
b = Branch.initialize(u'.')
276
file('hello', 'w').write('hello world')
277
b.working_tree().add('hello')
278
b.working_tree().commit(message='add hello', strict=True)
280
def test_nonstrict_commit(self):
281
"""Try and commit with unknown files and strict = False, should work."""
282
b = Branch.initialize(u'.')
283
file('hello', 'w').write('hello world')
284
b.working_tree().add('hello')
285
file('goodbye', 'w').write('goodbye cruel world!')
286
b.working_tree().commit(message='add hello but not goodbye', strict=False)
288
def test_nonstrict_commit_without_unknowns(self):
289
"""Try and commit with no unknown files and strict = False,
291
b = Branch.initialize(u'.')
292
file('hello', 'w').write('hello world')
293
b.working_tree().add('hello')
294
b.working_tree().commit(message='add hello', strict=False)
296
def test_signed_commit(self):
298
import bzrlib.commit as commit
299
oldstrategy = bzrlib.gpg.GPGStrategy
300
branch = Branch.initialize(u'.')
301
branch.working_tree().commit("base", allow_pointless=True, rev_id='A')
302
self.failIf(branch.revision_store.has_id('A', 'sig'))
304
from bzrlib.testament import Testament
305
# monkey patch gpg signing mechanism
306
bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
307
commit.Commit(config=MustSignConfig(branch)).commit(branch, "base",
308
allow_pointless=True,
310
self.assertEqual(Testament.from_revision(branch,'B').as_short_text(),
311
branch.revision_store.get('B', 'sig').read())
313
bzrlib.gpg.GPGStrategy = oldstrategy
315
def test_commit_failed_signature(self):
317
import bzrlib.commit as commit
318
oldstrategy = bzrlib.gpg.GPGStrategy
319
branch = Branch.initialize(u'.')
320
branch.working_tree().commit("base", allow_pointless=True, rev_id='A')
321
self.failIf(branch.revision_store.has_id('A', 'sig'))
323
from bzrlib.testament import Testament
324
# monkey patch gpg signing mechanism
325
bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
326
config = MustSignConfig(branch)
327
self.assertRaises(SigningFailed,
328
commit.Commit(config=config).commit,
330
allow_pointless=True,
332
branch = Branch.open(u'.')
333
self.assertEqual(branch.revision_history(), ['A'])
334
self.failIf(branch.revision_store.has_id('B'))
336
bzrlib.gpg.GPGStrategy = oldstrategy
338
def test_commit_invokes_hooks(self):
339
import bzrlib.commit as commit
340
branch = Branch.initialize(u'.')
342
def called(branch, rev_id):
343
calls.append('called')
344
bzrlib.ahook = called
346
config = BranchWithHooks(branch)
347
commit.Commit(config=config).commit(
349
allow_pointless=True,
351
self.assertEqual(['called', 'called'], calls)