#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
#        Tiago Gomes <tiago.gomes@codethink.co.uk>

from typing import TYPE_CHECKING, Optional, Dict, Union, List, Sequence

import os
import urllib.parse
from pathlib import Path
from pluginbase import PluginBase
from . import utils
from . import _site
from . import _yaml
from ._variables import Variables
from .utils import UtilError
from ._profile import Topics, PROFILER
from ._exceptions import LoadError
from .exceptions import LoadErrorReason
from ._options import OptionPool
from .node import ScalarNode, MappingNode, ProvenanceInformation, _assert_symbol_name
from ._pluginfactory import ElementFactory, SourceFactory, SourceMirrorFactory, load_plugin_origin
from .types import CoreWarnings, _HostMount, _SourceUriPolicy
from ._projectrefs import ProjectRefs, ProjectRefStorage
from ._loader import Loader, LoadContext
from .element import Element
from ._includes import Includes
from ._workspaces import WORKSPACE_PROJECT_FILE
from ._remotespec import RemoteSpec
from .sourcemirror import SourceMirror
from .source import AliasSubstitution, SourceError


if TYPE_CHECKING:
    from ._context import Context
    from .plugins.elements.junction import JunctionElement


# Project Configuration file
_PROJECT_CONF_FILE = "project.conf"


# Represents project configuration that can have different values for junctions.
class ProjectConfig:
    def __init__(self):
        self.options = None  # OptionPool
        self.base_variables = {}  # The base set of variables
        self.element_overrides = {}  # Element specific configurations
        self.source_overrides = {}  # Source specific configurations
        self.mirrors = {}  # Dictionary of SourceMirror objects
        self.default_mirror = None  # The name of the preferred mirror.
        self._aliases = None  # Aliases dictionary


