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
def get_file_sha1(self, file_id, path=None, stat_value=None):
299
def get_file_sha1(self, file_id, path=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.
327
:param stat_value: Optional stat value for the object
329
306
raise NotImplementedError(self.get_file_sha1)
822
799
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):
825
855
def find_ids_across_trees(filenames, trees, require_versioned=True):
826
856
"""Find the ids corresponding to specified filenames.
973
1003
if source_kind != target_kind:
974
1004
changed_content = True
975
1005
elif source_kind == 'file':
976
if not self.file_content_matches(file_id, file_id, source_path,
977
target_path, source_stat, target_stat):
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)):
978
1008
changed_content = True
979
1009
elif source_kind == 'symlink':
980
1010
if (self.source.get_symlink_target(file_id) !=
1293
1323
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
1327
InterTree.register_optimiser(InterTree)