# vim: set fileencoding=utf-8 :

"""Test submodule L{GitRepository} submodule methods"""

from . import context

import os
import shutil
import tarfile

import gbp.log
import gbp.git
import gbp.command_wrappers

from gbp.deb.policy import DebianPkgPolicy as Policy
from gbp.deb.git import DebianGitRepository
from gbp.pkg import Compressor

from gbp.scripts import buildpackage
from tests.testutils import ls_zip

REPO = None
REPODIR = None

SUBMODULES = []
SUBMODULE_NAMES = ["test_submodule", "sub module"]
TMPDIR = None
TESTFILE_NAME = "testfile"
TESTDIR_NAME = "testdir"


class Submodule(object):
    """Class representing remote repo for Git submodule"""
    def __init__(self, name, tmpdir):
        self.name = name
        self.dir = os.path.join(tmpdir, name)
        self.repo = gbp.git.GitRepository.create(self.dir)


def setup():
    """Test module setup"""
    global REPO, REPODIR, SUBMODULES, TMPDIR

    TMPDIR = context.new_tmpdir(__name__)
    REPODIR = TMPDIR.join('test_repo')
    REPO = DebianGitRepository.create(REPODIR)

    os.environ['GIT_ALLOW_PROTOCOL'] = 'file'
    for name in SUBMODULE_NAMES:
        SUBMODULES.append(Submodule(name, str(TMPDIR)))

    context.chdir(REPODIR)


def teardown():
    """Test module teardown"""

    context.teardown()
    del os.environ['GIT_ALLOW_PROTOCOL']


def test_empty_has_submodules():
    """Test empty repo for submodules"""
    assert not REPO.has_submodules()


def _add_dummy_data(repo, msg):
    """Commit dummy data to a Git repository"""
    shutil.copy(".git/HEAD", TESTFILE_NAME)
    os.mkdir(TESTDIR_NAME)
    shutil.copy(TESTFILE_NAME, os.path.join(TESTDIR_NAME, TESTFILE_NAME))
    repo.add_files('.', force=True)
    repo.commit_all(msg)


def test_add_files():
    """Add some dummy data"""
    _add_dummy_data(REPO, "initial commit")
    assert True


def test_add_submodule_files():
    """Add some dummy data"""
    for submodule in SUBMODULES:
        os.chdir(submodule.dir)
        _add_dummy_data(submodule.repo, "initial commit in submodule")
        os.chdir(REPODIR)
    assert True


def test_add_submodule():
    """Add a submodule"""
    REPO.add_submodule(SUBMODULES[0].dir)
    REPO.commit_all(msg='Added submodule %s' % SUBMODULES[0].dir)


def test_has_submodules():
    """Check for submodules"""
    assert REPO.has_submodules()
    assert REPO.has_submodules("HEAD")
    assert not REPO.has_submodules("HEAD^")


def test_get_submodules():
    """Check for submodules list of  (name, hash)"""
    modules = REPO.get_submodules("master")[0]
    assert modules[0] == "test_submodule"
    assert len(modules[1]) == 40


def test_dump_tree():
    """Dump the repository and check if files exist"""
    dumpdir = TMPDIR.join("dump")
    os.mkdir(dumpdir)
    assert buildpackage.dump_tree(REPO, dumpdir, "master", True)
    assert os.path.exists(os.path.join(dumpdir, TESTFILE_NAME))
    assert os.path.exists(os.path.join(dumpdir, TESTDIR_NAME, TESTFILE_NAME))
    assert os.path.exists(os.path.join(dumpdir, SUBMODULES[0].name, TESTFILE_NAME))
    # No submodules or subdirs if recursive is False
    dumpdir = TMPDIR.join("dump2")
    os.mkdir(dumpdir)
    assert buildpackage.dump_tree(REPO, dumpdir, "master", True, False)
    assert os.path.exists(os.path.join(dumpdir, TESTFILE_NAME))
    assert not os.path.exists(os.path.join(dumpdir, TESTDIR_NAME))
    assert not os.path.exists(os.path.join(dumpdir, SUBMODULES[0].name))


def test_create_tarballs():
    """Create an upstream tarball"""
    class MockedSource:
        def __init__(self, version):
            self.name = 'test'
            self.upstream_version = version

        def upstream_tarball_name(self, compression, component=None):
            return Policy.build_tarball_name(self.name,
                                             self.upstream_version,
                                             compression=compression)

    comp = Compressor('bzip2')
    # Tarball with submodules
    s = MockedSource("0.1")
    assert REPO.create_upstream_tarball_via_git_archive(
        s, str(TMPDIR), "HEAD", comp, with_submodules=True
    )
    # Tarball without submodules
    s = MockedSource("0.2")
    assert REPO.create_upstream_tarball_via_git_archive(
        s, str(TMPDIR), "HEAD", comp, with_submodules=False
    )


def test_create_zip_archives():
    """Create an upstream zip archive"""
    REPO.archive_comp('HEAD', 'with-submodules.zip', 'test',
                      None, format='zip', submodules=True)
    # Check that submodules were included
    contents = ls_zip("with-submodules.zip")
    assert "test/test_submodule/testfile" in contents

    REPO.archive_comp(
        "HEAD", "without-submodules.zip", "test", None, format="zip", submodules=False
    )
    contents = ls_zip("without-submodules.zip")
    assert "test/test_submodule/testfile" not in contents


def test_check_tarfiles():
    """Check the contents of the created tarfile"""
    # Check tarball with submodules
    tarobj = tarfile.open(TMPDIR.join("test_0.1.orig.tar.bz2"), 'r:*')
    files = tarobj.getmembers()
    assert "test-0.1/.gitmodules" in [f.name for f in files]
    assert len(files) == 10
    # Check tarball without submodules
    tarobj = tarfile.open(TMPDIR.join("test_0.2.orig.tar.bz2"), 'r:*')
    files = tarobj.getmembers()
    assert ("test-0.2/%s" % TESTFILE_NAME) in [f.name for f in files]
    assert len(files) == 6


def test_add_whitespace_submodule():
    """Add a second submodule with name containing whitespace"""
    REPO.add_submodule(SUBMODULES[1].dir)
    REPO.commit_all(msg='Added submodule %s' % SUBMODULES[0].dir)


def test_get_more_submodules():
    """Check for submodules list of  (name, hash)"""
    module = REPO.get_submodules("master")
    assert len(module) == len(SUBMODULE_NAMES)
    for module in REPO.get_submodules("master"):
        assert len(module[1]) == 40
        assert os.path.basename(module[0]) in SUBMODULE_NAMES


# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
