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.MemoryStack):
50
super(MustSignConfig, self).__init__('''
51
gpg_signing_command=cat -
52
create_signatures=always
55
56
class CapturingReporter(NullCommitReporter):
81
82
"""Commit and check two versions of a single file."""
82
83
wt = self.make_branch_and_tree('.')
84
file('hello', 'w').write('hello world')
85
with file('hello', 'w') as f: f.write('hello world')
86
wt.commit(message='add hello')
87
rev1 = wt.commit(message='add hello')
87
88
file_id = wt.path2id('hello')
89
file('hello', 'w').write('version 2')
90
wt.commit(message='commit 2')
90
with file('hello', 'w') as f: f.write('version 2')
91
rev2 = wt.commit(message='commit 2')
92
93
eq = self.assertEquals
94
rh = b.revision_history()
95
rev = b.repository.get_revision(rh[0])
95
rev = b.repository.get_revision(rev1)
96
96
eq(rev.message, 'add hello')
98
tree1 = b.repository.revision_tree(rh[0])
98
tree1 = b.repository.revision_tree(rev1)
100
100
text = tree1.get_file_text(file_id)
102
102
self.assertEqual('hello world', text)
104
tree2 = b.repository.revision_tree(rh[1])
104
tree2 = b.repository.revision_tree(rev2)
105
105
tree2.lock_read()
106
106
text = tree2.get_file_text(file_id)
108
108
self.assertEqual('version 2', text)
110
def test_commit_lossy_native(self):
111
"""Attempt a lossy commit to a native branch."""
112
wt = self.make_branch_and_tree('.')
114
with file('hello', 'w') as f: f.write('hello world')
116
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
117
self.assertEquals('revid', revid)
119
def test_commit_lossy_foreign(self):
120
"""Attempt a lossy commit to a foreign branch."""
121
test_foreign.register_dummy_foreign_for_test(self)
122
wt = self.make_branch_and_tree('.',
123
format=test_foreign.DummyForeignVcsDirFormat())
125
with file('hello', 'w') as f: f.write('hello world')
127
revid = wt.commit(message='add hello', lossy=True,
128
timestamp=1302659388, timezone=0)
129
self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
131
def test_commit_bound_lossy_foreign(self):
132
"""Attempt a lossy commit to a bzr branch bound to a foreign branch."""
133
test_foreign.register_dummy_foreign_for_test(self)
134
foreign_branch = self.make_branch('foreign',
135
format=test_foreign.DummyForeignVcsDirFormat())
136
wt = foreign_branch.create_checkout("local")
138
with file('local/hello', 'w') as f: f.write('hello world')
140
revid = wt.commit(message='add hello', lossy=True,
141
timestamp=1302659388, timezone=0)
142
self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
143
self.assertEquals('dummy-v1:1302659388.0-0-0',
144
foreign_branch.last_revision())
145
self.assertEquals('dummy-v1:1302659388.0-0-0',
146
wt.branch.last_revision())
110
148
def test_missing_commit(self):
111
149
"""Test a commit with a missing file"""
112
150
wt = self.make_branch_and_tree('.')
114
file('hello', 'w').write('hello world')
152
with file('hello', 'w') as f: f.write('hello world')
115
153
wt.add(['hello'], ['hello-id'])
116
154
wt.commit(message='add hello')
118
156
os.remove('hello')
119
wt.commit('removed hello', rev_id='rev2')
157
reporter = CapturingReporter()
158
wt.commit('removed hello', rev_id='rev2', reporter=reporter)
160
[('missing', u'hello'), ('deleted', u'hello')],
121
163
tree = b.repository.revision_tree('rev2')
122
164
self.assertFalse(tree.has_id('hello-id'))
171
213
"""Selective commit in tree with deletions"""
172
214
wt = self.make_branch_and_tree('.')
174
file('hello', 'w').write('hello')
175
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')
176
218
wt.add(['hello', 'buongia'],
177
219
['hello-id', 'buongia-id'])
178
220
wt.commit(message='add files',
179
221
rev_id='test@rev-1')
181
223
os.remove('hello')
182
file('buongia', 'w').write('new text')
224
with file('buongia', 'w') as f: f.write('new text')
183
225
wt.commit(message='update text',
184
226
specific_files=['buongia'],
185
227
allow_pointless=False,
224
266
eq(tree1.id2path('hello-id'), 'hello')
225
267
eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
226
268
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')
269
self.check_tree_shape(tree1, ['hello'])
270
eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
231
272
tree2 = b.repository.revision_tree('test@rev-2')
232
273
tree2.lock_read()
233
274
self.addCleanup(tree2.unlock)
234
275
eq(tree2.id2path('hello-id'), 'fruity')
235
276
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')
277
self.check_tree_shape(tree2, ['fruity'])
278
eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
240
280
def test_reused_rev_id(self):
241
281
"""Test that a revision id cannot be reused in a branch"""
284
323
wt.commit('four', rev_id=r4, allow_pointless=False)
287
self.check_inventory_shape(wt.read_working_inventory(),
288
['a/', 'a/b/hello', 'a/b/'])
326
self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
292
inv = b.repository.get_revision_inventory(r4)
330
inv = b.repository.get_inventory(r4)
293
331
eq(inv['hello-id'].revision, r4)
294
332
eq(inv['a-id'].revision, r1)
295
333
eq(inv['b-id'].revision, r3)
315
353
for i in range(4):
316
file('hello', 'w').write((str(i) * 4) + '\n')
354
with file('hello', 'w') as f: f.write((str(i) * 4) + '\n')
318
356
wt.add(['hello'], ['hello-id'])
319
357
rev_id = 'test@rev-%d' % (i+1)
320
358
rev_ids.append(rev_id)
321
359
wt.commit(message='rev %d' % (i+1),
323
eq = self.assertEquals
324
eq(b.revision_history(), rev_ids)
325
361
for i in range(4):
326
anc = b.repository.get_ancestry(rev_ids[i])
327
eq(anc, [None] + rev_ids[:i+1])
362
self.assertThat(rev_ids[:i+1],
363
MatchesAncestry(b.repository, rev_ids[i]))
329
365
def test_commit_new_subdir_child_selective(self):
330
366
wt = self.make_branch_and_tree('.')
344
380
from bzrlib.errors import StrictCommitFailed
345
381
wt = self.make_branch_and_tree('.')
347
file('hello', 'w').write('hello world')
383
with file('hello', 'w') as f: f.write('hello world')
349
file('goodbye', 'w').write('goodbye cruel world!')
385
with file('goodbye', 'w') as f: f.write('goodbye cruel world!')
350
386
self.assertRaises(StrictCommitFailed, wt.commit,
351
387
message='add hello but not goodbye', strict=True)
353
389
def test_strict_commit_without_unknowns(self):
354
390
"""Try and commit with no unknown files and strict = True,
356
from bzrlib.errors import StrictCommitFailed
357
392
wt = self.make_branch_and_tree('.')
359
file('hello', 'w').write('hello world')
394
with file('hello', 'w') as f: f.write('hello world')
361
396
wt.commit(message='add hello', strict=True)
385
420
wt = self.make_branch_and_tree('.')
386
421
branch = wt.branch
387
422
wt.commit("base", allow_pointless=True, rev_id='A')
388
self.failIf(branch.repository.has_signature_for_revision_id('A'))
423
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
390
425
from bzrlib.testament import Testament
391
426
# monkey patch gpg signing mechanism
392
427
bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
393
commit.Commit(config=MustSignConfig(branch)).commit(message="base",
394
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',
398
436
return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
399
437
self.assertEqual(sign(Testament.from_revision(branch.repository,
400
'B').as_short_text()),
438
'B').as_short_text()),
401
439
branch.repository.get_signature_text('B'))
403
441
bzrlib.gpg.GPGStrategy = oldstrategy
409
447
wt = self.make_branch_and_tree('.')
410
448
branch = wt.branch
411
449
wt.commit("base", allow_pointless=True, rev_id='A')
412
self.failIf(branch.repository.has_signature_for_revision_id('A'))
450
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
414
from bzrlib.testament import Testament
415
452
# monkey patch gpg signing mechanism
416
453
bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
417
config = MustSignConfig(branch)
454
conf = config.MemoryStack('''
455
gpg_signing_command=cat -
456
create_signatures=always
418
458
self.assertRaises(SigningFailed,
419
commit.Commit(config=config).commit,
459
commit.Commit(config_stack=conf).commit,
421
461
allow_pointless=True,
424
464
branch = Branch.open(self.get_url('.'))
425
self.assertEqual(branch.revision_history(), ['A'])
426
self.failIf(branch.repository.has_revision('B'))
465
self.assertEqual(branch.last_revision(), 'A')
466
self.assertFalse(branch.repository.has_revision('B'))
428
468
bzrlib.gpg.GPGStrategy = oldstrategy