719
def _bisect_recursive(self, dir_name_list):
720
"""Bisect for entries for all paths and their children.
722
This will use bisect to find all records for the supplied paths. It
723
will then continue to bisect for any records which are marked as
724
directories. (and renames?)
726
:param paths: A sorted list of (dir, name) pairs
727
eg: [('', 'a'), ('', 'f'), ('a/b', 'c')]
728
:return: A dictionary mapping (dir, name, file_id) => [tree_info]
730
# Map from (dir, name, file_id) => [tree_info]
733
found_dir_names = set()
735
# Directories that have been read
736
processed_dirs = set()
737
# Get the ball rolling with the first bisect for all entries.
738
newly_found = self._bisect(dir_name_list)
741
# Directories that need to be read
743
paths_to_search = set()
744
for entry_list in newly_found.itervalues():
745
for dir_name_id, trees_info in entry_list:
746
found[dir_name_id] = trees_info
747
found_dir_names.add(dir_name_id[:2])
749
for tree_info in trees_info:
750
minikind = tree_info[0]
753
# We already processed this one as a directory,
754
# we don't need to do the extra work again.
756
subdir, name, file_id = dir_name_id
757
path = osutils.pathjoin(subdir, name)
759
if path not in processed_dirs:
760
pending_dirs.add(path)
761
elif minikind == 'r':
762
# Rename, we need to directly search the target
763
# which is contained in the fingerprint column
764
dir_name = osutils.split(tree_info[1])
765
if dir_name[0] in pending_dirs:
766
# This entry will be found in the dir search
768
# TODO: We need to check if this entry has
769
# already been found. Otherwise we might be
770
# hitting infinite recursion.
771
if dir_name not in found_dir_names:
772
paths_to_search.add(dir_name)
773
# Now we have a list of paths to look for directly, and
774
# directory blocks that need to be read.
775
# newly_found is mixing the keys between (dir, name) and path
776
# entries, but that is okay, because we only really care about the
778
newly_found = self._bisect(sorted(paths_to_search))
779
newly_found.update(self._bisect_dirblocks(sorted(pending_dirs)))
780
processed_dirs.update(pending_dirs)
719
783
def _empty_parent_info(self):
720
784
return [DirState.NULL_PARENT_DETAILS] * (len(self._parents) -
721
785
len(self._ghosts))