def resolve_object(self, offset, type, obj, get_ref, get_offset=None): """Resolve an object, possibly resolving deltas when necessary. :return: Tuple with object type and contents. """ if type not in (6, 7): # Not a delta return type, obj if get_offset is None: get_offset = self.get_object_at if type == 6: # offset delta (delta_offset, delta) = obj assert isinstance(delta_offset, int) assert isinstance(delta, str) base_offset = offset-delta_offset type, base_obj = get_offset(base_offset) assert isinstance(type, int) elif type == 7: # ref delta (basename, delta) = obj assert isinstance(basename, str) and len(basename) == 20 assert isinstance(delta, str) type, base_obj = get_ref(basename) assert isinstance(type, int) # Can't be a ofs delta, as we wouldn't know the base offset assert type != 6 base_offset = None type, base_text = self.resolve_object(base_offset, type, base_obj, get_ref) if base_offset is not None: self._offset_cache[base_offset] = type, base_text ret = (type, apply_delta(base_text, delta)) return ret
def resolve_object(self, offset, type, obj, get_ref=None): """Resolve an object, possibly resolving deltas when necessary. :return: Tuple with object type and contents. """ if type not in DELTA_TYPES: return type, obj if get_ref is None: get_ref = self.get_ref if type == OFS_DELTA: (delta_offset, delta) = obj # TODO: clean up asserts and replace with nicer error messages assert isinstance(offset, int) assert isinstance(delta_offset, int) base_offset = offset-delta_offset type, base_obj = self.get_object_at(base_offset) assert isinstance(type, int) elif type == REF_DELTA: (basename, delta) = obj assert isinstance(basename, str) and len(basename) == 20 base_offset, type, base_obj = get_ref(basename) assert isinstance(type, int) type, base_chunks = self.resolve_object(base_offset, type, base_obj) chunks = apply_delta(base_chunks, delta) # TODO(dborowitz): This can result in poor performance if large base # objects are separated from deltas in the pack. We should reorganize # so that we apply deltas to all objects in a chain one after the other # to optimize cache performance. if offset is not None: self._offset_cache[offset] = type, chunks return type, chunks
def resolve_object(self, offset, type, obj, get_ref, get_offset=None): """Resolve an object, possibly resolving deltas when necessary. :return: Tuple with object type and contents. """ if type not in (6, 7): # Not a delta return type, obj if get_offset is None: get_offset = self.get_object_at if type == 6: # offset delta (delta_offset, delta) = obj assert isinstance(delta_offset, int) assert isinstance(delta, str) base_offset = offset - delta_offset type, base_obj = get_offset(base_offset) assert isinstance(type, int) elif type == 7: # ref delta (basename, delta) = obj assert isinstance(basename, str) and len(basename) == 20 assert isinstance(delta, str) type, base_obj = get_ref(basename) assert isinstance(type, int) # Can't be a ofs delta, as we wouldn't know the base offset assert type != 6 base_offset = None type, base_text = self.resolve_object(base_offset, type, base_obj, get_ref) if base_offset is not None: self._offset_cache[base_offset] = type, base_text ret = (type, apply_delta(base_text, delta)) return ret