#!/usr/bin/env python
# Copyright 1998-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

try:
    from setuptools.core import setup, Command
    from setuptools.command.build import build
    from setuptools.command.build_scripts import build_scripts
    from setuptools.command.clean import clean
    from setuptools.command.install import install
    from setuptools.command.install_data import install_data
    from setuptools.command.install_lib import install_lib
    from setuptools.command.install_scripts import install_scripts
    from setuptools.command.sdist import sdist
    from setuptools.dep_util import newer
    from setuptools.dir_util import mkpath, remove_tree
    from setuptools.util import change_root, subst_vars
except ImportError:
    from distutils.core import setup, Command
    from distutils.command.build import build
    from distutils.command.build_scripts import build_scripts
    from distutils.command.clean import clean
    from distutils.command.install import install
    from distutils.command.install_data import install_data
    from distutils.command.install_lib import install_lib
    from distutils.command.install_scripts import install_scripts
    from distutils.command.sdist import sdist
    from distutils.dep_util import newer
    from distutils.dir_util import mkpath, remove_tree
    from distutils.util import change_root, subst_vars

import codecs
import collections
import os
import os.path
import re
import subprocess
import sys

# change the cwd to this one
os.chdir(os.path.dirname(os.path.realpath(__file__)))

# TODO:
# - smarter rebuilds of docs w/ 'install_docbook' and 'install_epydoc'.

x_scripts = {
    "bin": [
        "bin/repoman",
    ],
}


class x_build(build):
    """Build command with extra build_man call."""

    def run(self):
        build.run(self)
        self.run_command("build_man")


class build_man(Command):
    """Perform substitutions in manpages."""

    user_options = []

    def initialize_options(self):
        self.build_base = None

    def finalize_options(self):
        self.set_undefined_options("build", ("build_base", "build_base"))

    def run(self):
        for d, files in self.distribution.data_files:
            if not d.startswith("$mandir/"):
                continue

            for source in files:
                target = os.path.join(self.build_base, source)
                mkpath(os.path.dirname(target))

                if not newer(source, target) and not newer(__file__, target):
                    continue

                print("copying and updating %s -> %s" % (source, target))

                with codecs.open(source, "r", "utf8") as f:
                    data = f.readlines()
                data[0] = data[0].replace("VERSION", self.distribution.get_version())
                with codecs.open(target, "w", "utf8") as f:
                    f.writelines(data)


class x_build_scripts_custom(build_scripts):
    def finalize_options(self):
        build_scripts.finalize_options(self)
        if "dir_name" in dir(self):
            self.build_dir = os.path.join(self.build_dir, self.dir_name)
            if self.dir_name in x_scripts:
                self.scripts = x_scripts[self.dir_name]
            else:
                self.scripts = set(self.scripts)
                for other_files in x_scripts.values():
                    self.scripts.difference_update(other_files)

    def run(self):
        # group scripts by subdirectory
        split_scripts = collections.defaultdict(list)
        for f in self.scripts:
            dir_name = os.path.dirname(f[len("bin/") :])
            split_scripts[dir_name].append(f)

        base_dir = self.build_dir
        base_scripts = self.scripts
        for d, files in split_scripts.items():
            self.build_dir = os.path.join(base_dir, d)
            self.scripts = files
            self.copy_scripts()

        # restore previous values
        self.build_dir = base_dir
        self.scripts = base_scripts


class x_build_scripts_bin(x_build_scripts_custom):
    dir_name = "bin"


class x_build_scripts(build_scripts):
    def initialize_option(self):
        build_scripts.initialize_options(self)

    def finalize_options(self):
        build_scripts.finalize_options(self)

    def run(self):
        self.run_command("build_scripts_bin")


class x_clean(clean):
    """clean extended for doc & post-test cleaning"""

    def clean_tests(self):
        # do not remove incorrect dirs accidentally
        top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
        cprefix = os.path.commonprefix((self.build_base, top_dir))
        if cprefix != self.build_base:
            return

        bin_dir = os.path.join(top_dir, "bin")
        if os.path.exists(bin_dir):
            remove_tree(bin_dir)

        conf_dir = os.path.join(top_dir, "cnf")
        if os.path.islink(conf_dir):
            print("removing %s symlink" % repr(conf_dir))
            os.unlink(conf_dir)

        pni_file = os.path.join(top_dir, ".repoman_not_installed")
        if os.path.exists(pni_file):
            print("removing %s" % repr(pni_file))
            os.unlink(pni_file)

    def clean_man(self):
        man_dir = os.path.join(self.build_base, "man")
        if os.path.exists(man_dir):
            remove_tree(man_dir)

    def run(self):
        if self.all:
            self.clean_tests()
            self.clean_docs()
            self.clean_man()

        clean.run(self)


