21
from bzrlib.tests import TestCaseInTempDir
21
from bzrlib.tests import TestCaseWithTransport
22
22
from bzrlib.branch import Branch
23
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
23
24
from bzrlib.workingtree import WorkingTree
24
25
from bzrlib.commit import Commit
25
26
from bzrlib.config import BranchConfig
26
from bzrlib.errors import PointlessCommit, BzrError, SigningFailed
27
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
29
31
# TODO: Test commit with some added, and added-but-missing files
43
45
return "bzrlib.ahook bzrlib.ahook"
46
class TestCommit(TestCaseInTempDir):
48
class TestCommit(TestCaseWithTransport):
48
50
def test_simple_commit(self):
49
51
"""Commit and check two versions of a single file."""
50
b = Branch.initialize(u'.')
52
wt = self.make_branch_and_tree('.')
51
54
file('hello', 'w').write('hello world')
52
b.working_tree().add('hello')
53
b.working_tree().commit(message='add hello')
54
file_id = b.working_tree().path2id('hello')
56
wt.commit(message='add hello')
57
file_id = wt.path2id('hello')
56
59
file('hello', 'w').write('version 2')
57
b.working_tree().commit(message='commit 2')
60
wt.commit(message='commit 2')
59
62
eq = self.assertEquals
72
75
def test_delete_commit(self):
73
76
"""Test a commit with a deleted file"""
74
b = Branch.initialize(u'.')
77
wt = self.make_branch_and_tree('.')
75
79
file('hello', 'w').write('hello world')
76
b.working_tree().add(['hello'], ['hello-id'])
77
b.working_tree().commit(message='add hello')
80
wt.add(['hello'], ['hello-id'])
81
wt.commit(message='add hello')
80
b.working_tree().commit('removed hello', rev_id='rev2')
84
wt.commit('removed hello', rev_id='rev2')
82
86
tree = b.repository.revision_tree('rev2')
83
87
self.assertFalse(tree.has_id('hello-id'))
85
89
def test_pointless_commit(self):
86
90
"""Commit refuses unless there are changes or it's forced."""
87
b = Branch.initialize(u'.')
91
wt = self.make_branch_and_tree('.')
88
93
file('hello', 'w').write('hello')
89
b.working_tree().add(['hello'])
90
b.working_tree().commit(message='add hello')
95
wt.commit(message='add hello')
91
96
self.assertEquals(b.revno(), 1)
92
97
self.assertRaises(PointlessCommit,
93
b.working_tree().commit,
95
100
allow_pointless=False)
96
101
self.assertEquals(b.revno(), 1)
98
103
def test_commit_empty(self):
99
104
"""Commiting an empty tree works."""
100
b = Branch.initialize(u'.')
101
b.working_tree().commit(message='empty tree', allow_pointless=True)
105
wt = self.make_branch_and_tree('.')
107
wt.commit(message='empty tree', allow_pointless=True)
102
108
self.assertRaises(PointlessCommit,
103
b.working_tree().commit,
104
110
message='empty tree',
105
111
allow_pointless=False)
106
b.working_tree().commit(message='empty tree', allow_pointless=True)
112
wt.commit(message='empty tree', allow_pointless=True)
107
113
self.assertEquals(b.revno(), 2)
110
115
def test_selective_delete(self):
111
116
"""Selective commit in tree with deletions"""
112
b = Branch.initialize(u'.')
117
wt = self.make_branch_and_tree('.')
113
119
file('hello', 'w').write('hello')
114
120
file('buongia', 'w').write('buongia')
115
b.working_tree().add(['hello', 'buongia'],
121
wt.add(['hello', 'buongia'],
116
122
['hello-id', 'buongia-id'])
117
b.working_tree().commit(message='add files',
123
wt.commit(message='add files',
118
124
rev_id='test@rev-1')
120
126
os.remove('hello')
121
127
file('buongia', 'w').write('new text')
122
b.working_tree().commit(message='update text',
128
wt.commit(message='update text',
123
129
specific_files=['buongia'],
124
130
allow_pointless=False,
125
131
rev_id='test@rev-2')
127
b.working_tree().commit(message='remove hello',
133
wt.commit(message='remove hello',
128
134
specific_files=['hello'],
129
135
allow_pointless=False,
130
136
rev_id='test@rev-3')
141
147
self.assertFalse(tree3.has_filename('hello'))
142
148
self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
145
150
def test_commit_rename(self):
146
151
"""Test commit of a revision where a file is renamed."""
147
b = Branch.initialize(u'.')
148
tree = WorkingTree(u'.', b)
152
tree = self.make_branch_and_tree('.')
149
154
self.build_tree(['hello'], line_endings='binary')
150
155
tree.add(['hello'], ['hello-id'])
151
156
tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
182
188
def test_commit_move(self):
183
189
"""Test commit of revisions with moved files and directories"""
184
190
eq = self.assertEquals
185
b = Branch.initialize(u'.')
191
wt = self.make_branch_and_tree('.')
186
193
r1 = 'test@rev-1'
187
194
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')
195
wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
196
wt.commit('initial', rev_id=r1, allow_pointless=False)
197
wt.move(['hello'], 'a')
191
198
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(),
199
wt.commit('two', rev_id=r2, allow_pointless=False)
200
self.check_inventory_shape(wt.read_working_inventory(),
194
201
['a', 'a/hello', 'b'])
196
b.working_tree().move(['b'], 'a')
197
204
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(),
205
wt.commit('three', rev_id=r3, allow_pointless=False)
206
self.check_inventory_shape(wt.read_working_inventory(),
200
207
['a', 'a/hello', 'a/b'])
201
208
self.check_inventory_shape(b.repository.get_revision_inventory(r3),
202
209
['a', 'a/hello', 'a/b'])
204
b.working_tree().move(['a/hello'], 'a/b')
211
wt.move(['a/hello'], 'a/b')
205
212
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(),
213
wt.commit('four', rev_id=r4, allow_pointless=False)
214
self.check_inventory_shape(wt.read_working_inventory(),
208
215
['a', 'a/b/hello', 'a/b'])
210
217
inv = b.repository.get_revision_inventory(r4)
215
222
def test_removed_commit(self):
216
223
"""Commit with a removed file"""
217
b = Branch.initialize(u'.')
218
wt = b.working_tree()
224
wt = self.make_branch_and_tree('.')
219
226
file('hello', 'w').write('hello world')
220
b.working_tree().add(['hello'], ['hello-id'])
221
b.working_tree().commit(message='add hello')
223
wt = b.working_tree() # FIXME: kludge for aliasing of working inventory
227
wt.add(['hello'], ['hello-id'])
228
wt.commit(message='add hello')
224
229
wt.remove('hello')
225
b.working_tree().commit('removed hello', rev_id='rev2')
230
wt.commit('removed hello', rev_id='rev2')
227
232
tree = b.repository.revision_tree('rev2')
228
233
self.assertFalse(tree.has_id('hello-id'))
231
235
def test_committed_ancestry(self):
232
236
"""Test commit appends revisions to ancestry."""
233
b = Branch.initialize(u'.')
237
wt = self.make_branch_and_tree('.')
235
240
for i in range(4):
236
241
file('hello', 'w').write((str(i) * 4) + '\n')
238
b.working_tree().add(['hello'], ['hello-id'])
243
wt.add(['hello'], ['hello-id'])
239
244
rev_id = 'test@rev-%d' % (i+1)
240
245
rev_ids.append(rev_id)
241
b.working_tree().commit(message='rev %d' % (i+1),
246
wt.commit(message='rev %d' % (i+1),
243
248
eq = self.assertEquals
244
249
eq(b.revision_history(), rev_ids)
247
252
eq(anc, [None] + rev_ids[:i+1])
249
254
def test_commit_new_subdir_child_selective(self):
250
b = Branch.initialize(u'.')
255
wt = self.make_branch_and_tree('.')
251
257
self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
252
b.working_tree().add(['dir', 'dir/file1', 'dir/file2'],
258
wt.add(['dir', 'dir/file1', 'dir/file2'],
253
259
['dirid', 'file1id', 'file2id'])
254
b.working_tree().commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
260
wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
255
261
inv = b.repository.get_inventory('1')
256
262
self.assertEqual('1', inv['dirid'].revision)
257
263
self.assertEqual('1', inv['file1id'].revision)
261
267
def test_strict_commit(self):
262
268
"""Try and commit with unknown files and strict = True, should fail."""
263
269
from bzrlib.errors import StrictCommitFailed
264
b = Branch.initialize(u'.')
270
wt = self.make_branch_and_tree('.')
265
272
file('hello', 'w').write('hello world')
266
b.working_tree().add('hello')
267
274
file('goodbye', 'w').write('goodbye cruel world!')
268
self.assertRaises(StrictCommitFailed, b.working_tree().commit,
275
self.assertRaises(StrictCommitFailed, wt.commit,
269
276
message='add hello but not goodbye', strict=True)
271
278
def test_strict_commit_without_unknowns(self):
272
279
"""Try and commit with no unknown files and strict = True,
274
281
from bzrlib.errors import StrictCommitFailed
275
b = Branch.initialize(u'.')
282
wt = self.make_branch_and_tree('.')
276
284
file('hello', 'w').write('hello world')
277
b.working_tree().add('hello')
278
b.working_tree().commit(message='add hello', strict=True)
286
wt.commit(message='add hello', strict=True)
280
288
def test_nonstrict_commit(self):
281
289
"""Try and commit with unknown files and strict = False, should work."""
282
b = Branch.initialize(u'.')
290
wt = self.make_branch_and_tree('.')
283
292
file('hello', 'w').write('hello world')
284
b.working_tree().add('hello')
285
294
file('goodbye', 'w').write('goodbye cruel world!')
286
b.working_tree().commit(message='add hello but not goodbye', strict=False)
295
wt.commit(message='add hello but not goodbye', strict=False)
288
297
def test_nonstrict_commit_without_unknowns(self):
289
298
"""Try and commit with no unknown files and strict = False,
291
b = Branch.initialize(u'.')
300
wt = self.make_branch_and_tree('.')
292
302
file('hello', 'w').write('hello world')
293
b.working_tree().add('hello')
294
b.working_tree().commit(message='add hello', strict=False)
304
wt.commit(message='add hello', strict=False)
296
306
def test_signed_commit(self):
297
307
import bzrlib.gpg
298
308
import bzrlib.commit as commit
299
309
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.repository.revision_store.has_id('A', 'sig'))
310
wt = self.make_branch_and_tree('.')
312
wt.commit("base", allow_pointless=True, rev_id='A')
313
self.failIf(branch.repository.has_signature_for_revision_id('A'))
304
315
from bzrlib.testament import Testament
305
316
# monkey patch gpg signing mechanism
306
317
bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
307
commit.Commit(config=MustSignConfig(branch)).commit(branch, "base",
318
commit.Commit(config=MustSignConfig(branch)).commit(message="base",
308
319
allow_pointless=True,
310
322
self.assertEqual(Testament.from_revision(branch.repository,
311
323
'B').as_short_text(),
312
branch.repository.revision_store.get('B',
324
branch.repository.get_signature_text('B'))
315
326
bzrlib.gpg.GPGStrategy = oldstrategy
318
329
import bzrlib.gpg
319
330
import bzrlib.commit as commit
320
331
oldstrategy = bzrlib.gpg.GPGStrategy
321
branch = Branch.initialize(u'.')
322
branch.working_tree().commit("base", allow_pointless=True, rev_id='A')
323
self.failIf(branch.repository.revision_store.has_id('A', 'sig'))
332
wt = self.make_branch_and_tree('.')
334
wt.commit("base", allow_pointless=True, rev_id='A')
335
self.failIf(branch.repository.has_signature_for_revision_id('A'))
325
337
from bzrlib.testament import Testament
326
338
# monkey patch gpg signing mechanism
328
340
config = MustSignConfig(branch)
329
341
self.assertRaises(SigningFailed,
330
342
commit.Commit(config=config).commit,
332
344
allow_pointless=True,
334
branch = Branch.open(u'.')
347
branch = Branch.open(self.get_url('.'))
335
348
self.assertEqual(branch.revision_history(), ['A'])
336
self.failIf(branch.repository.revision_store.has_id('B'))
349
self.failIf(branch.repository.has_revision('B'))
338
351
bzrlib.gpg.GPGStrategy = oldstrategy
340
353
def test_commit_invokes_hooks(self):
341
354
import bzrlib.commit as commit
342
branch = Branch.initialize(u'.')
355
wt = self.make_branch_and_tree('.')
344
358
def called(branch, rev_id):
345
359
calls.append('called')
348
362
config = BranchWithHooks(branch)
349
363
commit.Commit(config=config).commit(
351
365
allow_pointless=True,
366
rev_id='A', working_tree = wt)
353
367
self.assertEqual(['called', 'called'], calls)
371
def test_commit_object_doesnt_set_nick(self):
372
# using the Commit object directly does not set the branch nick.
373
wt = self.make_branch_and_tree('.')
375
c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
376
self.assertEquals(wt.branch.revno(), 1)
378
wt.branch.repository.get_revision(
379
wt.branch.last_revision()).properties)
381
def test_safe_master_lock(self):
383
master = BzrDirMetaFormat1().initialize('master')
384
master.create_repository()
385
master_branch = master.create_branch()
386
master.create_workingtree()
387
bound = master.sprout('bound')
388
wt = bound.open_workingtree()
389
wt.branch.set_bound_location(os.path.realpath('master'))
390
master_branch.lock_write()
391
self.assertRaises(LockContention, wt.commit, 'silly')