127
127
def has_id(self, file_id):
128
128
raise NotImplementedError(self.has_id)
130
@deprecated_method(deprecated_in((2, 4, 0)))
131
130
def __contains__(self, file_id):
132
131
return self.has_id(file_id)
278
277
:param file_id: The file_id of the file.
279
278
:param path: The path of the file.
281
279
If both file_id and path are supplied, an implementation may use
284
:returns: A single byte string for the whole file.
286
282
my_file = self.get_file(file_id, path)
301
297
return osutils.split_lines(self.get_file_text(file_id, path))
303
def get_file_verifier(self, file_id, path=None, stat_value=None):
304
"""Return a verifier for a file.
306
The default implementation returns a sha1.
308
:param file_id: The handle for this file.
309
:param path: The path that this file can be found at.
310
These must point to the same object.
311
:param stat_value: Optional stat value for the object
312
:return: Tuple with verifier name and verifier data
314
return ("SHA1", self.get_file_sha1(file_id, path=path,
315
stat_value=stat_value))
317
299
def get_file_sha1(self, file_id, path=None, stat_value=None):
318
300
"""Return the SHA1 file for a file.
320
:note: callers should use get_file_verifier instead
321
where possible, as the underlying repository implementation may
322
have quicker access to a non-sha1 verifier.
324
302
:param file_id: The handle for this file.
325
303
:param path: The path that this file can be found at.
326
304
These must point to the same object.
822
800
return self.get_file(self._inventory.path2id(path), path)
803
######################################################################
806
# TODO: Merge these two functions into a single one that can operate
807
# on either a whole tree or a set of files.
809
# TODO: Return the diff in order by filename, not by category or in
810
# random order. Can probably be done by lock-stepping through the
811
# filenames from both trees.
814
def file_status(filename, old_tree, new_tree):
815
"""Return single-letter status, old and new names for a file.
817
The complexity here is in deciding how to represent renames;
818
many complex cases are possible.
820
old_inv = old_tree.inventory
821
new_inv = new_tree.inventory
822
new_id = new_inv.path2id(filename)
823
old_id = old_inv.path2id(filename)
825
if not new_id and not old_id:
826
# easy: doesn't exist in either; not versioned at all
827
if new_tree.is_ignored(filename):
828
return 'I', None, None
830
return '?', None, None
832
# There is now a file of this name, great.
835
# There is no longer a file of this name, but we can describe
836
# what happened to the file that used to have
837
# this name. There are two possibilities: either it was
838
# deleted entirely, or renamed.
839
if new_inv.has_id(old_id):
840
return 'X', old_inv.id2path(old_id), new_inv.id2path(old_id)
842
return 'D', old_inv.id2path(old_id), None
844
# if the file_id is new in this revision, it is added
845
if new_id and not old_inv.has_id(new_id):
848
# if there used to be a file of this name, but that ID has now
849
# disappeared, it is deleted
850
if old_id and not new_inv.has_id(old_id):
825
856
def find_ids_across_trees(filenames, trees, require_versioned=True):
826
857
"""Find the ids corresponding to specified filenames.
973
1004
if source_kind != target_kind:
974
1005
changed_content = True
975
1006
elif source_kind == 'file':
976
if not self.file_content_matches(file_id, file_id, source_path,
977
target_path, source_stat, target_stat):
1007
if (self.source.get_file_sha1(file_id, source_path, source_stat) !=
1008
self.target.get_file_sha1(file_id, target_path, target_stat)):
978
1009
changed_content = True
979
1010
elif source_kind == 'symlink':
980
1011
if (self.source.get_symlink_target(file_id) !=
1293
1324
changed_file_ids.add(result[0])
1297
def file_content_matches(self, source_file_id, target_file_id,
1298
source_path=None, target_path=None, source_stat=None, target_stat=None):
1299
"""Check if two files are the same in the source and target trees.
1301
This only checks that the contents of the files are the same,
1302
it does not touch anything else.
1304
:param source_file_id: File id of the file in the source tree
1305
:param target_file_id: File id of the file in the target tree
1306
:param source_path: Path of the file in the source tree
1307
:param target_path: Path of the file in the target tree
1308
:param source_stat: Optional stat value of the file in the source tree
1309
:param target_stat: Optional stat value of the file in the target tree
1310
:return: Boolean indicating whether the files have the same contents
1312
source_verifier_kind, source_verifier_data = self.source.get_file_verifier(
1313
source_file_id, source_path, source_stat)
1314
target_verifier_kind, target_verifier_data = self.target.get_file_verifier(
1315
target_file_id, target_path, target_stat)
1316
if source_verifier_kind == target_verifier_kind:
1317
return (source_verifier_data == target_verifier_data)
1318
# Fall back to SHA1 for now
1319
if source_verifier_kind != "SHA1":
1320
source_sha1 = self.source.get_file_sha1(source_file_id,
1321
source_path, source_stat)
1323
source_sha1 = source_verifier_data
1324
if target_verifier_kind != "SHA1":
1325
target_sha1 = self.target.get_file_sha1(target_file_id,
1326
target_path, target_stat)
1328
target_sha1 = target_verifier_data
1329
return (source_sha1 == target_sha1)
1331
1328
InterTree.register_optimiser(InterTree)