Spaces:
Running
Running
# Copyright (C) 2010, 2011 Sebastian Thiel (byronimo@gmail.com) and contributors | |
# | |
# This module is part of GitDB and is released under | |
# the New BSD License: https://opensource.org/license/bsd-3-clause/ | |
"""Contains the MemoryDatabase implementation""" | |
from gitdb.db.loose import LooseObjectDB | |
from gitdb.db.base import ( | |
ObjectDBR, | |
ObjectDBW | |
) | |
from gitdb.base import ( | |
OStream, | |
IStream, | |
) | |
from gitdb.exc import ( | |
BadObject, | |
UnsupportedOperation | |
) | |
from gitdb.stream import ( | |
ZippedStoreShaWriter, | |
DecompressMemMapReader, | |
) | |
from io import BytesIO | |
__all__ = ("MemoryDB", ) | |
class MemoryDB(ObjectDBR, ObjectDBW): | |
"""A memory database stores everything to memory, providing fast IO and object | |
retrieval. It should be used to buffer results and obtain SHAs before writing | |
it to the actual physical storage, as it allows to query whether object already | |
exists in the target storage before introducing actual IO""" | |
def __init__(self): | |
super().__init__() | |
self._db = LooseObjectDB("path/doesnt/matter") | |
# maps 20 byte shas to their OStream objects | |
self._cache = dict() | |
def set_ostream(self, stream): | |
raise UnsupportedOperation("MemoryDB's always stream into memory") | |
def store(self, istream): | |
zstream = ZippedStoreShaWriter() | |
self._db.set_ostream(zstream) | |
istream = self._db.store(istream) | |
zstream.close() # close to flush | |
zstream.seek(0) | |
# don't provide a size, the stream is written in object format, hence the | |
# header needs decompression | |
decomp_stream = DecompressMemMapReader(zstream.getvalue(), close_on_deletion=False) | |
self._cache[istream.binsha] = OStream(istream.binsha, istream.type, istream.size, decomp_stream) | |
return istream | |
def has_object(self, sha): | |
return sha in self._cache | |
def info(self, sha): | |
# we always return streams, which are infos as well | |
return self.stream(sha) | |
def stream(self, sha): | |
try: | |
ostream = self._cache[sha] | |
# rewind stream for the next one to read | |
ostream.stream.seek(0) | |
return ostream | |
except KeyError as e: | |
raise BadObject(sha) from e | |
# END exception handling | |
def size(self): | |
return len(self._cache) | |
def sha_iter(self): | |
return self._cache.keys() | |
#{ Interface | |
def stream_copy(self, sha_iter, odb): | |
"""Copy the streams as identified by sha's yielded by sha_iter into the given odb | |
The streams will be copied directly | |
**Note:** the object will only be written if it did not exist in the target db | |
:return: amount of streams actually copied into odb. If smaller than the amount | |
of input shas, one or more objects did already exist in odb""" | |
count = 0 | |
for sha in sha_iter: | |
if odb.has_object(sha): | |
continue | |
# END check object existence | |
ostream = self.stream(sha) | |
# compressed data including header | |
sio = BytesIO(ostream.stream.data()) | |
istream = IStream(ostream.type, ostream.size, sio, sha) | |
odb.store(istream) | |
count += 1 | |
# END for each sha | |
return count | |
#} END interface | |