127
127
def has_id(self, file_id):
128
128
raise NotImplementedError(self.has_id)
130
@deprecated_method(deprecated_in((2, 4, 0)))
130
131
def __contains__(self, file_id):
131
132
return self.has_id(file_id)
277
278
:param file_id: The file_id of the file.
278
279
:param path: The path of the file.
279
281
If both file_id and path are supplied, an implementation may use
284
:returns: A single byte string for the whole file.
282
286
my_file = self.get_file(file_id, path)
297
301
return osutils.split_lines(self.get_file_text(file_id, path))
299
def get_file_sha1(self, file_id, path=None):
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
def get_file_sha1(self, file_id, path=None, stat_value=None):
300
318
"""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.
302
324
:param file_id: The handle for this file.
303
325
:param path: The path that this file can be found at.
304
326
These must point to the same object.
327
:param stat_value: Optional stat value for the object
306
329
raise NotImplementedError(self.get_file_sha1)
799
822
return self.get_file(self._inventory.path2id(path), path)
802
######################################################################
805
# TODO: Merge these two functions into a single one that can operate
806
# on either a whole tree or a set of files.
808
# TODO: Return the diff in order by filename, not by category or in
809
# random order. Can probably be done by lock-stepping through the
810
# filenames from both trees.
813
def file_status(filename, old_tree, new_tree):
814
"""Return single-letter status, old and new names for a file.
816
The complexity here is in deciding how to represent renames;
817
many complex cases are possible.
819
old_inv = old_tree.inventory
820
new_inv = new_tree.inventory
821
new_id = new_inv.path2id(filename)
822
old_id = old_inv.path2id(filename)
824
if not new_id and not old_id:
825
# easy: doesn't exist in either; not versioned at all
826
if new_tree.is_ignored(filename):
827
return 'I', None, None
829
return '?', None, None
831
# There is now a file of this name, great.
834
# There is no longer a file of this name, but we can describe
835
# what happened to the file that used to have
836
# this name. There are two possibilities: either it was
837
# deleted entirely, or renamed.
838
if new_inv.has_id(old_id):
839
return 'X', old_inv.id2path(old_id), new_inv.id2path(old_id)
841
return 'D', old_inv.id2path(old_id), None
843
# if the file_id is new in this revision, it is added
844
if new_id and not old_inv.has_id(new_id):
847
# if there used to be a file of this name, but that ID has now
848
# disappeared, it is deleted
849
if old_id and not new_inv.has_id(old_id):
855
825
def find_ids_across_trees(filenames, trees, require_versioned=True):
856
826
"""Find the ids corresponding to specified filenames.
1003
973
if source_kind != target_kind:
1004
974
changed_content = True
1005
975
elif source_kind == 'file':
1006
if (self.source.get_file_sha1(file_id, source_path, source_stat) !=
1007
self.target.get_file_sha1(file_id, target_path, target_stat)):
976
if not self.file_content_matches(file_id, file_id, source_path,
977
target_path, source_stat, target_stat):
1008
978
changed_content = True
1009
979
elif source_kind == 'symlink':
1010
980
if (self.source.get_symlink_target(file_id) !=
1323
1293
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)
1327
1331
InterTree.register_optimiser(InterTree)