1
# Copyright (C) 2005-2011 Canonical Ltd
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
21
21
from bzrlib import (
25
26
from bzrlib.branch import Branch
26
27
from bzrlib.bzrdir import BzrDirMetaFormat1
27
28
from bzrlib.commit import Commit, NullCommitReporter
28
from bzrlib.config import BranchConfig
29
29
from bzrlib.errors import (
45
45
# TODO: Test commit with some added, and added-but-missing files
47
class MustSignConfig(BranchConfig):
49
def signature_needed(self):
52
def gpg_signing_command(self):
56
class BranchWithHooks(BranchConfig):
58
def post_commit(self):
59
return "bzrlib.ahook bzrlib.ahook"
47
class MustSignConfig(config.MemoryStack):
50
super(MustSignConfig, self).__init__('''
51
gpg_signing_command=cat -
52
create_signatures=always
62
56
class CapturingReporter(NullCommitReporter):
88
82
"""Commit and check two versions of a single file."""
89
83
wt = self.make_branch_and_tree('.')
91
file('hello', 'w').write('hello world')
85
with file('hello', 'w') as f: f.write('hello world')
93
wt.commit(message='add hello')
87
rev1 = wt.commit(message='add hello')
94
88
file_id = wt.path2id('hello')
96
file('hello', 'w').write('version 2')
97
wt.commit(message='commit 2')
90
with file('hello', 'w') as f: f.write('version 2')
91
rev2 = wt.commit(message='commit 2')
99
eq = self.assertEquals
101
rh = b.revision_history()
102
rev = b.repository.get_revision(rh[0])
95
rev = b.repository.get_revision(rev1)
103
96
eq(rev.message, 'add hello')
105
tree1 = b.repository.revision_tree(rh[0])
98
tree1 = b.repository.revision_tree(rev1)
107
100
text = tree1.get_file_text(file_id)
109
102
self.assertEqual('hello world', text)
111
tree2 = b.repository.revision_tree(rh[1])
104
tree2 = b.repository.revision_tree(rev2)
112
105
tree2.lock_read()
113
106
text = tree2.get_file_text(file_id)
118
111
"""Attempt a lossy commit to a native branch."""
119
112
wt = self.make_branch_and_tree('.')
121
file('hello', 'w').write('hello world')
114
with file('hello', 'w') as f: f.write('hello world')
123
116
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
124
self.assertEquals('revid', revid)
117
self.assertEqual('revid', revid)
126
119
def test_commit_lossy_foreign(self):
127
120
"""Attempt a lossy commit to a foreign branch."""
129
122
wt = self.make_branch_and_tree('.',
130
123
format=test_foreign.DummyForeignVcsDirFormat())
132
file('hello', 'w').write('hello world')
125
with file('hello', 'w') as f: f.write('hello world')
134
127
revid = wt.commit(message='add hello', lossy=True,
135
128
timestamp=1302659388, timezone=0)
136
self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
129
self.assertEqual('dummy-v1:1302659388.0-0-UNKNOWN', revid)
138
131
def test_commit_bound_lossy_foreign(self):
139
132
"""Attempt a lossy commit to a bzr branch bound to a foreign branch."""
142
135
format=test_foreign.DummyForeignVcsDirFormat())
143
136
wt = foreign_branch.create_checkout("local")
145
file('local/hello', 'w').write('hello world')
138
with file('local/hello', 'w') as f: f.write('hello world')
147
140
revid = wt.commit(message='add hello', lossy=True,
148
141
timestamp=1302659388, timezone=0)
149
self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
150
self.assertEquals('dummy-v1:1302659388.0-0-0',
142
self.assertEqual('dummy-v1:1302659388.0-0-0', revid)
143
self.assertEqual('dummy-v1:1302659388.0-0-0',
151
144
foreign_branch.last_revision())
152
self.assertEquals('dummy-v1:1302659388.0-0-0',
145
self.assertEqual('dummy-v1:1302659388.0-0-0',
153
146
wt.branch.last_revision())
155
148
def test_missing_commit(self):
156
149
"""Test a commit with a missing file"""
157
150
wt = self.make_branch_and_tree('.')
159
file('hello', 'w').write('hello world')
152
with file('hello', 'w') as f: f.write('hello world')
160
153
wt.add(['hello'], ['hello-id'])
161
154
wt.commit(message='add hello')
163
156
os.remove('hello')
164
157
reporter = CapturingReporter()
165
158
wt.commit('removed hello', rev_id='rev2', reporter=reporter)
167
160
[('missing', u'hello'), ('deleted', u'hello')],
194
187
"""Commit refuses unless there are changes or it's forced."""
195
188
wt = self.make_branch_and_tree('.')
197
file('hello', 'w').write('hello')
190
with file('hello', 'w') as f: f.write('hello')
198
191
wt.add(['hello'])
199
192
wt.commit(message='add hello')
200
self.assertEquals(b.revno(), 1)
193
self.assertEqual(b.revno(), 1)
201
194
self.assertRaises(PointlessCommit,
204
197
allow_pointless=False)
205
self.assertEquals(b.revno(), 1)
198
self.assertEqual(b.revno(), 1)
207
200
def test_commit_empty(self):
208
201
"""Commiting an empty tree works."""
214
207
message='empty tree',
215
208
allow_pointless=False)
216
209
wt.commit(message='empty tree', allow_pointless=True)
217
self.assertEquals(b.revno(), 2)
210
self.assertEqual(b.revno(), 2)
219
212
def test_selective_delete(self):
220
213
"""Selective commit in tree with deletions"""
221
214
wt = self.make_branch_and_tree('.')
223
file('hello', 'w').write('hello')
224
file('buongia', 'w').write('buongia')
216
with file('hello', 'w') as f: f.write('hello')
217
with file('buongia', 'w') as f: f.write('buongia')
225
218
wt.add(['hello', 'buongia'],
226
219
['hello-id', 'buongia-id'])
227
220
wt.commit(message='add files',
228
221
rev_id='test@rev-1')
230
223
os.remove('hello')
231
file('buongia', 'w').write('new text')
224
with file('buongia', 'w') as f: f.write('new text')
232
225
wt.commit(message='update text',
233
226
specific_files=['buongia'],
234
227
allow_pointless=False,
239
232
allow_pointless=False,
240
233
rev_id='test@rev-3')
242
eq = self.assertEquals
235
eq = self.assertEqual
245
238
tree2 = b.repository.revision_tree('test@rev-2')
246
239
tree2.lock_read()
247
240
self.addCleanup(tree2.unlock)
248
241
self.assertTrue(tree2.has_filename('hello'))
249
self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
250
self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
242
self.assertEqual(tree2.get_file_text('hello-id'), 'hello')
243
self.assertEqual(tree2.get_file_text('buongia-id'), 'new text')
252
245
tree3 = b.repository.revision_tree('test@rev-3')
253
246
tree3.lock_read()
254
247
self.addCleanup(tree3.unlock)
255
248
self.assertFalse(tree3.has_filename('hello'))
256
self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
249
self.assertEqual(tree3.get_file_text('buongia-id'), 'new text')
258
251
def test_commit_rename(self):
259
252
"""Test commit of a revision where a file is renamed."""
266
259
tree.rename_one('hello', 'fruity')
267
260
tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
269
eq = self.assertEquals
262
eq = self.assertEqual
270
263
tree1 = b.repository.revision_tree('test@rev-1')
271
264
tree1.lock_read()
272
265
self.addCleanup(tree1.unlock)
343
336
"""Commit with a removed file"""
344
337
wt = self.make_branch_and_tree('.')
346
file('hello', 'w').write('hello world')
339
with file('hello', 'w') as f: f.write('hello world')
347
340
wt.add(['hello'], ['hello-id'])
348
341
wt.commit(message='add hello')
349
342
wt.remove('hello')
360
353
for i in range(4):
361
file('hello', 'w').write((str(i) * 4) + '\n')
354
with file('hello', 'w') as f: f.write((str(i) * 4) + '\n')
363
356
wt.add(['hello'], ['hello-id'])
364
357
rev_id = 'test@rev-%d' % (i+1)
365
358
rev_ids.append(rev_id)
366
359
wt.commit(message='rev %d' % (i+1),
368
eq = self.assertEquals
369
eq(b.revision_history(), rev_ids)
370
361
for i in range(4):
371
362
self.assertThat(rev_ids[:i+1],
372
363
MatchesAncestry(b.repository, rev_ids[i]))
389
380
from bzrlib.errors import StrictCommitFailed
390
381
wt = self.make_branch_and_tree('.')
392
file('hello', 'w').write('hello world')
383
with file('hello', 'w') as f: f.write('hello world')
394
file('goodbye', 'w').write('goodbye cruel world!')
385
with file('goodbye', 'w') as f: f.write('goodbye cruel world!')
395
386
self.assertRaises(StrictCommitFailed, wt.commit,
396
387
message='add hello but not goodbye', strict=True)
401
392
wt = self.make_branch_and_tree('.')
403
file('hello', 'w').write('hello world')
394
with file('hello', 'w') as f: f.write('hello world')
405
396
wt.commit(message='add hello', strict=True)
408
399
"""Try and commit with unknown files and strict = False, should work."""
409
400
wt = self.make_branch_and_tree('.')
411
file('hello', 'w').write('hello world')
402
with file('hello', 'w') as f: f.write('hello world')
413
file('goodbye', 'w').write('goodbye cruel world!')
404
with file('goodbye', 'w') as f: f.write('goodbye cruel world!')
414
405
wt.commit(message='add hello but not goodbye', strict=False)
416
407
def test_nonstrict_commit_without_unknowns(self):
419
410
wt = self.make_branch_and_tree('.')
421
file('hello', 'w').write('hello world')
412
with file('hello', 'w') as f: f.write('hello world')
423
414
wt.commit(message='add hello', strict=False)
434
425
from bzrlib.testament import Testament
435
426
# monkey patch gpg signing mechanism
436
427
bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
437
commit.Commit(config=MustSignConfig(branch)).commit(message="base",
438
allow_pointless=True,
428
conf = config.MemoryStack('''
429
gpg_signing_command=cat -
430
create_signatures=always
432
commit.Commit(config_stack=conf).commit(
433
message="base", allow_pointless=True, rev_id='B',
442
436
return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
443
437
self.assertEqual(sign(Testament.from_revision(branch.repository,
444
'B').as_short_text()),
438
'B').as_short_text()),
445
439
branch.repository.get_signature_text('B'))
447
441
bzrlib.gpg.GPGStrategy = oldstrategy
458
452
# monkey patch gpg signing mechanism
459
453
bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
460
config = MustSignConfig(branch)
454
conf = config.MemoryStack('''
455
gpg_signing_command=cat -
456
create_signatures=always
461
458
self.assertRaises(SigningFailed,
462
commit.Commit(config=config).commit,
459
commit.Commit(config_stack=conf).commit,
464
461
allow_pointless=True,
467
464
branch = Branch.open(self.get_url('.'))
468
self.assertEqual(branch.revision_history(), ['A'])
465
self.assertEqual(branch.last_revision(), 'A')
469
466
self.assertFalse(branch.repository.has_revision('B'))
471
468
bzrlib.gpg.GPGStrategy = oldstrategy
479
476
calls.append('called')
480
477
bzrlib.ahook = called
482
config = BranchWithHooks(branch)
483
commit.Commit(config=config).commit(
485
allow_pointless=True,
486
rev_id='A', working_tree = wt)
479
conf = config.MemoryStack('post_commit=bzrlib.ahook bzrlib.ahook')
480
commit.Commit(config_stack=conf).commit(
481
message = "base", allow_pointless=True, rev_id='A',
487
483
self.assertEqual(['called', 'called'], calls)
493
489
wt = self.make_branch_and_tree('.')
495
491
c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
496
self.assertEquals(wt.branch.revno(), 1)
492
self.assertEqual(wt.branch.revno(), 1)
497
493
self.assertEqual({},
498
494
wt.branch.repository.get_revision(
499
495
wt.branch.last_revision()).properties)
839
835
def test_commit_with_checkout_and_branch_sharing_repo(self):
840
836
repo = self.make_repository('repo', shared=True)
841
837
# make_branch_and_tree ignores shared repos
842
branch = bzrdir.BzrDir.create_branch_convenience('repo/branch')
838
branch = controldir.ControlDir.create_branch_convenience('repo/branch')
843
839
tree2 = branch.create_checkout('repo/tree2')
844
840
tree2.commit('message', rev_id='rev1')
845
841
self.assertTrue(tree2.branch.repository.has_revision('rev1'))