21
21
from bzrlib import (
28
26
from bzrlib.branch import Branch
29
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
27
from bzrlib.bzrdir import BzrDirMetaFormat1
30
28
from bzrlib.commit import Commit, NullCommitReporter
31
from bzrlib.config import BranchConfig
32
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
34
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
35
from bzrlib.workingtree import WorkingTree
29
from bzrlib.errors import (
35
from bzrlib.tests import (
36
TestCaseWithTransport,
39
from bzrlib.tests.features import (
42
from bzrlib.tests.matchers import MatchesAncestry
38
45
# TODO: Test commit with some added, and added-but-missing files
40
class MustSignConfig(BranchConfig):
42
def signature_needed(self):
45
def gpg_signing_command(self):
49
class BranchWithHooks(BranchConfig):
51
def post_commit(self):
52
return "bzrlib.ahook bzrlib.ahook"
47
class MustSignConfig(config.Stack):
49
def __init__(self, branch):
50
store = config.IniFileStore()
51
store._load_from_string('''
52
gpg_signing_command=cat -
53
create_signatures=always
55
super(MustSignConfig, self).__init__([store.get_sections])
56
# FIXME: Strictly speaking we should fallback to the no-name section in
57
# branch.conf but no tests need that so far -- vila 2011-12-14
60
class BranchWithHooks(config.Stack):
62
def __init__(self, branch):
63
store = config.IniFileStore()
64
store._load_from_string('post_commit=bzrlib.ahook bzrlib.ahook')
65
super(BranchWithHooks, self).__init__([store.get_sections])
66
# FIXME: Strictly speaking we should fallback to the no-name section in
67
# branch.conf but no tests need that so far -- vila 2011-12-14
55
70
class CapturingReporter(NullCommitReporter):
84
99
file('hello', 'w').write('hello world')
86
wt.commit(message='add hello')
101
rev1 = wt.commit(message='add hello')
87
102
file_id = wt.path2id('hello')
89
104
file('hello', 'w').write('version 2')
90
wt.commit(message='commit 2')
105
rev2 = wt.commit(message='commit 2')
92
107
eq = self.assertEquals
94
rh = b.revision_history()
95
rev = b.repository.get_revision(rh[0])
109
rev = b.repository.get_revision(rev1)
96
110
eq(rev.message, 'add hello')
98
tree1 = b.repository.revision_tree(rh[0])
112
tree1 = b.repository.revision_tree(rev1)
100
114
text = tree1.get_file_text(file_id)
102
116
self.assertEqual('hello world', text)
104
tree2 = b.repository.revision_tree(rh[1])
118
tree2 = b.repository.revision_tree(rev2)
105
119
tree2.lock_read()
106
120
text = tree2.get_file_text(file_id)
108
122
self.assertEqual('version 2', text)
124
def test_commit_lossy_native(self):
125
"""Attempt a lossy commit to a native branch."""
126
wt = self.make_branch_and_tree('.')
128
file('hello', 'w').write('hello world')
130
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
131
self.assertEquals('revid', revid)
133
def test_commit_lossy_foreign(self):
134
"""Attempt a lossy commit to a foreign branch."""
135
test_foreign.register_dummy_foreign_for_test(self)
136
wt = self.make_branch_and_tree('.',
137
format=test_foreign.DummyForeignVcsDirFormat())
139
file('hello', 'w').write('hello world')
141
revid = wt.commit(message='add hello', lossy=True,
142
timestamp=1302659388, timezone=0)
143
self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
145
def test_commit_bound_lossy_foreign(self):
146
"""Attempt a lossy commit to a bzr branch bound to a foreign branch."""
147
test_foreign.register_dummy_foreign_for_test(self)
148
foreign_branch = self.make_branch('foreign',
149
format=test_foreign.DummyForeignVcsDirFormat())
150
wt = foreign_branch.create_checkout("local")
152
file('local/hello', 'w').write('hello world')
154
revid = wt.commit(message='add hello', lossy=True,
155
timestamp=1302659388, timezone=0)
156
self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
157
self.assertEquals('dummy-v1:1302659388.0-0-0',
158
foreign_branch.last_revision())
159
self.assertEquals('dummy-v1:1302659388.0-0-0',
160
wt.branch.last_revision())
110
162
def test_missing_commit(self):
111
163
"""Test a commit with a missing file"""
112
164
wt = self.make_branch_and_tree('.')
116
168
wt.commit(message='add hello')
118
170
os.remove('hello')
119
wt.commit('removed hello', rev_id='rev2')
171
reporter = CapturingReporter()
172
wt.commit('removed hello', rev_id='rev2', reporter=reporter)
174
[('missing', u'hello'), ('deleted', u'hello')],
121
177
tree = b.repository.revision_tree('rev2')
122
178
self.assertFalse(tree.has_id('hello-id'))
224
280
eq(tree1.id2path('hello-id'), 'hello')
225
281
eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
226
282
self.assertFalse(tree1.has_filename('fruity'))
227
self.check_inventory_shape(tree1.inventory, ['hello'])
228
ie = tree1.inventory['hello-id']
229
eq(ie.revision, 'test@rev-1')
283
self.check_tree_shape(tree1, ['hello'])
284
eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
231
286
tree2 = b.repository.revision_tree('test@rev-2')
232
287
tree2.lock_read()
233
288
self.addCleanup(tree2.unlock)
234
289
eq(tree2.id2path('hello-id'), 'fruity')
235
290
eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
236
self.check_inventory_shape(tree2.inventory, ['fruity'])
237
ie = tree2.inventory['hello-id']
238
eq(ie.revision, 'test@rev-2')
291
self.check_tree_shape(tree2, ['fruity'])
292
eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
240
294
def test_reused_rev_id(self):
241
295
"""Test that a revision id cannot be reused in a branch"""
272
325
wt.commit('three', rev_id=r3, allow_pointless=False)
275
self.check_inventory_shape(wt.read_working_inventory(),
328
self.check_tree_shape(wt,
276
329
['a/', 'a/hello', 'a/b/'])
277
self.check_inventory_shape(b.repository.get_inventory(r3),
330
self.check_tree_shape(b.repository.revision_tree(r3),
278
331
['a/', 'a/hello', 'a/b/'])
320
372
rev_ids.append(rev_id)
321
373
wt.commit(message='rev %d' % (i+1),
323
eq = self.assertEquals
324
eq(b.revision_history(), rev_ids)
325
375
for i in range(4):
326
anc = b.repository.get_ancestry(rev_ids[i])
327
eq(anc, [None] + rev_ids[:i+1])
376
self.assertThat(rev_ids[:i+1],
377
MatchesAncestry(b.repository, rev_ids[i]))
329
379
def test_commit_new_subdir_child_selective(self):
330
380
wt = self.make_branch_and_tree('.')
385
434
wt = self.make_branch_and_tree('.')
386
435
branch = wt.branch
387
436
wt.commit("base", allow_pointless=True, rev_id='A')
388
self.failIf(branch.repository.has_signature_for_revision_id('A'))
437
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
390
439
from bzrlib.testament import Testament
391
440
# monkey patch gpg signing mechanism
392
441
bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
393
commit.Commit(config=MustSignConfig(branch)).commit(message="base",
394
allow_pointless=True,
442
commit.Commit(config_stack=MustSignConfig(branch)
443
).commit(message="base", allow_pointless=True,
444
rev_id='B', working_tree=wt)
398
446
return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
399
447
self.assertEqual(sign(Testament.from_revision(branch.repository,
400
'B').as_short_text()),
448
'B').as_short_text()),
401
449
branch.repository.get_signature_text('B'))
403
451
bzrlib.gpg.GPGStrategy = oldstrategy
409
457
wt = self.make_branch_and_tree('.')
410
458
branch = wt.branch
411
459
wt.commit("base", allow_pointless=True, rev_id='A')
412
self.failIf(branch.repository.has_signature_for_revision_id('A'))
460
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
414
from bzrlib.testament import Testament
415
462
# monkey patch gpg signing mechanism
416
463
bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
417
464
config = MustSignConfig(branch)
418
465
self.assertRaises(SigningFailed,
419
commit.Commit(config=config).commit,
466
commit.Commit(config_stack=config).commit,
421
468
allow_pointless=True,
424
471
branch = Branch.open(self.get_url('.'))
425
self.assertEqual(branch.revision_history(), ['A'])
426
self.failIf(branch.repository.has_revision('B'))
472
self.assertEqual(branch.last_revision(), 'A')
473
self.assertFalse(branch.repository.has_revision('B'))
428
475
bzrlib.gpg.GPGStrategy = oldstrategy