# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

import functools
import _emerge.emergelog
from _emerge.EbuildPhase import EbuildPhase
from _emerge.BinpkgFetcher import BinpkgFetcher
from _emerge.BinpkgEnvExtractor import BinpkgEnvExtractor
from _emerge.CompositeTask import CompositeTask
from _emerge.BinpkgVerifier import BinpkgVerifier
from _emerge.EbuildMerge import EbuildMerge
from _emerge.EbuildBuildDir import EbuildBuildDir
from _emerge.SpawnProcess import SpawnProcess
from portage.eapi import eapi_exports_replace_vars
from portage.exception import PortageException
from portage.output import colorize
from portage.util import ensure_dirs
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
from portage.util._dyn_libs.dyn_libs import check_dyn_libs_inconsistent
import portage
from portage import os
from portage import shutil
from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
import io
import logging


class Binpkg(CompositeTask):

    __slots__ = (
        "find_blockers",
        "ldpath_mtimes",
        "logger",
        "opts",
        "pkg",
        "pkg_count",
        "prefetcher",
        "settings",
        "world_atom",
    ) + (
        "_bintree",
        "_build_dir",
        "_build_prefix",
        "_ebuild_path",
        "_fetched_pkg",
        "_image_dir",
        "_infloc",
        "_pkg_path",
        "_tree",
        "_verify",
    )

    def _writemsg_level(self, msg, level=0, noiselevel=0):
        self.scheduler.output(
            msg,
            level=level,
            noiselevel=noiselevel,
            log_path=self.settings.get("PORTAGE_LOG_FILE"),
        )

    def _start(self):

        pkg = self.pkg
        settings = self.settings
        settings.setcpv(pkg)
        self._tree = "bintree"
        self._bintree = self.pkg.root_config.trees[self._tree]
        self._verify = not self.opts.pretend

        # Use realpath like doebuild_environment() does, since we assert
        # that this path is literally identical to PORTAGE_BUILDDIR.
        dir_path = os.path.join(
            os.path.realpath(settings["PORTAGE_TMPDIR"]),
            "portage",
            pkg.category,
            pkg.pf,
        )
        self._image_dir = os.path.join(dir_path, "image")
        self._infloc = os.path.join(dir_path, "build-info")
        self._ebuild_path = os.path.join(self._infloc, pkg.pf + ".ebuild")
        settings["EBUILD"] = self._ebuild_path
        portage.doebuild_environment(
            self._ebuild_path, "setup", settings=self.settings, db=self._bintree.dbapi
        )
        if dir_path != self.settings["PORTAGE_BUILDDIR"]:
            raise AssertionError(
                "'%s' != '%s'" % (dir_path, self.settings["PORTAGE_BUILDDIR"])
            )
        self._build_dir = EbuildBuildDir(scheduler=self.scheduler, settings=settings)
        settings.configdict["pkg"]["EMERGE_FROM"] = "binary"
        settings.configdict["pkg"]["MERGE_TYPE"] = "binary"

        if eapi_exports_replace_vars(settings["EAPI"]):
            vardb = self.pkg.root_config.trees["vartree"].dbapi
            settings["REPLACING_VERSIONS"] = " ".join(
                set(
                    portage.versions.cpv_getversion(x)
                    for x in vardb.match(self.pkg.slot_atom)
                    + vardb.match("=" + self.pkg.cpv)
                )
            )

        # The prefetcher has already completed or it
        # could be running now. If it's running now,
        # wait for it to complete since it holds
        # a lock on the file being fetched. The
        # portage.locks functions are only designed
        # to work between separate processes. Since
        # the lock is held by the current process,
        # use the scheduler and fetcher methods to
        # synchronize with the fetcher.
        prefetcher = self.prefetcher
        if prefetcher is None:
            pass
        elif prefetcher.isAlive() and prefetcher.poll() is None:

            if not self.background:
                fetch_log = os.path.join(
                    _emerge.emergelog._emerge_log_dir, "emerge-fetch.log"
                )
                msg = (
                    "Fetching in the background:",
                    prefetcher.pkg_path,
                    "To view fetch progress, run in another terminal:",
                    "tail -f %s" % fetch_log,
                )
                out = portage.output.EOutput()
                for l in msg:
                    out.einfo(l)

            self._current_task = prefetcher
            prefetcher.addExitListener(self._prefetch_exit)
            return

        self._prefetch_exit(prefetcher)

    def _prefetch_exit(self, prefetcher):

        if self._was_cancelled():
            self.wait()
            return

        if not (self.opts.pretend or self.opts.fetchonly):
            self._start_task(
                AsyncTaskFuture(future=self._build_dir.async_lock()),
                self._start_fetcher,
            )
        else:
            self._start_fetcher()

    def _start_fetcher(self, lock_task=None):
        if lock_task is not None:
            self._assert_current(lock_task)
            if lock_task.cancelled:
                self._default_final_exit(lock_task)
                return

            lock_task.future.result()
            # Initialize PORTAGE_LOG_FILE (clean_log won't work without it).
            portage.prepare_build_dirs(self.settings["ROOT"], self.settings, 1)
            # If necessary, discard old log so that we don't
            # append to it.
            self._build_dir.clean_log()

        pkg = self.pkg
        pkg_count = self.pkg_count
        fetcher = None

        if self.opts.getbinpkg and self._bintree.isremote(pkg.cpv):

            fetcher = BinpkgFetcher(
                background=self.background,
                logfile=self.settings.get("PORTAGE_LOG_FILE"),
                pkg=self.pkg,
                pretend=self.opts.pretend,
                scheduler=self.scheduler,
            )

            msg = " --- (%s of %s) Fetching Binary (%s::%s)" % (
                pkg_count.curval,
                pkg_count.maxval,
                pkg.cpv,
                fetcher.pkg_path,
            )
            short_msg = "emerge: (%s of %s) %s Fetch" % (
                pkg_count.curval,
                pkg_count.maxval,
                pkg.cpv,
            )
            self.logger.log(msg, short_msg=short_msg)

            # Allow the Scheduler's fetch queue to control the
            # number of concurrent fetchers.
            fetcher.addExitListener(self._fetcher_exit)
            self._task_queued(fetcher)
            self.scheduler.fetch.schedule(fetcher)
            return

        self._fetcher_exit(fetcher)

    def _fetcher_exit(self, fetcher):

        # The fetcher only has a returncode when
        # --getbinpkg is enabled.
        if fetcher is not None:
            self._fetched_pkg = fetcher.pkg_path
            if self._default_exit(fetcher) != os.EX_OK:
                self._async_unlock_builddir(returncode=self.returncode)
                return

        if self.opts.pretend:
            self._current_task = None
            self.returncode = os.EX_OK
            self.wait()
            return

        verifier = None
        if self._verify:
            if self._fetched_pkg:
                path = self._fetched_pkg
            else:
                path = self.pkg.root_config.trees["bintree"].getname(self.pkg.cpv)
            logfile = self.settings.get("PORTAGE_LOG_FILE")
            verifier = BinpkgVerifier(
                background=self.background,
                logfile=logfile,
                pkg=self.pkg,
                scheduler=self.scheduler,
                _pkg_path=path,
            )
            self._start_task(verifier, self._verifier_exit)
            return

        self._verifier_exit(verifier)

    def _verifier_exit(self, verifier):
        if verifier is not None and self._default_exit(verifier) != os.EX_OK:
            self._async_unlock_builddir(returncode=self.returncode)
            return

        logger = self.logger
        pkg = self.pkg
        pkg_count = self.pkg_count

        if self._fetched_pkg:
            pkg_path = self._bintree.getname(
                self._bintree.inject(pkg.cpv, current_pkg_path=self._fetched_pkg),
                allocate_new=False,
            )
        else:
            pkg_path = self.pkg.root_config.trees["bintree"].getname(self.pkg.cpv)

        # This gives bashrc users an opportunity to do various things
        # such as remove binary packages after they're installed.
        if pkg_path is not None:
            self.settings["PORTAGE_BINPKG_FILE"] = pkg_path
        self._pkg_path = pkg_path

        logfile = self.settings.get("PORTAGE_LOG_FILE")
        if logfile is not None and os.path.isfile(logfile):
            # Remove fetch log after successful fetch.
            try:
                os.unlink(logfile)
            except OSError:
                pass

        if self.opts.fetchonly:
            self._current_task = None
            self.returncode = os.EX_OK
            self.wait()
            return

        msg = " === (%s of %s) Merging Binary (%s::%s)" % (
            pkg_count.curval,
            pkg_count.maxval,
            pkg.cpv,
            pkg_path,
        )
        short_msg = "emerge: (%s of %s) %s Merge Binary" % (
            pkg_count.curval,
            pkg_count.maxval,
            pkg.cpv,
        )
        logger.log(msg, short_msg=short_msg)

        phase = "clean"
        settings = self.settings
        ebuild_phase = EbuildPhase(
            background=self.background,
            phase=phase,
            scheduler=self.scheduler,
            settings=settings,
        )

        self._start_task(ebuild_phase, self._clean_exit)

    def _clean_exit(self, clean_phase):
        if self._default_exit(clean_phase) != os.EX_OK:
            self._async_unlock_builddir(returncode=self.returncode)
            return

        self._start_task(
            AsyncTaskFuture(future=self._unpack_metadata(loop=self.scheduler)),
            self._unpack_metadata_exit,
        )

    async def _unpack_metadata(self, loop=None):

        dir_path = self.settings["PORTAGE_BUILDDIR"]

        infloc = self._infloc
        pkg = self.pkg
        pkg_path = self._pkg_path

        dir_mode = 0o755
        for mydir in (dir_path, self._image_dir, infloc):
            portage.util.ensure_dirs(
                mydir,
                uid=portage.data.portage_uid,
                gid=portage.data.portage_gid,
                mode=dir_mode,
            )

        # This initializes PORTAGE_LOG_FILE.
        portage.prepare_build_dirs(self.settings["ROOT"], self.settings, 1)
        self._writemsg_level(">>> Extracting info\n")

        await self._bintree.dbapi.unpack_metadata(
            self.settings, infloc, loop=self.scheduler
        )
        check_missing_metadata = ("CATEGORY", "PF")
        for k, v in zip(
            check_missing_metadata,
            self._bintree.dbapi.aux_get(self.pkg.cpv, check_missing_metadata),
        ):
            if v:
                continue
            elif k == "CATEGORY":
                v = pkg.category
            elif k == "PF":
                v = pkg.pf
            else:
                continue

            f = io.open(
                _unicode_encode(
                    os.path.join(infloc, k), encoding=_encodings["fs"], errors="strict"
                ),
                mode="w",
                encoding=_encodings["content"],
                errors="backslashreplace",
            )
            try:
                f.write(_unicode_decode(v + "\n"))
            finally:
                f.close()

        # Store the md5sum in the vdb.
        if pkg_path is not None:
            (md5sum,) = self._bintree.dbapi.aux_get(self.pkg.cpv, ["MD5"])
            if not md5sum:
                md5sum = portage.checksum.perform_md5(pkg_path)
            with io.open(
                _unicode_encode(
                    os.path.join(infloc, "BINPKGMD5"),
                    encoding=_encodings["fs"],
                    errors="strict",
                ),
                mode="w",
                encoding=_encodings["content"],
                errors="strict",
            ) as f:
                f.write(_unicode_decode("{}\n".format(md5sum)))

        env_extractor = BinpkgEnvExtractor(
            background=self.background, scheduler=self.scheduler, settings=self.settings
        )
        env_extractor.start()
        await env_extractor.async_wait()
        if env_extractor.returncode != os.EX_OK:
            raise portage.exception.PortageException(
                "failed to extract environment for {}".format(self.pkg.cpv)
            )

    def _unpack_metadata_exit(self, unpack_metadata):
        if self._default_exit(unpack_metadata) != os.EX_OK:
            unpack_metadata.future.result()
            self._async_unlock_builddir(returncode=self.returncode)
            return

        setup_phase = EbuildPhase(
            background=self.background,
            phase="setup",
            scheduler=self.scheduler,
            settings=self.settings,
        )

        setup_phase.addExitListener(self._setup_exit)
        self._task_queued(setup_phase)
        self.scheduler.scheduleSetup(setup_phase)

    def _setup_exit(self, setup_phase):
        if self._default_exit(setup_phase) != os.EX_OK:
            self._async_unlock_builddir(returncode=self.returncode)
            return

        self._writemsg_level(">>> Extracting %s\n" % self.pkg.cpv)
        self._start_task(
            AsyncTaskFuture(
                future=self._bintree.dbapi.unpack_contents(
                    self.settings, self._image_dir, loop=self.scheduler
                )
            ),
            self._unpack_contents_exit,
        )

    def _unpack_contents_exit(self, unpack_contents):
        if self._default_exit(unpack_contents) != os.EX_OK:
            try:
                unpack_contents.future.result()
                err = ""
            except PortageException as e:
                err = e

            self._writemsg_level(
                colorize(
                    "BAD",
                    f"!!! Error Extracting '{self._pkg_path}', {err}\n",
                ),
                noiselevel=-1,
                level=logging.ERROR,
            )
            self._async_unlock_builddir(returncode=self.returncode)
            return

        # Before anything else, let's do an integrity check.
        (provides,) = self._bintree.dbapi.aux_get(self.pkg.cpv, ["PROVIDES"])
        if check_dyn_libs_inconsistent(self.settings["D"], provides):
            self._writemsg_level(
                colorize(
                    "BAD",
                    "!!! Error! Installing dynamic libraries (.so) with blank PROVIDES!",
                ),
                noiselevel=-1,
                level=logging.ERROR,
            )

        try:
            with io.open(
                _unicode_encode(
                    os.path.join(self._infloc, "EPREFIX"),
                    encoding=_encodings["fs"],
                    errors="strict",
                ),
                mode="r",
                encoding=_encodings["repo.content"],
                errors="replace",
            ) as f:
                self._build_prefix = f.read().rstrip("\n")
        except IOError:
            self._build_prefix = ""

        if self._build_prefix == self.settings["EPREFIX"]:
            ensure_dirs(self.settings["ED"])
            self._current_task = None
            self.returncode = os.EX_OK
            self.wait()
            return

        env = self.settings.environ()
        env["PYTHONPATH"] = self.settings["PORTAGE_PYTHONPATH"]
        chpathtool = SpawnProcess(
            args=[
                portage._python_interpreter,
                os.path.join(self.settings["PORTAGE_BIN_PATH"], "chpathtool.py"),
                self.settings["D"],
                self._build_prefix,
                self.settings["EPREFIX"],
            ],
            background=self.background,
            env=env,
            scheduler=self.scheduler,
            logfile=self.settings.get("PORTAGE_LOG_FILE"),
        )
        self._writemsg_level(">>> Adjusting Prefix to %s\n" % self.settings["EPREFIX"])
        self._start_task(chpathtool, self._chpathtool_exit)

    def _chpathtool_exit(self, chpathtool):
        if self._final_exit(chpathtool) != os.EX_OK:
            self._writemsg_level(
                "!!! Error Adjusting Prefix to %s\n" % (self.settings["EPREFIX"],),
                noiselevel=-1,
                level=logging.ERROR,
            )
            self._async_unlock_builddir(returncode=self.returncode)
            return

        # We want to install in "our" prefix, not the binary one
        with io.open(
            _unicode_encode(
                os.path.join(self._infloc, "EPREFIX"),
                encoding=_encodings["fs"],
                errors="strict",
            ),
            mode="w",
            encoding=_encodings["repo.content"],
            errors="strict",
        ) as f:
            f.write(self.settings["EPREFIX"] + "\n")

        # Move the files to the correct location for merge.
        image_tmp_dir = os.path.join(self.settings["PORTAGE_BUILDDIR"], "image_tmp")
        build_d = os.path.join(
            self.settings["D"], self._build_prefix.lstrip(os.sep)
        ).rstrip(os.sep)
        if not os.path.isdir(build_d):
            # Assume this is a virtual package or something.
            shutil.rmtree(self._image_dir)
            ensure_dirs(self.settings["ED"])
        else:
            os.rename(build_d, image_tmp_dir)
            if build_d != self._image_dir:
                shutil.rmtree(self._image_dir)
            ensure_dirs(os.path.dirname(self.settings["ED"].rstrip(os.sep)))
            os.rename(image_tmp_dir, self.settings["ED"])

        self.wait()

    def _async_unlock_builddir(self, returncode=None):
        """
        Release the lock asynchronously, and if a returncode parameter
        is given then set self.returncode and notify exit listeners.
        """
        if self.opts.pretend or self.opts.fetchonly:
            if returncode is not None:
                self.returncode = returncode
                self._async_wait()
            return
        if returncode is not None:
            # The returncode will be set after unlock is complete.
            self.returncode = None
        portage.elog.elog_process(self.pkg.cpv, self.settings)
        self._start_task(
            AsyncTaskFuture(future=self._build_dir.async_unlock()),
            functools.partial(self._unlock_builddir_exit, returncode=returncode),
        )

    def _unlock_builddir_exit(self, unlock_task, returncode=None):
        self._assert_current(unlock_task)
        if unlock_task.cancelled and returncode is not None:
            self._default_final_exit(unlock_task)
            return

        # Normally, async_unlock should not raise an exception here.
        unlock_task.future.cancelled() or unlock_task.future.result()
        if returncode is not None:
            self.returncode = returncode
            self._async_wait()

    def create_install_task(self):
        task = EbuildMerge(
            exit_hook=self._install_exit,
            find_blockers=self.find_blockers,
            ldpath_mtimes=self.ldpath_mtimes,
            logger=self.logger,
            pkg=self.pkg,
            pkg_count=self.pkg_count,
            pkg_path=self._pkg_path,
            scheduler=self.scheduler,
            settings=self.settings,
            tree=self._tree,
            world_atom=self.world_atom,
        )
        return task

    def _install_exit(self, task):
        """
        @returns: Future, result is the returncode from an
                EbuildBuildDir.async_unlock() task
        """
        self.settings.pop("PORTAGE_BINPKG_FILE", None)
        if (
            task.returncode == os.EX_OK
            and "binpkg-logs" not in self.settings.features
            and self.settings.get("PORTAGE_LOG_FILE")
        ):
            try:
                os.unlink(self.settings["PORTAGE_LOG_FILE"])
            except OSError:
                pass
        self._async_unlock_builddir()
        if self._current_task is None:
            result = self.scheduler.create_future()
            self.scheduler.call_soon(result.set_result, os.EX_OK)
        else:
            result = self._current_task.async_wait()
        return result
