269
298
wt = self.make_branch_and_tree('source')
270
299
self.assertEqual([], wt.get_parent_ids())
271
300
wt.commit('A', allow_pointless=True, rev_id='A')
272
self.assertEqual(['A'], wt.get_parent_ids())
301
parent_ids = wt.get_parent_ids()
302
self.assertEqual(['A'], parent_ids)
303
for parent_id in parent_ids:
304
self.assertIsInstance(parent_id, str)
274
306
def test_set_last_revision(self):
275
307
wt = self.make_branch_and_tree('source')
276
308
# set last-revision to one not in the history
277
309
wt.set_last_revision('A')
278
310
# set it back to None for an empty tree.
279
wt.set_last_revision(None)
311
wt.set_last_revision('null:')
280
312
wt.commit('A', allow_pointless=True, rev_id='A')
281
313
self.assertEqual(['A'], wt.get_parent_ids())
282
314
# None is aways in the branch
283
wt.set_last_revision(None)
315
wt.set_last_revision('null:')
284
316
self.assertEqual([], wt.get_parent_ids())
285
317
# and now we can set it to 'A'
286
318
# because some formats mutate the branch to set it on the tree
287
319
# we need to alter the branch to let this pass.
288
wt.branch.set_revision_history(['A', 'B'])
321
wt.branch.set_revision_history(['A', 'B'])
322
except errors.NoSuchRevision, e:
323
self.assertEqual('B', e.revision)
324
raise TestSkipped("Branch format does not permit arbitrary"
289
326
wt.set_last_revision('A')
290
327
self.assertEqual(['A'], wt.get_parent_ids())
328
self.assertRaises(errors.ReservedId, wt.set_last_revision, 'A:')
292
330
def test_set_last_revision_different_to_branch(self):
293
331
# working tree formats from the meta-dir format and newer support
659
745
tree.add, [u'a\u030a'])
661
747
osutils.normalized_filename = orig
749
def test__write_inventory(self):
750
# The private interface _write_inventory is currently used by transform.
751
tree = self.make_branch_and_tree('.')
752
# if we write write an inventory then do a walkdirs we should get back
753
# missing entries, and actual, and unknowns as appropriate.
754
self.build_tree(['present', 'unknown'])
755
inventory = Inventory(tree.get_root_id())
756
inventory.add_path('missing', 'file', 'missing-id')
757
inventory.add_path('present', 'file', 'present-id')
758
# there is no point in being able to write an inventory to an unlocked
759
# tree object - its a low level api not a convenience api.
761
tree._write_inventory(inventory)
765
present_stat = os.lstat('present')
766
unknown_stat = os.lstat('unknown')
768
(('', tree.get_root_id()),
769
[('missing', 'missing', 'unknown', None, 'missing-id', 'file'),
770
('present', 'present', 'file', present_stat, 'present-id', 'file'),
771
('unknown', 'unknown', 'file', unknown_stat, None, None),
774
self.assertEqual(expected_results, list(tree.walkdirs()))
778
def test_path2id(self):
779
# smoke test for path2id
780
tree = self.make_branch_and_tree('.')
781
self.build_tree(['foo'])
782
tree.add(['foo'], ['foo-id'])
783
self.assertEqual('foo-id', tree.path2id('foo'))
784
# the next assertion is for backwards compatability with WorkingTree3,
785
# though its probably a bad idea, it makes things work. Perhaps
786
# it should raise a deprecation warning?
787
self.assertEqual('foo-id', tree.path2id('foo/'))
789
def test_filter_unversioned_files(self):
790
# smoke test for filter_unversioned_files
791
tree = self.make_branch_and_tree('.')
792
paths = ['here-and-versioned', 'here-and-not-versioned',
793
'not-here-and-versioned', 'not-here-and-not-versioned']
794
tree.add(['here-and-versioned', 'not-here-and-versioned'],
795
kinds=['file', 'file'])
796
self.build_tree(['here-and-versioned', 'here-and-not-versioned'])
798
self.addCleanup(tree.unlock)
800
set(['not-here-and-not-versioned', 'here-and-not-versioned']),
801
tree.filter_unversioned_files(paths))
803
def test_detect_real_kind(self):
804
# working trees report the real kind of the file on disk, not the kind
805
# they had when they were first added
806
# create one file of every interesting type
807
tree = self.make_branch_and_tree('.')
808
self.build_tree(['file', 'directory/'])
809
names = ['file', 'directory']
811
os.symlink('target', 'symlink')
812
names.append('symlink')
813
tree.add(names, [n + '-id' for n in names])
814
if tree.supports_tree_reference():
815
sub_tree = self.make_branch_and_tree('tree-reference')
816
sub_tree.set_root_id('tree-reference-id')
817
sub_tree.commit('message')
818
names.append('tree-reference')
819
tree.add_reference(sub_tree)
820
# now when we first look, we should see everything with the same kind
821
# with which they were initially added
823
actual_kind = tree.kind(n + '-id')
824
self.assertEqual(n, actual_kind)
825
# move them around so the names no longer correspond to the types
826
os.rename(names[0], 'tmp')
827
for i in range(1, len(names)):
828
os.rename(names[i], names[i-1])
829
os.rename('tmp', names[-1])
830
# now look and expect to see the correct types again
831
for i in range(len(names)):
832
actual_kind = tree.kind(names[i-1] + '-id')
833
expected_kind = names[i]
834
self.assertEqual(expected_kind, actual_kind)
836
def test_stored_kind_with_missing(self):
837
tree = self.make_branch_and_tree('tree')
839
self.addCleanup(tree.unlock)
840
self.build_tree(['tree/a', 'tree/b/'])
841
tree.add(['a', 'b'], ['a-id', 'b-id'])
844
self.assertEqual('file', tree.stored_kind('a-id'))
845
self.assertEqual('directory', tree.stored_kind('b-id'))
847
def test_missing_file_sha1(self):
848
"""If a file is missing, its sha1 should be reported as None."""
849
tree = self.make_branch_and_tree('.')
851
self.addCleanup(tree.unlock)
852
self.build_tree(['file'])
853
tree.add('file', 'file-id')
854
tree.commit('file added')
856
self.assertIs(None, tree.get_file_sha1('file-id'))
858
def test_no_file_sha1(self):
859
"""If a file is not present, get_file_sha1 should raise NoSuchId"""
860
tree = self.make_branch_and_tree('.')
862
self.addCleanup(tree.unlock)
863
self.assertRaises(errors.NoSuchId, tree.get_file_sha1, 'file-id')
864
self.build_tree(['file'])
865
tree.add('file', 'file-id')
868
self.assertRaises(errors.NoSuchId, tree.get_file_sha1, 'file-id')
870
def test_case_sensitive(self):
871
"""If filesystem is case-sensitive, tree should report this.
873
We check case-sensitivity by creating a file with a lowercase name,
874
then testing whether it exists with an uppercase name.
876
self.build_tree(['filename'])
877
if os.path.exists('FILENAME'):
878
case_sensitive = False
880
case_sensitive = True
881
tree = self.make_branch_and_tree('test')
882
if tree.__class__ == WorkingTree2:
883
raise TestSkipped('WorkingTree2 is not supported')
884
self.assertEqual(case_sensitive, tree.case_sensitive)
886
def test_all_file_ids_with_missing(self):
887
tree = self.make_branch_and_tree('tree')
889
self.addCleanup(tree.unlock)
890
self.build_tree(['tree/a', 'tree/b'])
891
tree.add(['a', 'b'], ['a-id', 'b-id'])
893
self.assertEqual(set(['a-id', 'b-id', tree.get_root_id()]),
896
def test_sprout_hardlink(self):
897
source = self.make_branch_and_tree('source')
898
self.build_tree(['source/file'])
900
source.commit('added file')
901
def fake_link(source, target):
902
raise OSError(errno.EPERM, 'Operation not permitted')
903
real_os_link = os.link
906
# Hard-link support is optional, so supplying hardlink=True may
907
# or may not raise an exception. But if it does, it must be
908
# HardLinkNotSupported
910
source.bzrdir.sprout('target', accelerator_tree=source,
912
except errors.HardLinkNotSupported:
915
os.link = real_os_link
918
class TestIllegalPaths(TestCaseWithWorkingTree):
920
def test_bad_fs_path(self):
921
self.requireFeature(tests.UTF8Filesystem)
922
# We require a UTF8 filesystem, because otherwise we would need to get
923
# tricky to figure out how to create an illegal filename.
924
# \xb5 is an illegal path because it should be \xc2\xb5 for UTF-8
925
tree = self.make_branch_and_tree('tree')
926
self.build_tree(['tree/subdir/'])
929
f = open('tree/subdir/m\xb5', 'wb')
936
self.addCleanup(tree.unlock)
937
basis = tree.basis_tree()
939
self.addCleanup(basis.unlock)
941
e = self.assertListRaises(errors.BadFilenameEncoding,
942
tree.iter_changes, tree.basis_tree(),
943
want_unversioned=True)
944
# We should display the relative path
945
self.assertEqual('subdir/m\xb5', e.filename)
946
self.assertEqual(osutils._fs_enc, e.fs_encoding)