Spaces:
Paused
Paused
| # Copyright (C) 2010, 2011 Sebastian Thiel ([email protected]) and contributors | |
| # | |
| # This module is part of GitDB and is released under | |
| # the New BSD License: https://opensource.org/license/bsd-3-clause/ | |
| """Module with basic data structures - they are designed to be lightweight and fast""" | |
| from gitdb.util import bin_to_hex | |
| from gitdb.fun import ( | |
| type_id_to_type_map, | |
| type_to_type_id_map | |
| ) | |
| __all__ = ('OInfo', 'OPackInfo', 'ODeltaPackInfo', | |
| 'OStream', 'OPackStream', 'ODeltaPackStream', | |
| 'IStream', 'InvalidOInfo', 'InvalidOStream') | |
| #{ ODB Bases | |
| class OInfo(tuple): | |
| """Carries information about an object in an ODB, providing information | |
| about the binary sha of the object, the type_string as well as the uncompressed size | |
| in bytes. | |
| It can be accessed using tuple notation and using attribute access notation:: | |
| assert dbi[0] == dbi.binsha | |
| assert dbi[1] == dbi.type | |
| assert dbi[2] == dbi.size | |
| The type is designed to be as lightweight as possible.""" | |
| __slots__ = tuple() | |
| def __new__(cls, sha, type, size): | |
| return tuple.__new__(cls, (sha, type, size)) | |
| def __init__(self, *args): | |
| tuple.__init__(self) | |
| #{ Interface | |
| def binsha(self): | |
| """:return: our sha as binary, 20 bytes""" | |
| return self[0] | |
| def hexsha(self): | |
| """:return: our sha, hex encoded, 40 bytes""" | |
| return bin_to_hex(self[0]) | |
| def type(self): | |
| return self[1] | |
| def type_id(self): | |
| return type_to_type_id_map[self[1]] | |
| def size(self): | |
| return self[2] | |
| #} END interface | |
| class OPackInfo(tuple): | |
| """As OInfo, but provides a type_id property to retrieve the numerical type id, and | |
| does not include a sha. | |
| Additionally, the pack_offset is the absolute offset into the packfile at which | |
| all object information is located. The data_offset property points to the absolute | |
| location in the pack at which that actual data stream can be found.""" | |
| __slots__ = tuple() | |
| def __new__(cls, packoffset, type, size): | |
| return tuple.__new__(cls, (packoffset, type, size)) | |
| def __init__(self, *args): | |
| tuple.__init__(self) | |
| #{ Interface | |
| def pack_offset(self): | |
| return self[0] | |
| def type(self): | |
| return type_id_to_type_map[self[1]] | |
| def type_id(self): | |
| return self[1] | |
| def size(self): | |
| return self[2] | |
| #} END interface | |
| class ODeltaPackInfo(OPackInfo): | |
| """Adds delta specific information, | |
| Either the 20 byte sha which points to some object in the database, | |
| or the negative offset from the pack_offset, so that pack_offset - delta_info yields | |
| the pack offset of the base object""" | |
| __slots__ = tuple() | |
| def __new__(cls, packoffset, type, size, delta_info): | |
| return tuple.__new__(cls, (packoffset, type, size, delta_info)) | |
| #{ Interface | |
| def delta_info(self): | |
| return self[3] | |
| #} END interface | |
| class OStream(OInfo): | |
| """Base for object streams retrieved from the database, providing additional | |
| information about the stream. | |
| Generally, ODB streams are read-only as objects are immutable""" | |
| __slots__ = tuple() | |
| def __new__(cls, sha, type, size, stream, *args, **kwargs): | |
| """Helps with the initialization of subclasses""" | |
| return tuple.__new__(cls, (sha, type, size, stream)) | |
| def __init__(self, *args, **kwargs): | |
| tuple.__init__(self) | |
| #{ Stream Reader Interface | |
| def read(self, size=-1): | |
| return self[3].read(size) | |
| def stream(self): | |
| return self[3] | |
| #} END stream reader interface | |
| class ODeltaStream(OStream): | |
| """Uses size info of its stream, delaying reads""" | |
| def __new__(cls, sha, type, size, stream, *args, **kwargs): | |
| """Helps with the initialization of subclasses""" | |
| return tuple.__new__(cls, (sha, type, size, stream)) | |
| #{ Stream Reader Interface | |
| def size(self): | |
| return self[3].size | |
| #} END stream reader interface | |
| class OPackStream(OPackInfo): | |
| """Next to pack object information, a stream outputting an undeltified base object | |
| is provided""" | |
| __slots__ = tuple() | |
| def __new__(cls, packoffset, type, size, stream, *args): | |
| """Helps with the initialization of subclasses""" | |
| return tuple.__new__(cls, (packoffset, type, size, stream)) | |
| #{ Stream Reader Interface | |
| def read(self, size=-1): | |
| return self[3].read(size) | |
| def stream(self): | |
| return self[3] | |
| #} END stream reader interface | |
| class ODeltaPackStream(ODeltaPackInfo): | |
| """Provides a stream outputting the uncompressed offset delta information""" | |
| __slots__ = tuple() | |
| def __new__(cls, packoffset, type, size, delta_info, stream): | |
| return tuple.__new__(cls, (packoffset, type, size, delta_info, stream)) | |
| #{ Stream Reader Interface | |
| def read(self, size=-1): | |
| return self[4].read(size) | |
| def stream(self): | |
| return self[4] | |
| #} END stream reader interface | |
| class IStream(list): | |
| """Represents an input content stream to be fed into the ODB. It is mutable to allow | |
| the ODB to record information about the operations outcome right in this instance. | |
| It provides interfaces for the OStream and a StreamReader to allow the instance | |
| to blend in without prior conversion. | |
| The only method your content stream must support is 'read'""" | |
| __slots__ = tuple() | |
| def __new__(cls, type, size, stream, sha=None): | |
| return list.__new__(cls, (sha, type, size, stream, None)) | |
| def __init__(self, type, size, stream, sha=None): | |
| list.__init__(self, (sha, type, size, stream, None)) | |
| #{ Interface | |
| def hexsha(self): | |
| """:return: our sha, hex encoded, 40 bytes""" | |
| return bin_to_hex(self[0]) | |
| def _error(self): | |
| """:return: the error that occurred when processing the stream, or None""" | |
| return self[4] | |
| def _set_error(self, exc): | |
| """Set this input stream to the given exc, may be None to reset the error""" | |
| self[4] = exc | |
| error = property(_error, _set_error) | |
| #} END interface | |
| #{ Stream Reader Interface | |
| def read(self, size=-1): | |
| """Implements a simple stream reader interface, passing the read call on | |
| to our internal stream""" | |
| return self[3].read(size) | |
| #} END stream reader interface | |
| #{ interface | |
| def _set_binsha(self, binsha): | |
| self[0] = binsha | |
| def _binsha(self): | |
| return self[0] | |
| binsha = property(_binsha, _set_binsha) | |
| def _type(self): | |
| return self[1] | |
| def _set_type(self, type): | |
| self[1] = type | |
| type = property(_type, _set_type) | |
| def _size(self): | |
| return self[2] | |
| def _set_size(self, size): | |
| self[2] = size | |
| size = property(_size, _set_size) | |
| def _stream(self): | |
| return self[3] | |
| def _set_stream(self, stream): | |
| self[3] = stream | |
| stream = property(_stream, _set_stream) | |
| #} END odb info interface | |
| class InvalidOInfo(tuple): | |
| """Carries information about a sha identifying an object which is invalid in | |
| the queried database. The exception attribute provides more information about | |
| the cause of the issue""" | |
| __slots__ = tuple() | |
| def __new__(cls, sha, exc): | |
| return tuple.__new__(cls, (sha, exc)) | |
| def __init__(self, sha, exc): | |
| tuple.__init__(self, (sha, exc)) | |
| def binsha(self): | |
| return self[0] | |
| def hexsha(self): | |
| return bin_to_hex(self[0]) | |
| def error(self): | |
| """:return: exception instance explaining the failure""" | |
| return self[1] | |
| class InvalidOStream(InvalidOInfo): | |
| """Carries information about an invalid ODB stream""" | |
| __slots__ = tuple() | |
| #} END ODB Bases | |