Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion git/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@

__all__ = ["GitCmdObjectDB", "GitDB"]

from gitdb.base import OInfo, OStream
from subprocess import PIPE

from gitdb.base import IStream, OInfo, OStream
from gitdb.db import GitDB, LooseObjectDB
from gitdb.exc import BadObject
from gitdb.fun import stream_copy

from git.compat import force_text
from git.util import bin_to_hex, hex_to_bin
from git.exc import GitCommandError

Expand Down Expand Up @@ -46,6 +50,25 @@ def stream(self, binsha: bytes) -> OStream:
hexsha, typename, size, stream = self._git.stream_object_data(bin_to_hex(binsha))
return OStream(hex_to_bin(hexsha), typename, size, stream)

def store(self, istream: IStream) -> IStream:
"""Store an object using git itself."""
if istream.binsha is not None or self.ostream() is not None:
return super().store(istream)

proc = self._git.hash_object(
"-t", force_text(istream.type), "-w", "--stdin", "--literally", as_process=True, istream=PIPE
)
assert proc.stdin is not None
try:
stream_copy(istream.read, proc.stdin.write, istream.size, self.stream_chunk_size)
finally:
proc.stdin.close()
assert proc.stdout is not None
hexsha = proc.stdout.read().strip()
proc.wait()
istream.binsha = hex_to_bin(hexsha)
return istream

# { Interface

def partial_to_complete_sha_hex(self, partial_hexsha: str) -> bytes:
Expand Down
16 changes: 15 additions & 1 deletion test/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,30 @@
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/

from io import BytesIO
import os.path as osp
from unittest import mock

from gitdb import IStream
from gitdb.db import LooseObjectDB
from gitdb.typ import str_blob_type

from git.db import GitCmdObjectDB
from git.exc import BadObject
from git.util import bin_to_hex

from test.lib import TestBase
from test.lib import TestBase, with_rw_repo


class TestDB(TestBase):
@with_rw_repo("HEAD")
def test_store_uses_hash_object(self, rw_repo):
data = b"hello world"
with mock.patch.object(LooseObjectDB, "store", side_effect=AssertionError("unexpected loose-object write")):
istream = rw_repo.odb.store(IStream(str_blob_type, len(data), BytesIO(data)))

assert rw_repo.odb.stream(istream.binsha).read() == data

def test_base(self):
gdb = GitCmdObjectDB(osp.join(self.rorepo.git_dir, "objects"), self.rorepo.git)

Expand Down
3 changes: 2 additions & 1 deletion test/test_refs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from git.exc import UnsafeOptionError
from git.objects.tag import TagObject
import git.refs as refs
from git.util import Actor
from git.util import Actor, rmtree

from test.lib import TestBase, requires_symlinks, with_rw_repo, PathLikeMock

Expand All @@ -43,6 +43,7 @@ def _repo_with_initial_commit(self, base_dir):
yield repo
finally:
repo.git.clear_cache()
rmtree(repo_dir)

def test_from_path(self):
# Should be able to create any reference directly.
Expand Down
Loading