class x_install(install):
    """install command with extra Portage paths"""

    user_options = install.user_options + [
        # note: $prefix and $exec_prefix are reserved for Python install
        ("system-prefix=", None, "Prefix for architecture-independent data"),
        ("system-exec-prefix=", None, "Prefix for architecture-specific data"),
        ("bindir=", None, "Install directory for main executables"),
        ("datarootdir=", None, "Data install root directory"),
        ("docdir=", None, "Documentation install directory"),
        ("htmldir=", None, "HTML documentation install directory"),
        ("mandir=", None, "Manpage root install directory"),
        ("portage-base=", "b", "Portage install base"),
        (
            "portage-bindir=",
            None,
            "Install directory for Portage internal-use executables",
        ),
        ("portage-datadir=", None, "Install directory for data files"),
        ("sbindir=", None, "Install directory for superuser-intended executables"),
        ("sysconfdir=", None, "System configuration path"),
    ]

    # note: the order is important for proper substitution
    paths = [
        ("system_prefix", "/usr"),
        ("system_exec_prefix", "$system_prefix"),
        ("bindir", "$system_exec_prefix/bin"),
        ("sbindir", "$system_exec_prefix/sbin"),
        ("sysconfdir", "/etc"),
        ("datarootdir", "$system_prefix/share"),
        ("docdir", "$datarootdir/doc/$package-$version"),
        ("htmldir", "$docdir/html"),
        ("mandir", "$datarootdir/man"),
        ("portage_base", "$system_exec_prefix/lib/portage"),
        ("portage_bindir", "$portage_base/bin"),
        ("portage_datadir", "$datarootdir/portage"),
        # not customized at the moment
        ("logrotatedir", "$sysconfdir/logrotate.d"),
        ("portage_confdir", "$portage_datadir/config"),
        ("portage_setsdir", "$portage_confdir/sets"),
    ]

    def initialize_options(self):
        install.initialize_options(self)

        for key, default in self.paths:
            setattr(self, key, default)
        self.subst_paths = {}

    def finalize_options(self):
        install.finalize_options(self)

        # substitute variables
        new_paths = {
            "package": self.distribution.get_name(),
            "version": self.distribution.get_version(),
        }
        for key, _default in self.paths:
            new_paths[key] = subst_vars(getattr(self, key), new_paths)
            setattr(self, key, new_paths[key])
        self.subst_paths = new_paths


class x_install_data(install_data):
    """install_data with customized path support"""

    user_options = install_data.user_options

    def initialize_options(self):
        install_data.initialize_options(self)
        self.build_base = None
        self.paths = None

    def finalize_options(self):
        install_data.finalize_options(self)
        self.set_undefined_options("build", ("build_base", "build_base"))
        self.set_undefined_options("install", ("subst_paths", "paths"))

    def run(self):
        self.run_command("build_man")

        def process_data_files(df):
            for d, files in df:
                # substitute man sources
                if d.startswith("$mandir/"):
                    files = [os.path.join(self.build_base, v) for v in files]

                # substitute variables in path
                d = subst_vars(d, self.paths)
                yield (d, files)

        old_data_files = self.data_files
        self.data_files = process_data_files(self.data_files)

        install_data.run(self)
        self.data_files = old_data_files


class x_install_lib(install_lib):
    """install_lib command with Portage path substitution"""

    user_options = install_lib.user_options

    def initialize_options(self):
        install_lib.initialize_options(self)

    def finalize_options(self):
        install_lib.finalize_options(self)
        self.set_undefined_options(
            "install",
        )

    def install(self):
        ret = install_lib.install(self)

        def rewrite_file(path, val_dict):
            path = os.path.join(self.install_dir, path)
            print("Rewriting %s" % path)
            with codecs.open(path, "r", "utf-8") as f:
                data = f.read()

            for varname, val in val_dict.items():
                regexp = r"(?m)^(%s\s*=).*$" % varname
                repl = r"\1 %s" % repr(val)

                data = re.sub(regexp, repl, data)

            with codecs.open(path, "w", "utf-8") as f:
                f.write(data)

        rewrite_file(
            "repoman/__init__.py",
            {
                "VERSION": self.distribution.get_version(),
            },
        )

        return ret


class x_install_scripts_custom(install_scripts):
    def initialize_options(self):
        install_scripts.initialize_options(self)
        self.root = None

    def finalize_options(self):
        self.set_undefined_options(
            "install", ("root", "root"), (self.var_name, "install_dir")
        )
        install_scripts.finalize_options(self)
        self.build_dir = os.path.join(self.build_dir, self.dir_name)

        # prepend root
        if self.root is not None:
            self.install_dir = change_root(self.root, self.install_dir)


class x_install_scripts_bin(x_install_scripts_custom):
    dir_name = "bin"
    var_name = "bindir"


