58
61
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
61
72
def changes_from(self, other, want_unchanged=False, specific_files=None,
62
73
extra_trees=None, require_versioned=False, include_root=False,
63
74
want_unversioned=False):
278
289
:param file_id: The file_id of the file.
279
290
:param path: The path of the file.
280
292
If both file_id and path are supplied, an implementation may use
295
:returns: A single byte string for the whole file.
283
297
my_file = self.get_file(file_id, path)
298
312
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))
300
328
def get_file_sha1(self, file_id, path=None, stat_value=None):
301
329
"""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.
303
335
:param file_id: The handle for this file.
304
336
:param path: The path that this file can be found at.
305
337
These must point to the same object.
326
358
raise NotImplementedError(self.get_file_size)
328
def get_file_by_path(self, path):
329
raise NotImplementedError(self.get_file_by_path)
331
360
def is_executable(self, file_id, path=None):
332
361
"""Check if a file is executable.
602
631
prefs = self.iter_search_rules([path], filter_pref_names).next()
603
632
stk = filters._get_filter_stack_for(prefs)
604
633
if 'filters' in debug.debug_flags:
605
trace.note("*** %s content-filter: %s => %r" % (path,prefs,stk))
634
trace.note(gettext("*** {0} content-filter: {1} => {2!r}").format(path,prefs,stk))
608
637
def _content_filter_stack_provider(self):
745
774
inventory = property(_get_inventory,
746
775
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
749
790
def path2id(self, path):
750
791
"""Return the id for path in this tree."""
751
return self._inventory.path2id(path)
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)
753
802
def id2path(self, file_id):
754
803
"""Return the path for a file id.
756
805
:raises NoSuchId:
758
return self.inventory.id2path(file_id)
807
inventory, file_id = self._unpack_file_id(file_id)
808
return inventory.id2path(file_id)
760
810
def has_id(self, file_id):
761
return self.inventory.has_id(file_id)
811
inventory, file_id = self._unpack_file_id(file_id)
812
return inventory.has_id(file_id)
763
814
def has_or_had_id(self, file_id):
764
return self.inventory.has_id(file_id)
815
inventory, file_id = self._unpack_file_id(file_id)
816
return inventory.has_id(file_id)
766
818
def all_file_ids(self):
767
return set(self.inventory)
820
[entry.file_id for path, entry in self.iter_entries_by_dir()])
769
822
@deprecated_method(deprecated_in((2, 4, 0)))
770
823
def __iter__(self):
771
return iter(self.inventory)
824
return iter(self.all_file_ids())
773
826
def filter_unversioned_files(self, paths):
774
827
"""Filter out paths that are versioned.
778
831
# NB: we specifically *don't* call self.has_filename, because for
779
832
# WorkingTrees that can indicate files that exist on disk but that
780
833
# are not versioned.
781
pred = self.inventory.has_filename
782
return set((p for p in paths if not pred(p)))
834
return set((p for p in paths if self.path2id(p) is None))
785
837
def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
794
846
down to specific_file_ids that have been requested. This has no
795
847
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)
797
859
return self.inventory.iter_entries_by_dir(
798
specific_file_ids=specific_file_ids, yield_parents=yield_parents)
860
specific_file_ids=inventory_file_ids, yield_parents=yield_parents)
862
@deprecated_method(deprecated_in((2, 5, 0)))
800
863
def get_file_by_path(self, path):
801
return self.get_file(self._inventory.path2id(path), path)
864
return self.get_file(self.path2id(path), path)
804
867
def find_ids_across_trees(filenames, trees, require_versioned=True):
952
1015
if source_kind != target_kind:
953
1016
changed_content = True
954
1017
elif source_kind == 'file':
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)):
1018
if not self.file_content_matches(file_id, file_id, source_path,
1019
target_path, source_stat, target_stat):
957
1020
changed_content = True
958
1021
elif source_kind == 'symlink':
959
1022
if (self.source.get_symlink_target(file_id) !=
1272
1335
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)
1276
1373
InterTree.register_optimiser(InterTree)