~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Martin Pool
  • Date: 2008-06-18 07:56:09 UTC
  • mto: This revision was merged to the branch mainline in revision 3510.
  • Revision ID: mbp@sourcefrog.net-20080618075609-zehkroqkqufck2zb
VersionedFiles review cleanups

Show diffs side-by-side

added added

removed removed

Lines of Context:
579
579
                result.append((prefix + (origin,), line))
580
580
            return result
581
581
        else:
 
582
            # XXX: This smells a bit.  Why would key ever be a non-tuple here?
 
583
            # Aren't keys defined to be tuples?  -- spiv 20080618
582
584
            return content.annotate()
583
585
 
584
586
 
647
649
 
648
650
def make_file_factory(annotated, mapper):
649
651
    """Create a factory for creating a file based KnitVersionedFiles.
 
652
 
 
653
    This is only functional enough to run interface tests, it doesn't try to
 
654
    provide a full pack environment.
650
655
    
651
656
    :param annotated: knit annotations are wanted.
652
657
    :param mapper: The mapper from keys to paths.
845
850
 
846
851
    def _check_add(self, key, lines, random_id, check_content):
847
852
        """check that version_id and lines are safe to add."""
848
 
        if contains_whitespace(key[-1]):
849
 
            raise InvalidRevisionId(key[-1], self.filename)
850
 
        self.check_not_reserved_id(key[-1])
 
853
        version_id = key[-1]
 
854
        if contains_whitespace(version_id):
 
855
            raise InvalidRevisionId(version_id, self.filename)
 
856
        self.check_not_reserved_id(version_id)
851
857
        # Technically this could be avoided if we are happy to allow duplicate
852
858
        # id insertion when other things than bzr core insert texts, but it
853
859
        # seems useful for folk using the knit api directly to have some safety
910
916
        # record_details, access_memo, compression_parent
911
917
        return build_details[3], build_details[0], build_details[1]
912
918
 
913
 
    def _get_components_positions(self, keys, noraise=False):
 
919
    def _get_components_positions(self, keys, allow_missing=False):
914
920
        """Produce a map of position data for the components of keys.
915
921
 
916
922
        This data is intended to be used for retrieving the knit records.
923
929
        next is the build-parent of the version, or None for fulltexts.
924
930
        parents is the version_ids of the parents of this version
925
931
 
926
 
        :param noraise: If True do not raise an error on a missing component,
 
932
        :param allow_missing: If True do not raise an error on a missing component,
927
933
            just ignore it.
928
934
        """
929
935
        component_data = {}
940
946
                    pending_components.add(compression_parent)
941
947
                component_data[key] = self._build_details_to_components(details)
942
948
            missing = current_components.difference(build_details)
943
 
            if missing and not noraise:
 
949
            if missing and not allow_missing:
944
950
                raise errors.RevisionNotPresent(missing.pop(), self)
945
951
        return component_data
946
952
       
960
966
        """Produce maps of text and KnitContents
961
967
        
962
968
        :return: (text_map, content_map) where text_map contains the texts for
963
 
        the requested versions and content_map contains the KnitContents.
 
969
            the requested versions and content_map contains the KnitContents.
