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

from _emerge.SubProcess import SubProcess
import sys
from portage.cache.mappings import slot_dict_class
import portage

portage.proxy.lazyimport.lazyimport(
    globals(),
    "portage.package.ebuild._metadata_invalid:eapi_invalid",
)
from portage import os
from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
from portage.dep import extract_unpack_dependencies
from portage.eapi import eapi_has_automatic_unpack_dependencies

import fcntl
import io


class EbuildMetadataPhase(SubProcess):

    """
    Asynchronous interface for the ebuild "depend" phase which is
    used to extract metadata from the ebuild.
    """

    __slots__ = (
        "cpv",
        "eapi_supported",
        "ebuild_hash",
        "fd_pipes",
        "metadata",
        "portdb",
        "repo_path",
        "settings",
        "write_auxdb",
    ) + (
        "_eapi",
        "_eapi_lineno",
        "_raw_metadata",
    )

    _file_names = ("ebuild",)
    _files_dict = slot_dict_class(_file_names, prefix="")

    def _start(self):
        ebuild_path = self.ebuild_hash.location

        with io.open(
            _unicode_encode(ebuild_path, encoding=_encodings["fs"], errors="strict"),
            mode="r",
            encoding=_encodings["repo.content"],
            errors="replace",
        ) as f:
            self._eapi, self._eapi_lineno = portage._parse_eapi_ebuild_head(f)

        parsed_eapi = self._eapi
        if parsed_eapi is None:
            parsed_eapi = "0"

        if not parsed_eapi:
            # An empty EAPI setting is invalid.
            self._eapi_invalid(None)
            self.returncode = 1
            self._async_wait()
            return

        self.eapi_supported = portage.eapi_is_supported(parsed_eapi)
        if not self.eapi_supported:
            self.metadata = {"EAPI": parsed_eapi}
            self.returncode = os.EX_OK
            self._async_wait()
            return

        settings = self.settings
        settings.setcpv(self.cpv)
        settings.configdict["pkg"]["EAPI"] = parsed_eapi

        debug = settings.get("PORTAGE_DEBUG") == "1"
        master_fd = None
        slave_fd = None
        fd_pipes = None
        if self.fd_pipes is not None:
            fd_pipes = self.fd_pipes.copy()
        else:
            fd_pipes = {}

        null_input = open("/dev/null", "rb")
        fd_pipes.setdefault(0, null_input.fileno())
        fd_pipes.setdefault(1, sys.__stdout__.fileno())
        fd_pipes.setdefault(2, sys.__stderr__.fileno())

        # flush any pending output
        stdout_filenos = (sys.__stdout__.fileno(), sys.__stderr__.fileno())
        for fd in fd_pipes.values():
            if fd in stdout_filenos:
                sys.__stdout__.flush()
                sys.__stderr__.flush()
                break

        self._files = self._files_dict()
        files = self._files

        master_fd, slave_fd = os.pipe()

        fcntl.fcntl(
            master_fd,
            fcntl.F_SETFL,
            fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK,
        )

        fd_pipes[slave_fd] = slave_fd
        settings["PORTAGE_PIPE_FD"] = str(slave_fd)

        self._raw_metadata = []
        files.ebuild = master_fd
        self.scheduler.add_reader(files.ebuild, self._output_handler)
        self._registered = True

        retval = portage.doebuild(
            ebuild_path,
            "depend",
            settings=settings,
            debug=debug,
            mydbapi=self.portdb,
            tree="porttree",
            fd_pipes=fd_pipes,
            returnpid=True,
        )
        settings.pop("PORTAGE_PIPE_FD", None)

        os.close(slave_fd)
        null_input.close()

        if isinstance(retval, int):
            # doebuild failed before spawning
            self.returncode = retval
            self._async_wait()
            return

        self.pid = retval[0]

    def _output_handler(self):
        while True:
            buf = self._read_buf(self._files.ebuild)
            if buf is None:
                break  # EAGAIN
            elif buf:
                self._raw_metadata.append(buf)
            else:  # EIO/POLLHUP
                if self.pid is None:
                    self._unregister()
                    self._async_wait()
                else:
                    self._async_waitpid()
                break

    def _unregister(self):
        if self._files is not None:
            self.scheduler.remove_reader(self._files.ebuild)
        SubProcess._unregister(self)

    def _async_waitpid_cb(self, *args, **kwargs):
        """
        Override _async_waitpid_cb to perform cleanup that is
        not necessarily idempotent.
        """
        SubProcess._async_waitpid_cb(self, *args, **kwargs)
        # self._raw_metadata is None when _start returns
        # early due to an unsupported EAPI
        if self.returncode == os.EX_OK and self._raw_metadata is not None:
            metadata_lines = _unicode_decode(
                b"".join(self._raw_metadata),
                encoding=_encodings["repo.content"],
                errors="replace",
            ).splitlines()
            metadata = {}
            metadata_valid = True
            for l in metadata_lines:
                if "=" not in l:
                    metadata_valid = False
                    break
                key, value = l.split("=", 1)
                metadata[key] = value

            if metadata_valid:
                parsed_eapi = self._eapi
                if parsed_eapi is None:
                    parsed_eapi = "0"
                self.eapi_supported = portage.eapi_is_supported(metadata["EAPI"])
                if (not metadata["EAPI"] or self.eapi_supported) and metadata[
                    "EAPI"
                ] != parsed_eapi:
                    self._eapi_invalid(metadata)
                    metadata_valid = False

            if metadata_valid:
                # Since we're supposed to be able to efficiently obtain the
                # EAPI from _parse_eapi_ebuild_head, we don't write cache
                # entries for unsupported EAPIs.
                if self.eapi_supported:

                    if metadata.get("INHERITED", False):
                        metadata[
                            "_eclasses_"
                        ] = self.portdb.repositories.get_repo_for_location(
                            self.repo_path
                        ).eclass_db.get_eclass_data(
                            metadata["INHERITED"].split()
                        )
                    else:
                        metadata["_eclasses_"] = {}
                    metadata.pop("INHERITED", None)

                    if eapi_has_automatic_unpack_dependencies(metadata["EAPI"]):
                        repo = self.portdb.repositories.get_name_for_location(
                            self.repo_path
                        )
                        unpackers = self.settings.unpack_dependencies.get(repo, {}).get(
                            metadata["EAPI"], {}
                        )
                        unpack_dependencies = extract_unpack_dependencies(
                            metadata["SRC_URI"], unpackers
                        )
                        if unpack_dependencies:
                            metadata["DEPEND"] += (
                                " " if metadata["DEPEND"] else ""
                            ) + unpack_dependencies

                    # If called by egencache, this cache write is
                    # undesirable when metadata-transfer is disabled.
                    if self.write_auxdb is not False:
                        self.portdb._write_cache(
                            self.cpv, self.repo_path, metadata, self.ebuild_hash
                        )
                else:
                    metadata = {"EAPI": metadata["EAPI"]}
                self.metadata = metadata
            else:
                self.returncode = 1

    def _eapi_invalid(self, metadata):
        repo_name = self.portdb.getRepositoryName(self.repo_path)
        if metadata is not None:
            eapi_var = metadata["EAPI"]
        else:
            eapi_var = None
        eapi_invalid(
            self,
            self.cpv,
            repo_name,
            self.settings,
            eapi_var,
            self._eapi,
            self._eapi_lineno,
        )