# Project()
#
# The Project Configuration
#
# Args:
#    directory: The project directory, or None for dummy ArtifactProjects
#    context: The invocation context
#    junction: The junction Element causing this project to be loaded
#    cli_options: The project options specified on the command line
#    default_mirror: The default mirror specified on the command line
#    parent_loader: The parent loader
#    provenance_node: The YAML provenance causing this project to be loaded
#    search_for_project: Whether to search for a project directory, e.g. from workspace metadata or parent directories
#
class Project:
    def __init__(
        self,
        directory: Optional[str],
        context: "Context",
        *,
        junction: Optional["JunctionElement"] = None,
        cli_options: Optional[Dict[str, str]] = None,
        default_mirror: Optional[str] = None,
        parent_loader: Optional[Loader] = None,
        provenance_node: Optional[ProvenanceInformation] = None,
        search_for_project: bool = True,
    ):
        #
        # Public members
        #
        self.name: str = ""  # The project name
        self.directory: Optional[str] = directory  # The project directory
        self.element_path: Optional[str] = None  # The project relative element path

        self.load_context: LoadContext  # The LoadContext
        self.loader: Optional[Loader] = None  # The loader associated to this project
        self.junction: Optional["JunctionElement"] = junction  # The junction Element object, if this is a subproject

        self.ref_storage: Optional[ProjectRefStorage] = None  # Where to store source refs
        self.refs: Optional[ProjectRefs] = None
        self.junction_refs: Optional[ProjectRefs] = None
        self.disallow_subproject_uris: bool = False

        self.config: ProjectConfig = ProjectConfig()
        self.first_pass_config: ProjectConfig = ProjectConfig()

        self.base_environment: Union[MappingNode, Dict[str, str]] = {}  # The base set of environment variables
        self.base_env_nocache: List[str] = []  # The base nocache mask (list) for the environment

        # Remote specs for communicating with remote services
        self.artifact_cache_specs: List[RemoteSpec] = []  # Artifact caches
        self.source_cache_specs: List[RemoteSpec] = []  # Source caches

        self.element_factory: Optional[ElementFactory] = None  # ElementFactory for loading elements
        self.source_factory: Optional[SourceFactory] = None  # SourceFactory for loading sources
        self.source_mirror_factory: Optional[SourceMirrorFactory] = None  # SourceMirrorFactory

        self.sandbox: Optional[MappingNode] = None
        self.splits: Optional[MappingNode] = None

        #
        # Private members
        #
        self._context: "Context" = context  # The invocation Context
        self._invoked_from_workspace_element: Optional[str] = None
        self._absolute_directory_path: Optional[Path] = None

        self._default_targets: Optional[List[str]] = None  # Default target elements
        self._default_mirror: Optional[str] = default_mirror  # The name of the preferred mirror.
        self._cli_options: Optional[Dict[str, str]] = cli_options

        self._fatal_warnings: List[str] = []  # A list of warnings which should trigger an error
        self._shell_command: List[str] = []  # The default interactive shell command
        self._shell_environment: Dict[str, str] = {}  # Statically set environment vars
        self._shell_host_files: List[_HostMount] = []  # A list of HostMount objects
        self._mirror_override: bool = False  # Whether mirrors have been declared in user configuration

        # This is a lookup table of lists indexed by project,
        # the child dictionaries are lists of ScalarNodes indicating
        # junction names
        self._junction_duplicates: Dict[str, List[str]] = {}

        # A list of project relative junctions to consider as 'internal',
        # stored as ScalarNodes.
        self._junction_internal: List[str] = []

        self._partially_loaded: bool = False
        self._fully_loaded: bool = False
        self._project_includes: Optional[Includes] = None

        #
        # Initialization body
        #
        if parent_loader:
            self.load_context = parent_loader.load_context
        else:
            self.load_context = LoadContext(self._context)

        if search_for_project:
            self.directory, self._invoked_from_workspace_element = self._find_project_dir(directory)

        if self.directory:
            self._absolute_directory_path = Path(self.directory).resolve()
            self.refs = ProjectRefs(self.directory, "project.refs")
            self.junction_refs = ProjectRefs(self.directory, "junction.refs")

        self._context.add_project(self)

        if self.directory:
            with PROFILER.profile(Topics.LOAD_PROJECT, self.directory.replace(os.sep, "-")):
                self._load(parent_loader=parent_loader, provenance_node=provenance_node)
        else:
            self._fully_loaded = True

        self._partially_loaded = True

    @property
    def options(self):
        return self.config.options

    @property
    def base_variables(self):
        return self.config.base_variables

    @property
    def element_overrides(self):
        return self.config.element_overrides

    @property
    def source_overrides(self):
        return self.config.source_overrides

    ########################################################
    #                     Public Methods                   #
    ########################################################

    # get_alias_url():
    #
    # Fetch the value of a URL alias
    #
    # Args:
    #    alias: The alias
    #    first_pass: Whether to use first pass configuration (for junctions)
    #
    # Returns:
    #    The alias substitution
    #
    def get_alias_url(self, alias: str, *, first_pass: bool = False) -> Optional[str]:
        if first_pass:
            config = self.first_pass_config
        else:
            config = self.config

        if config._aliases:
            return config._aliases.get_str(alias, default=None)

        return None

    # translate_url():
    #
    # Translates the given url which may be specified with an alias
    # into a fully qualified url.
    #
    # Args:
    #    url (str): A url, which may be using an alias
    #    first_pass (bool): Whether to use first pass configuration (for junctions)
    #
    # Returns:
    #    str: The fully qualified url, with aliases resolved
    #
    # This method is provided for :class:`.Source` objects to resolve
    # fully qualified urls based on the shorthand which is allowed
    # to be specified in the YAML
    def translate_url(self, url, *, source, first_pass=False):

        if url and utils._ALIAS_SEPARATOR in url:
            url_alias, url_body = url.split(utils._ALIAS_SEPARATOR, 1)
            alias_url = self.get_alias_url(url_alias, first_pass=first_pass)
            if alias_url:
                if self.junction:
                    parent_project = self.junction._get_project()
                    parent_alias = self.junction.get_parent_alias(url_alias)
                    if parent_alias:
                        # Delegate translation to parent project
                        return parent_project.translate_url(
                            parent_alias + utils._ALIAS_SEPARATOR + url_body, source=source, first_pass=first_pass
                        )
                    elif parent_project.disallow_subproject_uris:
                        raise SourceError(
                            "{}: Parent project did not provide a mapping for alias '{}' and disallowed usage of unmapped aliases".format(
                                source, url_alias
                            ),
                            reason="missing-alias-mapping",
                        )

                url = alias_url + url_body

        return url

    # get_shell_config()
    #
    # Gets the project specified shell configuration
    #
    # Returns:
    #    (list): The shell command
    #    (dict): The shell environment
    #    (list): The list of _HostMount objects
    #
    def get_shell_config(self):
        return (self._shell_command, self._shell_environment, self._shell_host_files)

    # get_path_from_node()
    #
    # Fetches the project path from a dictionary node and validates it
    #
    # Paths are asserted to never lead to a directory outside of the project
    # directory. In addition, paths can not point to symbolic links, fifos,
    # sockets and block/character devices.
    #
    # The `check_is_file` and `check_is_dir` parameters can be used to
    # perform additional validations on the path. Note that an exception
    # will always be raised if both parameters are set to ``True``.
    #
    # Args:
    #    node (ScalarNode): A Node loaded from YAML containing the path to validate
    #    check_is_file (bool): If ``True`` an error will also be raised
    #                          if path does not point to a regular file.
    #                          Defaults to ``False``
    #    check_is_dir (bool): If ``True`` an error will be also raised
    #                         if path does not point to a directory.
    #                         Defaults to ``False``
    # Returns:
    #    (str): The project path
    #
    # Raises:
    #    (LoadError): In case that the project path is not valid or does not
    #                 exist
    #
    def get_path_from_node(self, node, *, check_is_file=False, check_is_dir=False):
        path_str = node.as_str()
        path = Path(path_str)
        full_path = self._absolute_directory_path / path

        if full_path.is_symlink():
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' must not point to " "symbolic links ".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID_KIND,
            )

        if path.parts and path.parts[0] == "..":
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' first component must " "not be '..'".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID,
            )

        try:
            full_resolved_path = full_path.resolve(strict=True)
        except FileNotFoundError:
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' does not exist".format(provenance, path_str), LoadErrorReason.MISSING_FILE
            )

        is_inside = self._absolute_directory_path in full_resolved_path.parents or (
            full_resolved_path == self._absolute_directory_path
        )

        if not is_inside:
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' must not lead outside of the "
                "project directory".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID,
            )

        if path.is_absolute():
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Absolute path: '{}' invalid.\n"
                "Please specify a path relative to the project's root.".format(provenance, path),
                LoadErrorReason.PROJ_PATH_INVALID,
            )

        if full_resolved_path.is_socket() or (full_resolved_path.is_fifo() or full_resolved_path.is_block_device()):
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' points to an unsupported " "file kind".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID_KIND,
            )

        if check_is_file and not full_resolved_path.is_file():
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' is not a regular file".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID_KIND,
            )

        if check_is_dir and not full_resolved_path.is_dir():
            provenance = node.get_provenance()
            raise LoadError(
                "{}: Specified path '{}' is not a directory".format(provenance, path_str),
                LoadErrorReason.PROJ_PATH_INVALID_KIND,
            )

        return path_str

    # create_element()
    #
    # Instantiate and return an element
    #
    # Args:
    #    load_element (LoadElement): The LoadElement
    #
    # Returns:
    #    (Element): A newly created Element object of the appropriate kind
    #
    def create_element(self, load_element):
        return self.element_factory.create(self._context, self, load_element)

    # create_source()
    #
    # Instantiate and return a Source
    #
    # Args:
    #    meta (MetaSource): The loaded MetaSource
    #    variables (Variables): The list of variables available to the source
    #
    # Returns:
    #    (Source): A newly created Source object of the appropriate kind
    #
    def create_source(self, meta, variables):
        return self.source_factory.create(self._context, self, meta, variables)

    # alias_exists()
    #
    # Returns the URI for a given alias, if it exists
    #
    # Args:
    #    alias (str): The alias.
    #    first_pass (bool): Whether to use first pass configuration (for junctions)
    #
    # Returns:
    #    bool: Whether the alias is declared in the scope of this project
    #
    def alias_exists(self, alias, *, source, first_pass=False):
        if first_pass:
            config = self.first_pass_config
        else:
            config = self.config

        if self.junction:
            parent_project = self.junction._get_project()
            parent_alias = self.junction.get_parent_alias(alias)
            if parent_alias:
                if parent_project.alias_exists(parent_alias, source=source, first_pass=first_pass):
                    return True
                else:
                    raise SourceError(
                        "{}: Mapped alias '{}' for subproject alias '{}' is invalid in the parent project".format(
                            self.junction, parent_alias, alias
                        ),
                        reason="invalid-source-alias",
                    )
            elif parent_project.disallow_subproject_uris:
                raise SourceError(
                    "{}: Parent project did not provide a mapping for alias '{}' and disallowed usage of unmapped aliases".format(
                        source, alias
                    ),
                    reason="missing-alias-mapping",
                )

        return config._aliases.get_str(alias, default=None) is not None

    # get_alias_uris()
    #
    # Args:
    #    alias: The alias.
    #    first_pass: Whether to use first pass configuration (for junctions)
    #    tracking: Whether we want the aliases for tracking (otherwise assume fetching)
    #
    # Returns:
    #    A list of alias substitutions found. Each substitution is either a string
    #    (to be prepended to the rest of the URL instead of the alias) or a
    #    SourceMirror object.
    #
    def get_alias_uris(
        self, alias: str, *, first_pass: bool = False, tracking: bool = False
    ) -> Sequence[Optional[AliasSubstitution]]:

        if first_pass:
            config = self.first_pass_config
        else:
            config = self.config

        if not alias or alias not in config._aliases:  # pylint: disable=unsupported-membership-test
            return [None]

        if self.junction:
            parent_project = self.junction._get_project()
            parent_alias = self.junction.get_parent_alias(alias)
            if parent_alias:
                # Delegate translation to parent project
                return parent_project.get_alias_uris(parent_alias, first_pass=first_pass, tracking=tracking)
            elif parent_project.disallow_subproject_uris:
                return [None]

        uri_list: List[Union[SourceMirror, str]] = []
        policy = self._context.track_source if tracking else self._context.fetch_source

        if policy in (_SourceUriPolicy.ALL, _SourceUriPolicy.MIRRORS) or (
            policy == _SourceUriPolicy.USER and self._mirror_override
        ):
            for mirror_name, mirror in config.mirrors.items():
                list_to_add = mirror._get_alias_uris(alias)

                if mirror_name == config.default_mirror:
                    uri_list = list_to_add + uri_list
                else:
                    uri_list += list_to_add

        if policy in (_SourceUriPolicy.ALL, _SourceUriPolicy.ALIASES):
            uri_list.append(config._aliases.get_str(alias))

        return [AliasSubstitution(alias, mirror) for mirror in uri_list]

    # load_elements()
    #
    # Loads elements from target names.
    #
    # Args:
    #    targets (list): Target names
    #
    # Returns:
    #    (list): A list of loaded Element
    #
    def load_elements(self, targets):

        with self._context.messenger.simple_task("Loading elements", silent_nested=True) as task:
            self.load_context.set_task(task)
            load_elements = self.loader.load(targets)
            self.load_context.set_task(None)

        with self._context.messenger.simple_task("Resolving elements", silent_nested=True) as task:
            if task:
                task.set_maximum_progress(self.loader.loaded)
            elements = [Element._new_from_load_element(load_element, task) for load_element in load_elements]

        Element._clear_meta_elements_cache()

        # Assert loaders after resolving everything, this is because plugin
        # loading (across junction boundaries) can also be the cause of
        # conflicting projects.
        #
        self.load_context.assert_loaders()

        # Now warn about any redundant source references which may have
        # been discovered in the resolve() phase.
        redundant_refs = Element._get_redundant_source_refs()
        if redundant_refs:
            detail = "The following inline specified source references will be ignored:\n\n"
            lines = ["{}:{}".format(source._get_provenance(), ref) for source, ref in redundant_refs]
            detail += "\n".join(lines)
            self._context.messenger.warn("Ignoring redundant source references", detail=detail)

        return elements

    # ensure_fully_loaded()
    #
    # Ensure project has finished loading. At first initialization, a
    # project can only load junction elements. Other elements require
    # project to be fully loaded.
    #
    def ensure_fully_loaded(self):
        if self._fully_loaded:
            return
        assert self._partially_loaded

        # Here we mark the project as fully loaded right away,
        # before doing the work.
        #
        # This function will otherwise reenter itself infinitely:
        #
        #   * Ensuring the invariant that a parent project is fully
        #     loaded before completing the load of this project, will
        #     trigger this function when completing the load of subprojects.
        #
        #   * Completing the load of this project may include processing
        #     some `(@)` include directives, which can directly trigger
        #     the loading of subprojects.
        #
        self._fully_loaded = True

        if self.junction:
            self.junction._get_project().ensure_fully_loaded()

        self._load_second_pass()

    # get_default_target()
    #
    # Attempts to interpret which element the user intended to run a command on.
    # This is for commands that only accept a single target element and thus,
    # this only uses the workspace element (if invoked from workspace directory)
    # and does not use the project default targets.
    #
    def get_default_target(self):
        return self._invoked_from_workspace_element

    # get_default_targets()
    #
    # Attempts to interpret which elements the user intended to run a command on.
    # This is for commands that accept multiple target elements.
    #
    def get_default_targets(self):

        # If _invoked_from_workspace_element has a value,
        # a workspace element was found before a project config
        # Therefore the workspace does not contain a project
        if self._invoked_from_workspace_element:
            return (self._invoked_from_workspace_element,)

        # Default targets from project configuration
        if self._default_targets:
            return tuple(self._default_targets)

        # If default targets are not configured, default to all project elements
        default_targets = []
        for root, dirs, files in os.walk(self.element_path):
            # Do not recurse down the ".bst" directory which is where we stage
            # junctions and other BuildStream internals.
            if ".bst" in dirs:
                dirs.remove(".bst")
            for file in files:
                if file.endswith(".bst"):
                    rel_dir = os.path.relpath(root, self.element_path)
                    rel_file = os.path.join(rel_dir, file).lstrip("./")
                    default_targets.append(rel_file)

        return tuple(default_targets)

    # junction_is_duplicated()
    #
    # Check whether this loader is specified as a duplicate by
    # this project.
    #
    # Args:
    #    project_name: (str): The project name
    #    loader (Loader): The loader to check for
    #
    # Returns:
    #    (bool): Whether the loader is specified as duplicate
    #
    def junction_is_duplicated(self, project_name, loader):

        junctions = self._junction_duplicates.get(project_name, {})

        # Iterate over all paths specified by this project and see
        # if we find a match for the specified loader.
        #
        # Using the regular `Loader.get_loader()` codepath from this
        # project ensures that we will find the correct loader relative
        # to this project, regardless of any overrides or link elements
        # which might have been used in the project.
        #
        for dup_path in junctions:
            search = self.loader.get_loader(dup_path.as_str(), dup_path, load_subprojects=False)
            if loader is search:
                return True

        return False

    # junction_is_internal()
    #
    # Check whether this loader is specified as internal to
    # this project.
    #
    # Args:
    #    loader (Loader): The loader to check for
    #
    # Returns:
    #    (bool): Whether the loader is specified as internal
    #
    def junction_is_internal(self, loader):

        # Iterate over all paths specified by this project and see
        # if we find a match for the specified loader.
        #
        # Using the regular `Loader.get_loader()` codepath from this
        # project ensures that we will find the correct loader relative
        # to this project, regardless of any overrides or link elements
        # which might have been used in the project.
        #
        for internal_path in self._junction_internal:
            search = self.loader.get_loader(internal_path.as_str(), internal_path, load_subprojects=False)
            if loader is search:
                return True

        return False

    # loaded_projects()
    #
    # A generator which yields all the projects in context of a loaded
    # pipeline, including the self project.
    #
    # Projects will be yielded in the order in which they were loaded
    # for the current session's pipeline.
    #
    # This is used by the frontend to print information about all the
    # loaded projects.
    #
    # Yields:
    #    (_ProjectInformation): A descriptive project information object
    #
    def loaded_projects(self):
        yield from self.load_context.loaded_projects()

    ########################################################
    #                    Private Methods                   #
    ########################################################

    # _validate_toplevel_node()
    #
    # Validates the toplevel project.conf keys
    #
    # Args:
    #    node (MappingNode): The toplevel project.conf node
    #    first_pass (bool): Whether this is the first or second pass
    #
    def _validate_toplevel_node(self, node, *, first_pass=False):
        node.validate_keys(
            [
                "min-version",
                "element-path",
                "variables",
                "environment",
                "environment-nocache",
                "split-rules",
                "elements",
                "plugins",
                "aliases",
                "name",
                "defaults",
                "artifacts",
                "options",
                "fail-on-overlap",
                "shell",
                "fatal-warnings",
                "ref-storage",
                "sandbox",
                "mirrors",
                "sources",
                "source-caches",
                "junctions",
                "(@)",
                "(?)",
            ]
        )

        # Keys which are invalid if specified outside of project.conf
        if not first_pass:
            invalid_keys = {"name", "element-path", "min-version", "plugins"}

            for invalid_key in invalid_keys:
                invalid_node = node.get_node(invalid_key, allow_none=True)
                if invalid_node:
                    provenance = invalid_node.get_provenance()
                    if (
                        provenance._shortname != "project.conf"
                        and provenance._filename != _site.default_project_config
                    ):
                        raise LoadError(
                            "{}: Unexpected key: {}".format(provenance, invalid_key),
                            LoadErrorReason.INVALID_DATA,
                            detail="The '{}' configuration must be specified in project.conf".format(invalid_key),
                        )

    # _validate_version()
    #
    # Asserts that we have a BuildStream installation which is recent
    # enough for the project required version
    #
    # Args:
    #    config_node (dict) - YaML node of the configuration file.
    #
    # Raises: LoadError if there was a problem with the project.conf
    #
    def _validate_version(self, config_node):

        bst_major, bst_minor = utils._get_bst_api_version()

        # Use a custom error message for the absence of the required "min-version"
        # as this may be an indication that we are trying to load a BuildStream 1 project.
        #
        min_version_node = config_node.get_scalar("min-version", None)
        if min_version_node.is_none():
            p = config_node.get_provenance()
            raise LoadError(
                "{}: Dictionary did not contain expected key 'min-version'".format(p),
                LoadErrorReason.INVALID_DATA,
                #
                # TODO: Provide a link to documentation on how to install
                #       BuildStream 1 in a venv
                #
                detail="If you are trying to use a BuildStream 1 project, "
                + "please install BuildStream 1 to use this project.",
            )

        # Parse the project declared minimum required BuildStream version
        min_version = min_version_node.as_str()
        try:
            min_version_major, min_version_minor = utils._parse_version(min_version)
        except UtilError as e:
            p = min_version_node.get_provenance()
            raise LoadError(
                "{}: {}\n".format(p, e),
                LoadErrorReason.INVALID_DATA,
                detail="The min-version must be specified as MAJOR.MINOR with "
                + "numeric major and minor minimum required version numbers",
            ) from e

        # Future proofing, in case there is ever a BuildStream 3
        if min_version_major != bst_major:
            p = min_version_node.get_provenance()
            raise LoadError(
                "{}: Version mismatch".format(p),
                LoadErrorReason.UNSUPPORTED_PROJECT,
                detail="Project requires BuildStream {}, ".format(min_version_major)
                + "but BuildStream {} is installed.\n".format(bst_major)
                + "Please use BuildStream {} with this project.".format(min_version_major),
            )

        # Check minimal minor point requirement is satisfied
        if min_version_minor > bst_minor:
            p = min_version_node.get_provenance()
            raise LoadError(
                "{}: Version mismatch".format(p),
                LoadErrorReason.UNSUPPORTED_PROJECT,
                detail="Project requires at least BuildStream {}.{}, ".format(min_version_major, min_version_minor)
                + "but BuildStream {}.{} is installed.\n".format(bst_major, bst_minor)
                + "Please upgrade BuildStream.",
            )

    # _load():
    #
    # Loads the project configuration file in the project
    # directory process the first pass.
    #
    # Raises: LoadError if there was a problem with the project.conf
    #
    def _load(self, *, parent_loader=None, provenance_node=None):

        # Load builtin default
        projectfile = os.path.join(self.directory, _PROJECT_CONF_FILE)
        self._default_config_node = _yaml.load(_site.default_project_config, shortname="projectconfig.yaml")

        # Load project local config and override the builtin
        try:
            self._project_conf = _yaml.load(projectfile, shortname=_PROJECT_CONF_FILE, project=self)
        except LoadError as e:
            # Raise a more specific error here
            if e.reason == LoadErrorReason.MISSING_FILE:
                raise LoadError(str(e), LoadErrorReason.MISSING_PROJECT_CONF) from e

            # Otherwise re-raise the original exception
            raise

        pre_config_node = self._default_config_node.clone()
        self._project_conf._composite(pre_config_node)

        # Assert project's minimum required version early, before validating toplevel keys
        self._validate_version(pre_config_node)

        self._validate_toplevel_node(pre_config_node, first_pass=True)

        # The project name, element path and option declarations
        # are constant and cannot be overridden by option conditional statements
        # FIXME: we should be keeping node information for further composition here
        self.name = self._project_conf.get_str("name")

        # Validate that project name is a valid symbol name
        _assert_symbol_name(self.name, "project name", ref_node=pre_config_node.get_node("name"))

        self.element_path = os.path.join(
            self.directory, self.get_path_from_node(pre_config_node.get_scalar("element-path"), check_is_dir=True)
        )

        self.config.options = OptionPool(self.element_path)
        self.first_pass_config.options = OptionPool(self.element_path)

        defaults = pre_config_node.get_mapping("defaults")
        defaults.validate_keys(["targets"])
        self._default_targets = defaults.get_str_list("targets")

        # Fatal warnings
        self._fatal_warnings = pre_config_node.get_str_list("fatal-warnings", default=[])

        # Junction configuration
        junctions_node = pre_config_node.get_mapping("junctions", default={})
        junctions_node.validate_keys(["duplicates", "internal", "disallow-subproject-uris"])

        if self.junction and self.junction._get_project().disallow_subproject_uris:
            # If the parent project doesn't allow subproject URIs, this must
            # be enforced for nested subprojects as well.
            self.disallow_subproject_uris = True

            # The `disallow-subproject-uris` flag also implies fatal `unaliased-url` in subprojects
            # to ensure no subproject URIs escape the parent project's control.
            if CoreWarnings.UNALIASED_URL not in self._fatal_warnings:
                self._fatal_warnings.append(CoreWarnings.UNALIASED_URL)
        else:
            self.disallow_subproject_uris = junctions_node.get_bool("disallow-subproject-uris", default=False)

        # Parse duplicates
        junction_duplicates = junctions_node.get_mapping("duplicates", default={})
        for project_name, junctions in junction_duplicates.items():
            self._junction_duplicates[project_name] = junctions

        # Parse internal
        self._junction_internal = junctions_node.get_sequence("internal", default=[])

        self.loader = Loader(self, parent=parent_loader, provenance_node=provenance_node)

        self._project_includes = Includes(self.loader, copy_tree=False)

        project_conf_first_pass = self._project_conf.clone()
        self._project_includes.process(project_conf_first_pass, only_local=True, process_project_options=False)
        config_no_include = self._default_config_node.clone()
        project_conf_first_pass._composite(config_no_include)

        # Plugin factories must be defined in project.conf, not included from elsewhere.
        self._load_plugin_factories(config_no_include)

        self._load_pass(config_no_include, self.first_pass_config, ignore_unknown=True)

        # Use separate file for storing source references
        ref_storage_node = pre_config_node.get_scalar("ref-storage")
        self.ref_storage = ref_storage_node.as_str()
        if self.ref_storage not in [ProjectRefStorage.INLINE, ProjectRefStorage.PROJECT_REFS]:
            p = ref_storage_node.get_provenance()
            raise LoadError(
                "{}: Invalid value '{}' specified for ref-storage".format(p, self.ref_storage),
                LoadErrorReason.INVALID_DATA,
            )

        if self.ref_storage == ProjectRefStorage.PROJECT_REFS:
            self.junction_refs.load(self.first_pass_config.options)

    # _load_second_pass()
    #
    # Process the second pass of loading the project configuration.
    #
    def _load_second_pass(self):
        project_conf_second_pass = self._project_conf.clone()
        self._project_includes.process(project_conf_second_pass, process_project_options=False)
        config = self._default_config_node.clone()
        project_conf_second_pass._composite(config)

        self._load_pass(config, self.config)

        self._validate_toplevel_node(config, first_pass=False)

        #
        # Now all YAML composition is done, from here on we just load
        # the values from our loaded configuration dictionary.
        #

        # Load artifact remote specs
        caches = config.get_sequence("artifacts", default=[], allowed_types=[MappingNode])
        for node in caches:
            spec = RemoteSpec.new_from_node(node, self.directory)
            self.artifact_cache_specs.append(spec)

        # Load source cache remote specs
        caches = config.get_sequence("source-caches", default=[], allowed_types=[MappingNode])
        for node in caches:
            spec = RemoteSpec.new_from_node(node, self.directory)
            self.source_cache_specs.append(spec)

        # Load sandbox environment variables
        self.base_environment = config.get_mapping("environment")
        self.base_env_nocache = config.get_str_list("environment-nocache")

        # Load sandbox configuration
        self.sandbox = config.get_mapping("sandbox")

        # Load project split rules
        self.splits = config.get_mapping("split-rules")

        # Support backwards compatibility for fail-on-overlap
        fail_on_overlap = config.get_scalar("fail-on-overlap", None)

        # Deprecation check
        if not fail_on_overlap.is_none():
            self._context.messenger.warn(
                "Use of fail-on-overlap within project.conf "
                + "is deprecated. Consider using fatal-warnings instead.",
            )

            if (CoreWarnings.OVERLAPS not in self._fatal_warnings) and fail_on_overlap.as_bool():
                self._fatal_warnings.append(CoreWarnings.OVERLAPS)

        # Load project.refs if it exists, this may be ignored.
        if self.ref_storage == ProjectRefStorage.PROJECT_REFS:
            self.refs.load(self.options)

        # Parse shell options
        shell_options = config.get_mapping("shell")
        shell_options.validate_keys(["command", "environment", "host-files"])
        self._shell_command = shell_options.get_str_list("command")

        # Perform environment expansion right away
        shell_environment = shell_options.get_mapping("environment", default={})
        for key in shell_environment.keys():
            value = shell_environment.get_str(key)
            self._shell_environment[key] = os.path.expandvars(value)

        # Host files is parsed as a list for convenience
        host_files = shell_options.get_sequence("host-files", default=[])
        for host_file in host_files:
            if isinstance(host_file, ScalarNode):
                mount = _HostMount(host_file.as_str())
            else:
                # Some validation
                host_file.validate_keys(["path", "host_path", "optional"])

                # Parse the host mount
                path = host_file.get_str("path")
                host_path = host_file.get_str("host_path", default=None)
                optional = host_file.get_bool("optional", default=False)
                mount = _HostMount(path, host_path, optional)

            self._shell_host_files.append(mount)

    # _load_pass():
    #
    # Loads parts of the project configuration that are different
    # for first and second pass configurations.
    #
    # Args:
    #    config (dict) - YaML node of the configuration file.
    #    output (ProjectConfig) - ProjectConfig to load configuration onto.
    #    ignore_unknown (bool) - Whether option loader shoud ignore unknown options.
    #
    def _load_pass(self, config, output, *, ignore_unknown=False):

        # Load project options
        options_node = config.get_mapping("options", default={})
        output.options.load(options_node)
        if self.junction:
            # load before user configuration
            output.options.load_yaml_values(self.junction.options)

        # Collect option values specified in the user configuration
        overrides = self._context.get_overrides(self.name)
        override_options = overrides.get_mapping("options", default={})
        output.options.load_yaml_values(override_options)
        if self._cli_options:
            output.options.load_cli_values(self._cli_options, ignore_unknown=ignore_unknown)

        # We're done modifying options, now we can use them for substitutions
        output.options.resolve()

        #
        # Now resolve any conditionals in the remaining configuration,
        # any conditionals specified for project option declarations,
        # or conditionally specifying the project name; will be ignored.
        #
        # Specify any options that would be ignored in the restrict list
        # so as to raise an appropriate error.
        #
        output.options.process_node(
            config,
            restricted=[
                "min-version",
                "name",
                "element-path",
                "junctions",
                "defaults",
                "fatal-warnings",
                "ref-storage",
                "options",
                "plugins",
            ],
        )

        # Element and Source  type configurations will be composited later onto
        # element/source types, so we delete it from here and run our final
        # assertion after.
        output.element_overrides = config.get_mapping("elements", default={})
        output.source_overrides = config.get_mapping("sources", default={})
        config.safe_del("elements")
        config.safe_del("sources")
        config._assert_fully_composited()

        # Load base variables
        output.base_variables = config.get_mapping("variables")

        # Add the project name as a default variable
        output.base_variables["project-name"] = self.name

        # Extend variables with automatic variables and option exports
        # Initialize it as a string as all variables are processed as strings.
        # Based on some testing (mainly on AWS), maximum effective
        # max-jobs value seems to be around 8-10 if we have enough cores
        # users should set values based on workload and build infrastructure
        if self._context.build_max_jobs == 0:
            # User requested automatic max-jobs
            platform = self._context.platform
            output.base_variables["max-jobs"] = str(platform.get_cpu_count(8))
        else:
            # User requested explicit max-jobs setting
            output.base_variables["max-jobs"] = str(self._context.build_max_jobs)

        # Export options into variables, if that was requested
        output.options.export_variables(output.base_variables)

        # Prepare a Variables instance for substitution of source alias and
        # source mirror values.
        #
        # This allows substitution of any project-level variables, plus the special
        # variables which allow resolving project relative directories on the host.
        #
        toplevel_project = self._context.get_toplevel_project()
        variables_node = output.base_variables.clone()
        variables_node["project-root"] = str(self._absolute_directory_path)
        variables_node["toplevel-root"] = str(toplevel_project._absolute_directory_path)
        variables_node["project-root-uri"] = "file://" + urllib.parse.quote(str(self._absolute_directory_path))
        variables_node["toplevel-root-uri"] = "file://" + urllib.parse.quote(
            str(toplevel_project._absolute_directory_path)
        )
        variables = Variables(variables_node)

        # Override default_mirror if not set by command-line
        output.default_mirror = self._default_mirror or overrides.get_str("default-mirror", default=None)

        # First try mirrors specified in user configuration, user configuration
        # is allowed to completely disable mirrors by specifying an empty list,
        # so we check for a None value here too.
        #
        mirrors_node = overrides.get_sequence("mirrors", default=None)
        if mirrors_node is None:
            mirrors_node = config.get_sequence("mirrors", default=[])
        else:
            self._mirror_override = True

        # Perform variable substitutions in source mirror definitions,
        # even if the mirrors are specified in user configuration.
        variables.expand(mirrors_node)

        # Collect SourceMirror objects
        for mirror_node in mirrors_node:
            mirror = self.source_mirror_factory.create(self._context, self, mirror_node)
            output.mirrors[mirror.name] = mirror
            if not output.default_mirror:
                output.default_mirror = mirror.name

        # Source url aliases
        output._aliases = config.get_mapping("aliases", default={})

        # Perform variable substitutions in source aliases
        variables.expand(output._aliases)

    # _find_project_dir()
    #
    # Returns path of the project directory, if a configuration file is found
    # in given directory or any of its parent directories.
    #
    # Args:
    #    directory (str) - directory from where the command was invoked
    #
    # Raises:
    #    LoadError if project.conf is not found
    #
    # Returns:
    #    (str) - the directory that contains the project, and
    #    (str) - the name of the element required to find the project, or None
    #
    def _find_project_dir(self, directory):
        workspace_element = None
        config_filenames = [_PROJECT_CONF_FILE, WORKSPACE_PROJECT_FILE]
        found_directory, filename = utils._search_upward_for_files(directory, config_filenames)
        if filename == _PROJECT_CONF_FILE:
            project_directory = found_directory
        elif filename == WORKSPACE_PROJECT_FILE:
            workspace_project_cache = self._context.get_workspace_project_cache()
            workspace_project = workspace_project_cache.get(found_directory)
            if workspace_project:
                project_directory = workspace_project.get_default_project_path()
                workspace_element = workspace_project.get_default_element()
        else:
            raise LoadError(
                "None of {names} found in '{path}' or any of its parent directories".format(
                    names=config_filenames, path=directory
                ),
                LoadErrorReason.MISSING_PROJECT_CONF,
            )

        return project_directory, workspace_element

    # _load_plugin_factories()
    #
    # Loads the plugin factories
    #
    # Args:
    #    config (MappingNode): The main project.conf node in the first pass
    #
    def _load_plugin_factories(self, config):
        # Create the factories
        pluginbase = PluginBase(package="buildstream.plugins")
        self.element_factory = ElementFactory(pluginbase)
        self.source_factory = SourceFactory(pluginbase)
        self.source_mirror_factory = SourceMirrorFactory(pluginbase)

        # Load the plugin origins and register them to their factories
        origins = config.get_sequence("plugins", default=[])
        for origin_node in origins:
            origin = load_plugin_origin(self, origin_node)
            for kind, conf in origin.elements.items():
                self.element_factory.register_plugin_origin(kind, origin, conf.allow_deprecated)
            for kind, conf in origin.sources.items():
                self.source_factory.register_plugin_origin(kind, origin, conf.allow_deprecated)
            for kind, conf in origin.source_mirrors.items():
                self.source_mirror_factory.register_plugin_origin(kind, origin, conf.allow_deprecated)

    # _warning_is_fatal():
    #
    # Returns true if the warning in question should be considered fatal based on
    # the project configuration.
    #
    # Args:
    #   warning_str (str): The warning configuration string to check against
    #
    # Returns:
    #    (bool): True if the warning should be considered fatal and cause an error.
    #
    def _warning_is_fatal(self, warning_str):
        return warning_str in self._fatal_warnings
