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