964
970
        """
965
971
        # FUTURE: This function could be improved for the 'extract many' case
966
972
        # by tracking each component and only doing the copy when the number of
1062
1068
            # Cannot topological order when no graph has been stored.
1063
1069
            ordering = 'unordered'
1064
1070
        if include_delta_closure:
1065
 
            positions = self._get_components_positions(keys, noraise=True)
 
1071
            positions = self._get_components_positions(keys, allow_missing=True)
1066
1072
        else:
1067
1073
            build_details = self._index.get_build_details(keys)
1068
1074
            positions = dict((key, self._build_details_to_components(details))
1071
1077
        # There may be more absent keys : if we're missing the basis component
1072
1078
        # and are trying to include the delta closure.
1073
1079
        if include_delta_closure:
1074
 
            # key:True means key can be reconstructed
1075
 
            checked_keys = {}
 
1080
            # Build up reconstructable_keys dict.  key:True in this dict means the key
 
1081
            # can be reconstructed.
 
1082
            reconstructable_keys = {}
1076
1083
            for key in keys:
1077
1084
                # the delta chain
1078
1085
                try:
1082
1089
                    continue
1083
1090
                result = True
1084
1091
                while chain[-1] is not None:
1085
 
                    if chain[-1] in checked_keys:
1086
 
                        result = checked_keys[chain[-1]]
 
1092
                    if chain[-1] in reconstructable_keys:
 
1093
                        result = reconstructable_keys[chain[-1]]
1087
1094
                        break
1088
1095
                    else:
1089
1096
                        try:
1093
1100
                            result = False
1094
1101
                            break
1095
1102
                for chain_key in chain[:-1]:
1096
 
                    checked_keys[chain_key] = result
 
1103
                    reconstructable_keys[chain_key] = result
1097
1104
                if not result:
1098
1105
                    absent_keys.add(key)
1099
1106
        for key in absent_keys:
1205
1212
                    basis_parent = parents[0]
1206
1213
                    # Note that pack backed knits don't need to buffer here
1207
1214
                    # because they buffer all writes to the transaction level,
1208
 
                    # but we don't expose that differnet at the index level. If
 
1215
                    # but we don't expose that difference at the index level. If
1209
1216
                    # the query here has sufficient cost to show up in
1210
1217
                    # profiling we should do that.
1211
1218
                    if basis_parent not in self.get_parent_map([basis_parent]):
1279
1286
        for key in keys:
1280
1287
            key_records.append((key, build_details[key][0]))
1281
1288
        total = len(key_records)
1282
 
        for key_idx, (key, data, sha_value) in \
1283
 
            enumerate(self._read_records_iter(key_records)):
 
1289
        records_iter = enumerate(self._read_records_iter(key_records))
 
1290
        for (key_idx, (key, data, sha_value)) in records_iter:
1284
1291
            pb.update('Walking content.', key_idx, total)
1285
1292
            compression_parent = build_details[key][1]
1286
1293
            if compression_parent is None:
1333
1340
                    # content for any line that matches the last-checked
1334
1341
                    # parent.
1335
1342
                    content._lines[j:j+n] = merge_content._lines[i:i+n]
 
1343
            # XXX: Robert says the following block is a workaround for a
 
1344
            # now-fixed bug and it can probably be deleted. -- mbp 20080618
1336
1345
            if content._lines and content._lines[-1][1][-1] != '\n':
1337
1346
                # The copied annotation was from a line without a trailing EOL,
1338
1347
                # reinstate one for the content object, to ensure correct
1499
1508
class _KndxIndex(object):
1500
1509
    """Manages knit index files
1501
1510
 
1502
 
    The index is kept in memorya  already kept in memory and read on startup, to enable
 
1511
    The index is kept in memory and read on startup, to enable
1503
1512
    fast lookups of revision information.  The cursor of the index
1504
1513
    file is always pointing to the end, making it easy to append
1505
1514
    entries.
1665
1674
        Ghosts are omitted from the result.
1666
1675
 
1667
1676
        :param keys: An iterable of keys.
1668
 
        :return: A dict of key:(access_memo, compression_parent, parents,
 
1677
        :return: A dict of key:(index_memo, compression_parent, parents,
1669
1678
            record_details).
1670
1679
            index_memo
1671
1680
                opaque structure to pass to read_records to extract the raw
1725
1734
        # Parse what we need to up front, this potentially trades off I/O
1726
1735
        # locality (.kndx and .knit in the same block group for the same file
1727
1736
        # id) for less checking in inner loops.
1728
 
        prefixes = set()
1729
 
        prefixes.update(key[:-1] for key in keys)
 
1737
        prefixes = set(key[:-1] for key in keys)
1730
1738
        self._load_prefixes(prefixes)
1731
1739
        result = {}
1732
1740
        for key in keys: