102
107
tree1.lock_read()
103
108
text = tree1.get_file_text('hello')
105
self.assertEqual('hello world', text)
110
self.assertEqual(b'hello world', text)
107
112
tree2 = b.repository.revision_tree(rev2)
108
113
tree2.lock_read()
109
114
text = tree2.get_file_text('hello')
111
self.assertEqual('version 2', text)
116
self.assertEqual(b'version 2', text)
113
118
def test_commit_lossy_native(self):
114
119
"""Attempt a lossy commit to a native branch."""
115
120
wt = self.make_branch_and_tree('.')
117
with open('hello', 'w') as f: f.write('hello world')
122
with open('hello', 'w') as f:
123
f.write('hello world')
119
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
120
self.assertEqual('revid', revid)
125
revid = wt.commit(message='add hello', rev_id=b'revid', lossy=True)
126
self.assertEqual(b'revid', revid)
122
128
def test_commit_lossy_foreign(self):
123
129
"""Attempt a lossy commit to a foreign branch."""
124
130
test_foreign.register_dummy_foreign_for_test(self)
125
131
wt = self.make_branch_and_tree('.',
126
format=test_foreign.DummyForeignVcsDirFormat())
132
format=test_foreign.DummyForeignVcsDirFormat())
128
with open('hello', 'w') as f: f.write('hello world')
134
with open('hello', 'w') as f:
135
f.write('hello world')
130
137
revid = wt.commit(message='add hello', lossy=True,
131
timestamp=1302659388, timezone=0)
132
self.assertEqual('dummy-v1:1302659388.0-0-UNKNOWN', revid)
138
timestamp=1302659388, timezone=0)
139
self.assertEqual(b'dummy-v1:1302659388-0-UNKNOWN', revid)
134
141
def test_commit_bound_lossy_foreign(self):
135
142
"""Attempt a lossy commit to a bzr branch bound to a foreign branch."""
136
143
test_foreign.register_dummy_foreign_for_test(self)
137
144
foreign_branch = self.make_branch('foreign',
138
format=test_foreign.DummyForeignVcsDirFormat())
145
format=test_foreign.DummyForeignVcsDirFormat())
139
146
wt = foreign_branch.create_checkout("local")
141
with open('local/hello', 'w') as f: f.write('hello world')
148
with open('local/hello', 'w') as f:
149
f.write('hello world')
143
151
revid = wt.commit(message='add hello', lossy=True,
144
timestamp=1302659388, timezone=0)
145
self.assertEqual('dummy-v1:1302659388.0-0-0', revid)
146
self.assertEqual('dummy-v1:1302659388.0-0-0',
147
foreign_branch.last_revision())
148
self.assertEqual('dummy-v1:1302659388.0-0-0',
149
wt.branch.last_revision())
152
timestamp=1302659388, timezone=0)
153
self.assertEqual(b'dummy-v1:1302659388-0-0', revid)
154
self.assertEqual(b'dummy-v1:1302659388-0-0',
155
foreign_branch.last_revision())
156
self.assertEqual(b'dummy-v1:1302659388-0-0',
157
wt.branch.last_revision())
151
159
def test_missing_commit(self):
152
160
"""Test a commit with a missing file"""
153
161
wt = self.make_branch_and_tree('.')
155
with open('hello', 'w') as f: f.write('hello world')
156
wt.add(['hello'], ['hello-id'])
163
with open('hello', 'w') as f:
164
f.write('hello world')
165
wt.add(['hello'], [b'hello-id'])
157
166
wt.commit(message='add hello')
159
168
os.remove('hello')
160
169
reporter = CapturingReporter()
161
wt.commit('removed hello', rev_id='rev2', reporter=reporter)
170
wt.commit('removed hello', rev_id=b'rev2', reporter=reporter)
162
171
self.assertEqual(
163
172
[('missing', u'hello'), ('deleted', u'hello')],
166
tree = b.repository.revision_tree('rev2')
167
self.assertFalse(tree.has_id('hello-id'))
175
tree = b.repository.revision_tree(b'rev2')
176
self.assertFalse(tree.has_filename('hello'))
169
178
def test_partial_commit_move(self):
170
179
"""Test a partial commit where a file was renamed but not committed.
180
189
self.build_tree(['annotate/', 'annotate/foo.py',
181
190
'olive/', 'olive/dialog.py'
183
192
wt.add(['annotate', 'olive', 'annotate/foo.py', 'olive/dialog.py'])
184
193
wt.commit(message='add files')
185
194
wt.rename_one("olive/dialog.py", "aaa")
186
self.build_tree_contents([('annotate/foo.py', 'modified\n')])
195
self.build_tree_contents([('annotate/foo.py', b'modified\n')])
187
196
wt.commit('renamed hello', specific_files=["annotate"])
189
198
def test_pointless_commit(self):
190
199
"""Commit refuses unless there are changes or it's forced."""
191
200
wt = self.make_branch_and_tree('.')
193
with open('hello', 'w') as f: f.write('hello')
202
with open('hello', 'w') as f:
194
204
wt.add(['hello'])
195
205
wt.commit(message='add hello')
196
206
self.assertEqual(b.revno(), 1)
216
226
"""Selective commit in tree with deletions"""
217
227
wt = self.make_branch_and_tree('.')
219
with open('hello', 'w') as f: f.write('hello')
220
with open('buongia', 'w') as f: f.write('buongia')
229
with open('hello', 'w') as f:
231
with open('buongia', 'w') as f:
221
233
wt.add(['hello', 'buongia'],
222
['hello-id', 'buongia-id'])
234
[b'hello-id', b'buongia-id'])
223
235
wt.commit(message='add files',
236
rev_id=b'test@rev-1')
226
238
os.remove('hello')
227
with open('buongia', 'w') as f: f.write('new text')
239
with open('buongia', 'w') as f:
228
241
wt.commit(message='update text',
229
specific_files=['buongia'],
230
allow_pointless=False,
242
specific_files=['buongia'],
243
allow_pointless=False,
244
rev_id=b'test@rev-2')
233
246
wt.commit(message='remove hello',
234
specific_files=['hello'],
235
allow_pointless=False,
247
specific_files=['hello'],
248
allow_pointless=False,
249
rev_id=b'test@rev-3')
238
251
eq = self.assertEqual
241
tree2 = b.repository.revision_tree('test@rev-2')
254
tree2 = b.repository.revision_tree(b'test@rev-2')
242
255
tree2.lock_read()
243
256
self.addCleanup(tree2.unlock)
244
257
self.assertTrue(tree2.has_filename('hello'))
245
self.assertEqual(tree2.get_file_text('hello'), 'hello')
246
self.assertEqual(tree2.get_file_text('buongia'), 'new text')
258
self.assertEqual(tree2.get_file_text('hello'), b'hello')
259
self.assertEqual(tree2.get_file_text('buongia'), b'new text')
248
tree3 = b.repository.revision_tree('test@rev-3')
261
tree3 = b.repository.revision_tree(b'test@rev-3')
249
262
tree3.lock_read()
250
263
self.addCleanup(tree3.unlock)
251
264
self.assertFalse(tree3.has_filename('hello'))
252
self.assertEqual(tree3.get_file_text('buongia'), 'new text')
265
self.assertEqual(tree3.get_file_text('buongia'), b'new text')
254
267
def test_commit_rename(self):
255
268
"""Test commit of a revision where a file is renamed."""
256
269
tree = self.make_branch_and_tree('.')
258
271
self.build_tree(['hello'], line_endings='binary')
259
tree.add(['hello'], ['hello-id'])
260
tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
272
tree.add(['hello'], [b'hello-id'])
273
tree.commit(message='one', rev_id=b'test@rev-1', allow_pointless=False)
262
275
tree.rename_one('hello', 'fruity')
263
tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
276
tree.commit(message='renamed', rev_id=b'test@rev-2',
277
allow_pointless=False)
265
279
eq = self.assertEqual
266
tree1 = b.repository.revision_tree('test@rev-1')
280
tree1 = b.repository.revision_tree(b'test@rev-1')
267
281
tree1.lock_read()
268
282
self.addCleanup(tree1.unlock)
269
eq(tree1.id2path('hello-id'), 'hello')
270
eq(tree1.get_file_text('hello'), 'contents of hello\n')
283
eq(tree1.id2path(b'hello-id'), 'hello')
284
eq(tree1.get_file_text('hello'), b'contents of hello\n')
271
285
self.assertFalse(tree1.has_filename('fruity'))
272
286
self.check_tree_shape(tree1, ['hello'])
273
eq(tree1.get_file_revision('hello'), 'test@rev-1')
287
eq(tree1.get_file_revision('hello'), b'test@rev-1')
275
tree2 = b.repository.revision_tree('test@rev-2')
289
tree2 = b.repository.revision_tree(b'test@rev-2')
276
290
tree2.lock_read()
277
291
self.addCleanup(tree2.unlock)
278
eq(tree2.id2path('hello-id'), 'fruity')
279
eq(tree2.get_file_text('fruity'), 'contents of hello\n')
292
eq(tree2.id2path(b'hello-id'), 'fruity')
293
eq(tree2.get_file_text('fruity'), b'contents of hello\n')
280
294
self.check_tree_shape(tree2, ['fruity'])
281
eq(tree2.get_file_revision('fruity'), 'test@rev-2')
295
eq(tree2.get_file_revision('fruity'), b'test@rev-2')
283
297
def test_reused_rev_id(self):
284
298
"""Test that a revision id cannot be reused in a branch"""
285
299
wt = self.make_branch_and_tree('.')
287
wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
301
wt.commit('initial', rev_id=b'test@rev-1', allow_pointless=True)
288
302
self.assertRaises(Exception,
290
304
message='reused id',
305
rev_id=b'test@rev-1',
292
306
allow_pointless=True)
294
308
def test_commit_move(self):
333
347
inv = b.repository.get_inventory(r4)
334
eq(inv['hello-id'].revision, r4)
335
eq(inv['a-id'].revision, r1)
336
eq(inv['b-id'].revision, r3)
348
eq(inv.get_entry(b'hello-id').revision, r4)
349
eq(inv.get_entry(b'a-id').revision, r1)
350
eq(inv.get_entry(b'b-id').revision, r3)
338
352
def test_removed_commit(self):
339
353
"""Commit with a removed file"""
340
354
wt = self.make_branch_and_tree('.')
342
with open('hello', 'w') as f: f.write('hello world')
343
wt.add(['hello'], ['hello-id'])
356
with open('hello', 'w') as f:
357
f.write('hello world')
358
wt.add(['hello'], [b'hello-id'])
344
359
wt.commit(message='add hello')
345
360
wt.remove('hello')
346
wt.commit('removed hello', rev_id='rev2')
361
wt.commit('removed hello', rev_id=b'rev2')
348
tree = b.repository.revision_tree('rev2')
349
self.assertFalse(tree.has_id('hello-id'))
363
tree = b.repository.revision_tree(b'rev2')
364
self.assertFalse(tree.has_filename('hello'))
351
366
def test_committed_ancestry(self):
352
367
"""Test commit appends revisions to ancestry."""
356
371
for i in range(4):
357
with open('hello', 'w') as f: f.write((str(i) * 4) + '\n')
372
with open('hello', 'w') as f:
373
f.write((str(i) * 4) + '\n')
359
wt.add(['hello'], ['hello-id'])
360
rev_id = 'test@rev-%d' % (i+1)
375
wt.add(['hello'], [b'hello-id'])
376
rev_id = b'test@rev-%d' % (i + 1)
361
377
rev_ids.append(rev_id)
362
wt.commit(message='rev %d' % (i+1),
378
wt.commit(message='rev %d' % (i + 1),
364
380
for i in range(4):
365
self.assertThat(rev_ids[:i+1],
366
MatchesAncestry(b.repository, rev_ids[i]))
381
self.assertThat(rev_ids[:i + 1],
382
MatchesAncestry(b.repository, rev_ids[i]))
368
384
def test_commit_new_subdir_child_selective(self):
369
385
wt = self.make_branch_and_tree('.')
371
387
self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
372
388
wt.add(['dir', 'dir/file1', 'dir/file2'],
373
['dirid', 'file1id', 'file2id'])
374
wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
375
inv = b.repository.get_inventory('1')
376
self.assertEqual('1', inv['dirid'].revision)
377
self.assertEqual('1', inv['file1id'].revision)
389
[b'dirid', b'file1id', b'file2id'])
390
wt.commit('dir/file1', specific_files=['dir/file1'], rev_id=b'1')
391
inv = b.repository.get_inventory(b'1')
392
self.assertEqual(b'1', inv.get_entry(b'dirid').revision)
393
self.assertEqual(b'1', inv.get_entry(b'file1id').revision)
378
394
# FIXME: This should raise a KeyError I think, rbc20051006
379
self.assertRaises(BzrError, inv.__getitem__, 'file2id')
395
self.assertRaises(BzrError, inv.get_entry, b'file2id')
381
397
def test_strict_commit(self):
382
398
"""Try and commit with unknown files and strict = True, should fail."""
383
399
from ..errors import StrictCommitFailed
384
400
wt = self.make_branch_and_tree('.')
386
with open('hello', 'w') as f: f.write('hello world')
402
with open('hello', 'w') as f:
403
f.write('hello world')
388
with open('goodbye', 'w') as f: f.write('goodbye cruel world!')
405
with open('goodbye', 'w') as f:
406
f.write('goodbye cruel world!')
389
407
self.assertRaises(StrictCommitFailed, wt.commit,
390
message='add hello but not goodbye', strict=True)
408
message='add hello but not goodbye', strict=True)
392
410
def test_strict_commit_without_unknowns(self):
393
411
"""Try and commit with no unknown files and strict = True,
395
413
wt = self.make_branch_and_tree('.')
397
with open('hello', 'w') as f: f.write('hello world')
415
with open('hello', 'w') as f:
416
f.write('hello world')
399
418
wt.commit(message='add hello', strict=True)
422
444
oldstrategy = breezy.gpg.GPGStrategy
423
445
wt = self.make_branch_and_tree('.')
424
446
branch = wt.branch
425
wt.commit("base", allow_pointless=True, rev_id='A')
426
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
447
wt.commit("base", allow_pointless=True, rev_id=b'A')
448
self.assertFalse(branch.repository.has_signature_for_revision_id(b'A'))
428
from ..testament import Testament
450
from ..bzr.testament import Testament
429
451
# monkey patch gpg signing mechanism
430
452
breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
431
conf = config.MemoryStack('''
453
conf = config.MemoryStack(b'''
432
454
create_signatures=always
434
456
commit.Commit(config_stack=conf).commit(
435
message="base", allow_pointless=True, rev_id='B',
457
message="base", allow_pointless=True, rev_id=b'B',
438
return breezy.gpg.LoopbackGPGStrategy(None).sign(text)
461
return breezy.gpg.LoopbackGPGStrategy(None).sign(
462
text, breezy.gpg.MODE_CLEAR)
439
463
self.assertEqual(sign(Testament.from_revision(branch.repository,
440
'B').as_short_text()),
441
branch.repository.get_signature_text('B'))
464
b'B').as_short_text()),
465
branch.repository.get_signature_text(b'B'))
443
467
breezy.gpg.GPGStrategy = oldstrategy
448
472
oldstrategy = breezy.gpg.GPGStrategy
449
473
wt = self.make_branch_and_tree('.')
450
474
branch = wt.branch
451
wt.commit("base", allow_pointless=True, rev_id='A')
452
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
475
wt.commit("base", allow_pointless=True, rev_id=b'A')
476
self.assertFalse(branch.repository.has_signature_for_revision_id(b'A'))
454
478
# monkey patch gpg signing mechanism
455
479
breezy.gpg.GPGStrategy = breezy.gpg.DisabledGPGStrategy
456
conf = config.MemoryStack('''
480
conf = config.MemoryStack(b'''
457
481
create_signatures=always
459
483
self.assertRaises(breezy.gpg.SigningFailed,
460
484
commit.Commit(config_stack=conf).commit,
462
486
allow_pointless=True,
465
489
branch = Branch.open(self.get_url('.'))
466
self.assertEqual(branch.last_revision(), 'A')
467
self.assertFalse(branch.repository.has_revision('B'))
490
self.assertEqual(branch.last_revision(), b'A')
491
self.assertFalse(branch.repository.has_revision(b'B'))
469
493
breezy.gpg.GPGStrategy = oldstrategy
682
def test_unsupported_symlink_commit(self):
683
self.requireFeature(SymlinkFeature)
684
tree = self.make_branch_and_tree('.')
685
self.build_tree(['hello'])
687
tree.commit('added hello', rev_id=b'hello_id')
688
os.symlink('hello', 'foo')
690
tree.commit('added foo', rev_id=b'foo_id')
692
trace.push_log_file(log)
693
os_symlink = getattr(os, 'symlink', None)
696
# At this point as bzr thinks symlinks are not supported
697
# we should get a warning about symlink foo and bzr should
698
# not think its removed.
700
self.build_tree(['world'])
702
tree.commit('added world', rev_id=b'world_id')
705
os.symlink = os_symlink
706
self.assertContainsRe(
708
b'Ignoring "foo" as symlinks are not '
709
b'supported on this filesystem\\.')
653
711
def test_commit_kind_changes(self):
654
712
self.requireFeature(SymlinkFeature)
655
713
tree = self.make_branch_and_tree('.')
656
714
os.symlink('target', 'name')
657
tree.add('name', 'a-file-id')
715
tree.add('name', b'a-file-id')
658
716
tree.commit('Added a symlink')
659
717
self.assertBasisTreeKind('symlink', tree, 'name')
811
870
def test_multiple_authors(self):
812
871
tree = self.make_branch_and_tree('foo')
813
872
rev_id = tree.commit('commit 1',
814
authors=['John Doe <jdoe@example.com>',
815
'Jane Rey <jrey@example.com>'])
873
authors=['John Doe <jdoe@example.com>',
874
'Jane Rey <jrey@example.com>'])
816
875
rev = tree.branch.repository.get_revision(rev_id)
817
876
self.assertEqual('John Doe <jdoe@example.com>\n'
818
'Jane Rey <jrey@example.com>', rev.properties['authors'])
877
'Jane Rey <jrey@example.com>', rev.properties['authors'])
819
878
self.assertFalse('author' in rev.properties)
821
880
def test_author_with_newline_rejected(self):
822
881
tree = self.make_branch_and_tree('foo')
823
882
self.assertRaises(AssertionError, tree.commit, 'commit 1',
824
authors=['John\nDoe <jdoe@example.com>'])
883
authors=['John\nDoe <jdoe@example.com>'])
826
885
def test_commit_with_checkout_and_branch_sharing_repo(self):
827
886
repo = self.make_repository('repo', shared=True)
828
887
# make_branch_and_tree ignores shared repos
829
888
branch = controldir.ControlDir.create_branch_convenience('repo/branch')
830
889
tree2 = branch.create_checkout('repo/tree2')
831
tree2.commit('message', rev_id='rev1')
832
self.assertTrue(tree2.branch.repository.has_revision('rev1'))
890
tree2.commit('message', rev_id=b'rev1')
891
self.assertTrue(tree2.branch.repository.has_revision(b'rev1'))
835
894
class FilterExcludedTests(TestCase):
837
896
def test_add_file_not_excluded(self):
839
('fid', (None, 'newpath'),
840
0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
841
('file', 'file'), (True, True))]
842
self.assertEqual(changes, list(filter_excluded(changes, ['otherpath'])))
899
'fid', (None, 'newpath'),
900
0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
901
('file', 'file'), (True, True))]
902
self.assertEqual(changes, list(
903
filter_excluded(changes, ['otherpath'])))
844
905
def test_add_file_excluded(self):
846
('fid', (None, 'newpath'),
847
0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
848
('file', 'file'), (True, True))]
908
'fid', (None, 'newpath'),
909
0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
910
('file', 'file'), (True, True))]
849
911
self.assertEqual([], list(filter_excluded(changes, ['newpath'])))
851
913
def test_delete_file_excluded(self):
853
('fid', ('somepath', None),
854
0, (False, None), ('pid', None), ('newpath', None),
855
('file', None), (True, None))]
916
'fid', ('somepath', None),
917
0, (False, None), ('pid', None), ('newpath', None),
918
('file', None), (True, None))]
856
919
self.assertEqual([], list(filter_excluded(changes, ['somepath'])))
858
921
def test_move_from_or_to_excluded(self):
860
('fid', ('oldpath', 'newpath'),
861
0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
862
('file', 'file'), (True, True))]
924
'fid', ('oldpath', 'newpath'),
925
0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
926
('file', 'file'), (True, True))]
863
927
self.assertEqual([], list(filter_excluded(changes, ['oldpath'])))
864
928
self.assertEqual([], list(filter_excluded(changes, ['newpath'])))