# Copyright 2010-2019 The pygit2 contributors
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# In addition to the permissions in the GNU General Public License,
# the authors give you unlimited permission to link the compiled
# version of this file into combinations with other programs,
# and to distribute those combinations without any restriction
# coming from the use of this file.  (The General Public License
# restrictions do apply in other respects; for example, they cover
# modification of the file, and distribution when not linked into
# a combined executable.)
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

"""Tests for Odb objects."""

# Import from the Standard Library
import binascii
import gc
import os
import unittest

import pytest

# Import from pygit2
from pygit2 import Odb, OdbBackendPack, OdbBackendLoose, Oid
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB

from . import utils


BLOB_HEX = 'af431f20fc541ed6d5afede3e2dc7160f6f01f16'
BLOB_RAW = binascii.unhexlify(BLOB_HEX.encode('ascii'))
BLOB_OID = Oid(raw=BLOB_RAW)

class EmptyOdbTest(unittest.TestCase):
    def setUp(self):
        self.odb = Odb()

    def test_iterable(self):
        assert len([str(o) for o in self.odb]) == 0

    def test_contains(self):
        assert BLOB_HEX not in self.odb

    def test_add_disk_alternate(self):
        assert BLOB_HEX not in self.odb
        path = os.path.join(os.path.dirname(__file__),
                'data', 'testrepo.git', 'objects')
        self.odb.add_disk_alternate(path)
        assert BLOB_HEX in self.odb

class OdbTest(utils.BareRepoTestCase):

    def setUp(self):
        super().setUp()
        self.odb = self.repo.odb

    def tearDown(self):
        del self.odb
        gc.collect()
        super().tearDown()

    def test_iterable(self):
        assert BLOB_HEX in [str(o) for o in self.odb]

    def test_contains(self):
        assert BLOB_HEX in self.odb

    def test_read(self):
        with pytest.raises(TypeError): self.odb.read(123)
        self.assertRaisesWithArg(KeyError, '1' * 40, self.odb.read, '1' * 40)

        ab = self.odb.read(BLOB_OID)
        a = self.odb.read(BLOB_HEX)
        assert ab == a
        assert (GIT_OBJ_BLOB, b'a contents\n') == a

        a2 = self.odb.read('7f129fd57e31e935c6d60a0c794efe4e6927664b')
        assert (GIT_OBJ_BLOB, b'a contents 2\n') == a2

        a_hex_prefix = BLOB_HEX[:4]
        a3 = self.odb.read(a_hex_prefix)
        assert (GIT_OBJ_BLOB, b'a contents\n') == a3

    def test_write(self):
        data = b"hello world"
        # invalid object type
        with pytest.raises(ValueError): self.odb.write(GIT_OBJ_ANY, data)

        oid = self.odb.write(GIT_OBJ_BLOB, data)
        assert type(oid) == Oid


class OdbBackendTest(utils.BareRepoTestCase):

    def setUp(self):
        super().setUp()
        self.ref_odb = self.repo.odb
        self.obj_path = os.path.join(os.path.dirname(__file__),
                'data', 'testrepo.git', 'objects')

    def tearDown(self):
        del self.ref_odb
        gc.collect()
        super().tearDown()

    def test_pack(self):
        pack = OdbBackendPack(self.obj_path)
        assert len(list(pack)) > 0
        for obj in pack:
            assert obj in self.ref_odb

    def test_loose(self):
        pack = OdbBackendLoose(self.obj_path, 5, False)
        assert len(list(pack)) > 0
        for obj in pack:
            assert obj in self.ref_odb
