61
58
trees or versioned trees.
64
def has_versioned_directories(self):
65
"""Whether this tree can contain explicitly versioned directories.
67
This defaults to True, but some implementations may want to override
72
61
def changes_from(self, other, want_unchanged=False, specific_files=None,
73
62
extra_trees=None, require_versioned=False, include_root=False,
74
63
want_unversioned=False):
289
278
:param file_id: The file_id of the file.
290
279
:param path: The path of the file.
292
280
If both file_id and path are supplied, an implementation may use
295
:returns: A single byte string for the whole file.
297
283
my_file = self.get_file(file_id, path)
312
298
return osutils.split_lines(self.get_file_text(file_id, path))
314
def get_file_verifier(self, file_id, path=None, stat_value=None):
315
"""Return a verifier for a file.
317
The default implementation returns a sha1.
319
:param file_id: The handle for this file.
320
:param path: The path that this file can be found at.
321
These must point to the same object.
322
:param stat_value: Optional stat value for the object
323
:return: Tuple with verifier name and verifier data
325
return ("SHA1", self.get_file_sha1(file_id, path=path,
326
stat_value=stat_value))
328
300
def get_file_sha1(self, file_id, path=None, stat_value=None):
329
301
"""Return the SHA1 file for a file.
331
:note: callers should use get_file_verifier instead
332
where possible, as the underlying repository implementation may
333
have quicker access to a non-sha1 verifier.
335
303
:param file_id: The handle for this file.
336
304
:param path: The path that this file can be found at.
337
305
These must point to the same object.
358
326
raise NotImplementedError(self.get_file_size)
328
def get_file_by_path(self, path):
329
raise NotImplementedError(self.get_file_by_path)
360
331
def is_executable(self, file_id, path=None):
361
332
"""Check if a file is executable.
631
602
prefs = self.iter_search_rules([path], filter_pref_names).next()
632
603
stk = filters._get_filter_stack_for(prefs)
633
604
if 'filters' in debug.debug_flags:
634
trace.note(gettext("*** {0} content-filter: {1} => {2!r}").format(path,prefs,stk))
605
trace.note("*** %s content-filter: %s => %r" % (path,prefs,stk))
637
608
def _content_filter_stack_provider(self):
774
745
inventory = property(_get_inventory,
775
746
doc="Inventory of this Tree")
777
def _unpack_file_id(self, file_id):
778
"""Find the inventory and inventory file id for a tree file id.
780
:param file_id: The tree file id, as bytestring or tuple
781
:return: Inventory and inventory file id
783
if isinstance(file_id, tuple):
784
if len(file_id) != 1:
785
raise ValueError("nested trees not yet supported: %r" % file_id)
787
return self.inventory, file_id
790
749
def path2id(self, path):
791
750
"""Return the id for path in this tree."""
792
return self._path2inv_file_id(path)[1]
794
def _path2inv_file_id(self, path):
795
"""Lookup a inventory and inventory file id by path.
797
:param path: Path to look up
798
:return: tuple with inventory and inventory file id
800
return self.inventory, self.inventory.path2id(path)
751
return self._inventory.path2id(path)
802
753
def id2path(self, file_id):
803
754
"""Return the path for a file id.
805
756
:raises NoSuchId:
807
inventory, file_id = self._unpack_file_id(file_id)
808
return inventory.id2path(file_id)
758
return self.inventory.id2path(file_id)
810
760
def has_id(self, file_id):
811
inventory, file_id = self._unpack_file_id(file_id)
812
return inventory.has_id(file_id)
761
return self.inventory.has_id(file_id)
814
763
def has_or_had_id(self, file_id):
815
inventory, file_id = self._unpack_file_id(file_id)
816
return inventory.has_id(file_id)
764
return self.inventory.has_id(file_id)
818
766
def all_file_ids(self):
820
[entry.file_id for path, entry in self.iter_entries_by_dir()])
767
return set(self.inventory)
822
769
@deprecated_method(deprecated_in((2, 4, 0)))
823
770
def __iter__(self):
824
return iter(self.all_file_ids())
771
return iter(self.inventory)
826
773
def filter_unversioned_files(self, paths):
827
774
"""Filter out paths that are versioned.
831
778
# NB: we specifically *don't* call self.has_filename, because for
832
779
# WorkingTrees that can indicate files that exist on disk but that
833
780
# are not versioned.
834
return set((p for p in paths if self.path2id(p) is None))
781
pred = self.inventory.has_filename
782
return set((p for p in paths if not pred(p)))
837
785
def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
846
794
down to specific_file_ids that have been requested. This has no
847
795
impact if specific_file_ids is None.
849
if specific_file_ids is None:
850
inventory_file_ids = None
852
inventory_file_ids = []
853
for tree_file_id in specific_file_ids:
854
inventory, inv_file_id = self._unpack_file_id(tree_file_id)
855
if not inventory is self.inventory: # for now
856
raise AssertionError("%r != %r" % (
857
inventory, self.inventory))
858
inventory_file_ids.append(inv_file_id)
859
797
return self.inventory.iter_entries_by_dir(
860
specific_file_ids=inventory_file_ids, yield_parents=yield_parents)
798
specific_file_ids=specific_file_ids, yield_parents=yield_parents)
862
@deprecated_method(deprecated_in((2, 5, 0)))
863
800
def get_file_by_path(self, path):
864
return self.get_file(self.path2id(path), path)
801
return self.get_file(self._inventory.path2id(path), path)
867
804
def find_ids_across_trees(filenames, trees, require_versioned=True):
1015
952
if source_kind != target_kind:
1016
953
changed_content = True
1017
954
elif source_kind == 'file':
1018
if not self.file_content_matches(file_id, file_id, source_path,
1019
target_path, source_stat, target_stat):
955
if (self.source.get_file_sha1(file_id, source_path, source_stat) !=
956
self.target.get_file_sha1(file_id, target_path, target_stat)):
1020
957
changed_content = True
1021
958
elif source_kind == 'symlink':
1022
959
if (self.source.get_symlink_target(file_id) !=
1335
1272
changed_file_ids.add(result[0])
1339
def file_content_matches(self, source_file_id, target_file_id,
1340
source_path=None, target_path=None, source_stat=None, target_stat=None):
1341
"""Check if two files are the same in the source and target trees.
1343
This only checks that the contents of the files are the same,
1344
it does not touch anything else.
1346
:param source_file_id: File id of the file in the source tree
1347
:param target_file_id: File id of the file in the target tree
1348
:param source_path: Path of the file in the source tree
1349
:param target_path: Path of the file in the target tree
1350
:param source_stat: Optional stat value of the file in the source tree
1351
:param target_stat: Optional stat value of the file in the target tree
1352
:return: Boolean indicating whether the files have the same contents
1354
source_verifier_kind, source_verifier_data = self.source.get_file_verifier(
1355
source_file_id, source_path, source_stat)
1356
target_verifier_kind, target_verifier_data = self.target.get_file_verifier(
1357
target_file_id, target_path, target_stat)
1358
if source_verifier_kind == target_verifier_kind:
1359
return (source_verifier_data == target_verifier_data)
1360
# Fall back to SHA1 for now
1361
if source_verifier_kind != "SHA1":
1362
source_sha1 = self.source.get_file_sha1(source_file_id,
1363
source_path, source_stat)
1365
source_sha1 = source_verifier_data
1366
if target_verifier_kind != "SHA1":
1367
target_sha1 = self.target.get_file_sha1(target_file_id,
1368
target_path, target_stat)
1370
target_sha1 = target_verifier_data
1371
return (source_sha1 == target_sha1)
1373
1276
InterTree.register_optimiser(InterTree)