396
def fileid_involved_between_revs(self, from_revid, to_revid):
397
""" This function returns the file_id(s) involved in the
398
changes between the from_revid revision and the to_revid
401
raise NotImplementedError('fileid_involved_between_revs is abstract')
403
def fileid_involved(self, last_revid=None):
404
""" This function returns the file_id(s) involved in the
405
changes up to the revision last_revid
406
If no parametr is passed, then all file_id[s] present in the
407
repository are returned
409
raise NotImplementedError('fileid_involved is abstract')
411
def fileid_involved_by_set(self, changes):
412
""" This function returns the file_id(s) involved in the
413
changes present in the set 'changes'
415
raise NotImplementedError('fileid_involved_by_set is abstract')
417
def fileid_involved_between_revs(self, from_revid, to_revid):
418
""" This function returns the file_id(s) involved in the
419
changes between the from_revid revision and the to_revid
422
raise NotImplementedError('fileid_involved_between_revs is abstract')
424
def fileid_involved(self, last_revid=None):
425
""" This function returns the file_id(s) involved in the
426
changes up to the revision last_revid
427
If no parametr is passed, then all file_id[s] present in the
428
repository are returned
430
raise NotImplementedError('fileid_involved is abstract')
432
def fileid_involved_by_set(self, changes):
433
""" This function returns the file_id(s) involved in the
434
changes present in the set 'changes'
436
raise NotImplementedError('fileid_involved_by_set is abstract')
395
439
class BzrBranch(Branch):
396
440
"""A branch stored in the actual filesystem.
831
874
return Branch.clone(self, to_location, revision, basis_branch, to_branch_type)
876
def fileid_involved_between_revs(self, from_revid, to_revid):
877
"""Find file_id(s) which are involved in the changes between revisions.
879
This determines the set of revisions which are involved, and then
880
finds all file ids affected by those revisions.
882
# TODO: jam 20060119 This code assumes that w.inclusions will
883
# always be correct. But because of the presence of ghosts
884
# it is possible to be wrong.
885
# One specific example from Robert Collins:
886
# Two branches, with revisions ABC, and AD
887
# C is a ghost merge of D.
888
# Inclusions doesn't recognize D as an ancestor.
889
# If D is ever merged in the future, the weave
890
# won't be fixed, because AD never saw revision C
891
# to cause a conflict which would force a reweave.
892
w = self.repository.get_inventory_weave()
893
from_set = set(w.inclusions([w.lookup(from_revid)]))
894
to_set = set(w.inclusions([w.lookup(to_revid)]))
895
included = to_set.difference(from_set)
896
changed = map(w.idx_to_name, included)
897
return self._fileid_involved_by_set(changed)
899
def fileid_involved(self, last_revid=None):
900
"""Find all file_ids modified in the ancestry of last_revid.
902
:param last_revid: If None, last_revision() will be used.
904
w = self.repository.get_inventory_weave()
906
changed = set(w._names)
908
included = w.inclusions([w.lookup(last_revid)])
909
changed = map(w.idx_to_name, included)
910
return self._fileid_involved_by_set(changed)
912
def fileid_involved_by_set(self, changes):
913
"""Find all file_ids modified by the set of revisions passed in.
915
:param changes: A set() of revision ids
917
# TODO: jam 20060119 This line does *nothing*, remove it.
918
# or better yet, change _fileid_involved_by_set so
919
# that it takes the inventory weave, rather than
920
# pulling it out by itself.
921
w = self.repository.get_inventory_weave()
922
return self._fileid_involved_by_set(changes)
924
def _fileid_involved_by_set(self, changes):
925
"""Find the set of file-ids affected by the set of revisions.
927
:param changes: A set() of revision ids.
928
:return: A set() of file ids.
930
This peaks at the Weave, interpreting each line, looking to
931
see if it mentions one of the revisions. And if so, includes
932
the file id mentioned.
933
This expects both the Weave format, and the serialization
934
to have a single line per file/directory, and to have
935
fileid="" and revision="" on that line.
937
assert self._branch_format in (5, 6), \
938
"fileid_involved only supported for branches which store inventory as xml"
940
w = self.repository.get_inventory_weave()
942
for line in w._weave:
944
# it is ugly, but it is due to the weave structure
945
if not isinstance(line, basestring): continue
947
start = line.find('file_id="')+9
948
if start < 9: continue
949
end = line.find('"', start)
951
file_id = xml.sax.saxutils.unescape(line[start:end])
953
# check if file_id is already present
954
if file_id in file_ids: continue
956
start = line.find('revision="')+10
957
if start < 10: continue
958
end = line.find('"', start)
960
revision_id = xml.sax.saxutils.unescape(line[start:end])
962
if revision_id in changes:
963
file_ids.add(file_id)
834
968
class ScratchBranch(BzrBranch):
835
969
"""Special test class: a branch that cleans up after itself.