class x_install_scripts(install_scripts):
    def initialize_option(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        self.run_command("install_scripts_bin")


class x_sdist(sdist):
    """sdist defaulting to .tar.xz format, and archive files owned by root"""

    def initialize_options(self):
        super().initialize_options()
        self.formats = ["xztar"]

    def finalize_options(self):
        if self.owner is None:
            self.owner = "root"
        if self.group is None:
            self.group = "root"

        sdist.finalize_options(self)


class build_tests(x_build_scripts_custom):
    """Prepare build dir for running tests."""

    def initialize_options(self):
        x_build_scripts_custom.initialize_options(self)
        self.build_base = None
        self.build_lib = None

    def finalize_options(self):
        x_build_scripts_custom.finalize_options(self)
        self.set_undefined_options(
            "build", ("build_base", "build_base"), ("build_lib", "build_lib")
        )

        # since we will be writing to $build_lib/.., it is important
        # that we do not leave $build_base
        self.top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
        cprefix = os.path.commonprefix((self.build_base, self.top_dir))
        if cprefix != self.build_base:
            raise SystemError("build_lib must be a subdirectory of build_base")

        self.build_dir = os.path.join(self.top_dir, "bin")

    def run(self):
        self.run_command("build_py")

        # install all scripts $build_lib/../bin
        # (we can't do a symlink since we want shebangs corrected)
        x_build_scripts_custom.run(self)

        # symlink 'cnf' directory
        conf_dir = os.path.join(self.top_dir, "cnf")
        if os.path.exists(conf_dir):
            if not os.path.islink(conf_dir):
                raise SystemError(
                    "%s exists and is not a symlink (collision)" % repr(conf_dir)
                )
            os.unlink(conf_dir)
        conf_src = os.path.relpath("cnf", self.top_dir)
        print("Symlinking %s -> %s" % (conf_dir, conf_src))
        os.symlink(conf_src, conf_dir)

        # create $build_lib/../.repoman_not_installed
        # to enable proper paths in tests
        with open(os.path.join(self.top_dir, ".repoman_not_installed"), "w"):
            pass


class test(Command):
    """run tests"""

    user_options = []

    def initialize_options(self):
        self.build_lib = None

    def finalize_options(self):
        self.set_undefined_options("build", ("build_lib", "build_lib"))

    def run(self):
        self.run_command("build_tests")
        subprocess.check_call(
            [
                sys.executable,
                "-bWd",
                os.path.join(self.build_lib, "repoman/tests/runTests.py"),
            ]
        )


def find_packages():
    for dirpath, _dirnames, filenames in os.walk("lib"):
        if "__init__.py" in filenames:
            yield os.path.relpath(dirpath, "lib")


def find_scripts():
    for dirpath, _dirnames, filenames in os.walk("bin"):
        for f in filenames:
            if f not in ["deprecated-path"]:
                yield os.path.join(dirpath, f)


def get_manpages():
    linguas = os.environ.get("LINGUAS")
    if linguas is not None:
        linguas = linguas.split()

    for dirpath, _dirnames, filenames in os.walk("man"):
        groups = collections.defaultdict(list)
        for f in filenames:
            _fn, suffix = f.rsplit(".", 1)
            groups[suffix].append(os.path.join(dirpath, f))

        topdir = dirpath[len("man/") :]
        if not topdir or linguas is None or topdir in linguas:
            for g, mans in groups.items():
                yield [os.path.join("$mandir", topdir, "man%s" % g), mans]


setup(
    name="repoman",
    version="3.0.3",
    url="https://wiki.gentoo.org/wiki/Project:Portage",
    author="Gentoo Portage Development Team",
    author_email="dev-portage@gentoo.org",
    package_dir={"": "lib"},
    packages=list(find_packages()),
    # something to cheat build & install commands
    scripts=list(find_scripts()),
    data_files=list(get_manpages())
    + [
        ["$docdir", ["NEWS", "RELEASE-NOTES"]],
        ["share/repoman/qa_data", ["cnf/qa_data/qa_data.yaml"]],
        ["share/repoman/linechecks", ["cnf/linechecks/linechecks.yaml"]],
        [
            "share/repoman/repository",
            [
                "cnf/repository/linechecks.yaml",
                "cnf/repository/qa_data.yaml",
                "cnf/repository/repository.yaml",
            ],
        ],
    ],
    cmdclass={
        "build": x_build,
        "build_man": build_man,
        "build_scripts": x_build_scripts,
        "build_scripts_bin": x_build_scripts_bin,
        "build_tests": build_tests,
        "clean": x_clean,
        "install": x_install,
        "install_data": x_install_data,
        "install_lib": x_install_lib,
        "install_scripts": x_install_scripts,
        "install_scripts_bin": x_install_scripts_bin,
        "sdist": x_sdist,
        "test": test,
    },
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Environment :: Console",
        "Intended Audience :: System Administrators",
        "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
        "Operating System :: POSIX",
        "Programming Language :: Python :: 3",
        "Topic :: System :: Installation/Setup",
    ],
)
