#
#  Copyright (C) 2020 Codethink Limited
#
#  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>
#        Jürg Billeter <juerg.billeter@codethink.co.uk>
#        Tristan Maat <tristan.maat@codethink.co.uk>

import itertools
import os
import sys
import stat
import shlex
import shutil
import tarfile
import tempfile
from contextlib import contextmanager, suppress
from collections import deque
from typing import List, Tuple, Optional, Iterable, Callable

from ._artifactelement import verify_artifact_ref, ArtifactElement
from ._artifactproject import ArtifactProject
from ._exceptions import StreamError, ImplError, BstError, ArtifactElementError, ArtifactError
from ._scheduler import (
    Scheduler,
    SchedStatus,
    TrackQueue,
    CacheQueryQueue,
    FetchQueue,
    SourcePushQueue,
    BuildQueue,
    PullQueue,
    ArtifactPushQueue,
)
from .element import Element
from ._profile import Topics, PROFILER
from ._project import ProjectRefStorage
from ._remotespec import RemoteSpec
from ._state import State
from .types import _KeyStrength, _PipelineSelection, _Scope, _HostMount
from .plugin import Plugin
from . import utils, node, _yaml, _site, _pipeline
from .downloadablefilesource import DownloadableFileSource


# Stream()
#
# This is the main, toplevel calling interface in BuildStream core.
#
# Args:
#    context (Context): The Context object
#    session_start (datetime): The time when the session started
#    session_start_callback (callable): A callback to invoke when the session starts
#    interrupt_callback (callable): A callback to invoke when we get interrupted
#    ticker_callback (callable): Invoked every second while running the scheduler
#
class Stream:
    def __init__(
        self, context, session_start, *, session_start_callback=None, interrupt_callback=None, ticker_callback=None
    ):

        #
        # Public members
        #
        self.targets = []  # Resolved target elements
        self.session_elements = []  # List of elements being processed this session
        self.total_elements = []  # Total list of elements based on targets
        self.queues = []  # Queue objects

        #
        # Private members
        #
        self._context = context
        self._artifacts = None
        self._elementsourcescache = None
        self._sourcecache = None
        self._project = None
        self._state = State(session_start)  # Owned by Stream, used by Core to set state
        self._notification_queue = deque()

        context.messenger.set_state(self._state)

        self._scheduler = Scheduler(context, session_start, self._state, interrupt_callback, ticker_callback)
        self._session_start_callback = session_start_callback
        self._running = False
        self._terminated = False
        self._suspended = False

    # init()
    #
    # Initialization of Stream that has side-effects that require it to be
    # performed after the Stream is created.
    #
    def init(self):
        self._artifacts = self._context.artifactcache
        self._elementsourcescache = self._context.elementsourcescache
        self._sourcecache = self._context.sourcecache

    # cleanup()
    #
    # Cleans up application state
    #
    def cleanup(self):
        # Reset the element loader state
        Element._reset_load_state()

        # Reset global state in node.pyx, this is for the sake of
        # test isolation.
        node._reset_global_state()

        # Ensure that any global state loaded by the downloadablefilesource
        # is discarded in between sessions (different invocations of the CLI
        # may come with different local state such as .netrc files, so we need
        # a reset here).
        DownloadableFileSource._reset_url_opener()

    # set_project()
    #
    # Set the top-level project.
    #
    # Args:
    #    project (Project): The Project object
    #
    def set_project(self, project):
        assert self._project is None
        self._project = project
        if self._project:
            self._project.load_context.set_fetch_subprojects(self._fetch_subprojects)

    # load_selection()
    #
    # An all purpose method for loading a selection of elements, this
    # is primarily useful for the frontend to implement `bst show`
    # and `bst shell`.
    #
    # Args:
    #    targets: Targets to pull
    #    selection: The selection mode for the specified targets (_PipelineSelection)
    #    except_targets: Specified targets to except from fetching
    #    load_artifacts (bool): Whether to load artifacts with artifact names
    #    connect_artifact_cache: Whether to try to contact remote artifact caches
    #    connect_source_cache: Whether to try to contact remote source caches
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    # Returns:
    #    (list of Element): The selected elements
    def load_selection(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        except_targets: Iterable[str] = (),
        load_artifacts: bool = False,
        connect_artifact_cache: bool = False,
        connect_source_cache: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
        ignore_project_source_remotes: bool = False,
    ):
        with PROFILER.profile(Topics.LOAD_SELECTION, "_".join(t.replace(os.sep, "-") for t in targets)):
            target_objects = self._load(
                targets,
                selection=selection,
                except_targets=except_targets,
                load_artifacts=load_artifacts,
                connect_artifact_cache=connect_artifact_cache,
                connect_source_cache=connect_source_cache,
                artifact_remotes=artifact_remotes,
                source_remotes=source_remotes,
                ignore_project_artifact_remotes=ignore_project_artifact_remotes,
                ignore_project_source_remotes=ignore_project_source_remotes,
            )
            return target_objects

    # query_cache()
    #
    # Query the artifact and source caches to determine the cache status
    # of the specified elements.
    #
    # Args:
    #    elements (list of Element): The elements to check
    #    sources_of_cached_elements (bool): True to query the source cache for elements with a cached artifact
    #    only_sources (bool): True to only query the source cache
    #
    def query_cache(self, elements, *, sources_of_cached_elements=False, only_sources=False):
        # It doesn't make sense to combine these flags
        assert not sources_of_cached_elements or not only_sources

        with self._context.messenger.simple_task("Query cache", silent_nested=True) as task:
            # Enqueue complete build plan as this is required to determine `buildable` status.
            plan = list(_pipeline.dependencies(elements, _Scope.ALL))

            if self._context.remote_cache_spec:
                # Parallelize cache queries if a remote cache is configured
                self._reset()
                self._add_queue(CacheQueryQueue(self._scheduler, sources=only_sources), track=True)
                self._enqueue_plan(plan)
                self._run()
            else:
                task.set_maximum_progress(len(plan))
                for element in plan:
                    if element._can_query_cache():
                        # Cache status already available.
                        # This is the case for artifact elements, which load the
                        # artifact early on.
                        pass
                    elif not only_sources and element._get_cache_key(strength=_KeyStrength.WEAK):
                        element._load_artifact(pull=False)
                        if (
                            sources_of_cached_elements
                            or not element._can_query_cache()
                            or not element._cached_success()
                        ):
                            element._query_source_cache()
                        if not element._pull_pending():
                            element._load_artifact_done()
                    elif element._has_all_sources_resolved():
                        element._query_source_cache()

                    task.add_current_progress()

    # shell()
    #
    # Run a shell
    #
    # Args:
    #    target: The name of the element to run the shell for
    #    scope: The scope for the shell, only BUILD or RUN are valid (_Scope)
    #    prompt: A function to return the prompt to display in the shell
    #    unique_id: (str): A unique_id to use to lookup an Element instance
    #    mounts: Additional directories to mount into the sandbox
    #    isolate (bool): Whether to isolate the environment like we do in builds
    #    command (list): An argv to launch in the sandbox, or None
    #    usebuildtree (bool): Whether to use a buildtree as the source, given cli option
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    # Returns:
    #    (int): The exit code of the launched shell
    #
    def shell(
        self,
        target: str,
        scope: int,
        prompt: Callable[[Element], str],
        *,
        unique_id: Optional[str] = None,
        mounts: Optional[List[_HostMount]] = None,
        isolate: bool = False,
        command: Optional[List[str]] = None,
        usebuildtree: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
        ignore_project_source_remotes: bool = False,
    ):
        element: Element

        # Load the Element via the unique_id if given
        if unique_id and target is None:
            element = Plugin._lookup(unique_id)
        else:
            if usebuildtree:
                selection = _PipelineSelection.NONE
            elif scope == _Scope.BUILD:
                selection = _PipelineSelection.BUILD
            else:
                selection = _PipelineSelection.RUN

            elements = self.load_selection(
                (target,),
                selection=selection,
                connect_artifact_cache=True,
                connect_source_cache=True,
                artifact_remotes=artifact_remotes,
                source_remotes=source_remotes,
                ignore_project_artifact_remotes=ignore_project_artifact_remotes,
                ignore_project_source_remotes=ignore_project_source_remotes,
            )

            # Get element to stage from `targets` list.
            # If scope is BUILD, it will not be in the `elements` list.
            assert len(self.targets) == 1
            element = self.targets[0]
            element._set_required(scope)

            if scope == _Scope.BUILD:
                pull_elements = [element] + elements
            else:
                pull_elements = elements

            # Check whether the required elements are cached, and then
            # try to pull them if they are not already cached.
            #
            self.query_cache(pull_elements)
            self._pull_missing_artifacts(pull_elements)

        # We dont need dependency artifacts to shell into a cached build tree
        if not usebuildtree:
            missing_deps = [dep for dep in _pipeline.dependencies([element], scope) if not dep._cached()]
            if missing_deps:
                raise StreamError(
                    "Elements need to be built or downloaded before staging a shell environment",
                    detail="\n".join(list(map(lambda x: x._get_full_name(), missing_deps))),
                    reason="shell-missing-deps",
                )

        # Check if we require a pull queue attempt, with given artifact state and context
        if usebuildtree:
            if not element._cached_buildroot():
                if not element._cached():
                    message = "Artifact not cached locally or in available remotes"
                    reason = "missing-buildtree-artifact-not-cached"
                elif element._buildroot_exists():
                    message = "Buildtree is not cached locally or in available remotes"
                    reason = "missing-buildtree-artifact-buildtree-not-cached"
                else:
                    message = "Artifact was created without buildtree"
                    reason = "missing-buildtree-artifact-created-without-buildtree"
                raise StreamError(message, reason=reason)

            # Raise warning if the element is cached in a failed state
            if element._cached_failure():
                self._context.messenger.warn("using a buildtree from a failed build.")

        # Ensure we have our sources if we are launching a build shell
        if scope == _Scope.BUILD and not usebuildtree:
            self.query_cache([element], only_sources=True)
            self._fetch([element])
            _pipeline.assert_sources_cached(self._context, [element])

        return element._shell(
            scope, mounts=mounts, isolate=isolate, prompt=prompt(element), command=command, usebuildtree=usebuildtree
        )

    # build()
    #
    # Builds (assembles) elements in the pipeline.
    #
    # Args:
    #    targets: Targets to build
    #    selection: The selection mode for the specified targets (_PipelineSelection)
    #    ignore_junction_targets: Whether junction targets should be filtered out
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    # If `remote` specified as None, then regular configuration will be used
    # to determine where to push artifacts to.
    #
    def build(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        ignore_junction_targets: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
        ignore_project_source_remotes: bool = False,
    ):

        # Flag the build state
        self._context.build = True

        elements = self._load(
            targets,
            selection=selection,
            ignore_junction_targets=ignore_junction_targets,
            dynamic_plan=True,
            connect_artifact_cache=True,
            connect_source_cache=True,
            artifact_remotes=artifact_remotes,
            source_remotes=source_remotes,
            ignore_project_artifact_remotes=ignore_project_artifact_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        # Assert that the elements are consistent
        _pipeline.assert_consistent(self._context, elements)

        source_push_enabled = self._sourcecache.has_push_remotes()

        # If source push is enabled, the source cache status of all elements
        # is required, independent of whether the artifact is already available.
        self.query_cache(elements, sources_of_cached_elements=source_push_enabled)

        # Now construct the queues
        #
        self._reset()

        if self._artifacts.has_fetch_remotes():
            self._add_queue(PullQueue(self._scheduler))

        self._add_queue(FetchQueue(self._scheduler, skip_cached=True))

        self._add_queue(BuildQueue(self._scheduler))

        if self._artifacts.has_push_remotes():
            self._add_queue(ArtifactPushQueue(self._scheduler, skip_uncached=True))

        if source_push_enabled:
            self._add_queue(SourcePushQueue(self._scheduler))

        # Enqueue elements
        self._enqueue_plan(elements)
        self._run(announce_session=True)

    # fetch()
    #
    # Fetches sources on the pipeline.
    #
    # Args:
    #    targets: Targets to fetch
    #    selection: The selection mode for the specified targets (_PipelineSelection)
    #    except_targets: Specified targets to except from fetching
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    def fetch(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        except_targets: Iterable[str] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_source_remotes: bool = False,
    ):

        if self._context.remote_cache_spec:
            self._context.messenger.warn(
                "Cache Storage Service is configured, fetched sources may not be available in the local cache"
            )

        elements = self._load(
            targets,
            selection=selection,
            except_targets=except_targets,
            connect_source_cache=True,
            source_remotes=source_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        self.query_cache(elements, only_sources=True)

        # Delegated to a shared fetch method
        self._fetch(elements, announce_session=True)

    # track()
    #
    # Tracks all the sources of the selected elements.
    #
    # Args:
    #    targets (list of str): Targets to track
    #    selection (_PipelineSelection): The selection mode for the specified targets
    #    except_targets (list of str): Specified targets to except from tracking
    #    cross_junctions (bool): Whether tracking should cross junction boundaries
    #
    # If no error is encountered while tracking, then the project files
    # are rewritten inline.
    #
    def track(self, targets, *, selection=_PipelineSelection.REDIRECT, except_targets=None, cross_junctions=False):

        elements = self._load_tracking(
            targets, selection=selection, except_targets=except_targets, cross_junctions=cross_junctions
        )

        # Note: We do not currently need to initialize the state of an
        # element before it is tracked, since tracking can be done
        # irrespective of source/artifact condition. Once an element
        # is tracked, its state must be fully updated in either case,
        # and we anyway don't do anything else with it.

        self._reset()
        track_queue = TrackQueue(self._scheduler)
        self._add_queue(track_queue, track=True)
        self._enqueue_plan(elements, queue=track_queue)
        self._run(announce_session=True)

    # source_push()
    #
    # Push sources.
    #
    # Args:
    #    targets (list of str): Targets to push
    #    selection (_PipelineSelection): The selection mode for the specified targets
    #    except_targets: Specified targets to except from pushing
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    # If `remote` specified as None, then regular configuration will be used
    # to determine where to push sources to.
    #
    # If any of the given targets are missing their expected sources,
    # a fetch queue will be created if user context and available remotes allow for
    # attempting to fetch them.
    #
    def source_push(
        self,
        targets,
        *,
        selection=_PipelineSelection.NONE,
        except_targets: Iterable[str] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_source_remotes: bool = False,
    ):

        elements = self._load(
            targets,
            selection=selection,
            except_targets=except_targets,
            load_artifacts=True,
            connect_source_cache=True,
            source_remotes=source_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        self.query_cache(elements, only_sources=True)

        if not self._sourcecache.has_push_remotes():
            raise StreamError("No source caches available for pushing sources")

        _pipeline.assert_consistent(self._context, elements)

        self._add_queue(FetchQueue(self._scheduler))

        self._add_queue(SourcePushQueue(self._scheduler))

        self._enqueue_plan(elements)
        self._run(announce_session=True)

    # pull()
    #
    # Pulls artifacts from remote artifact server(s)
    #
    # Args:
    #    targets: Targets to pull
    #    selection: The selection mode for the specified targets (_PipelineSelection)
    #    ignore_junction_targets: Whether junction targets should be filtered out
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #
    def pull(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        ignore_junction_targets: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
    ):

        if self._context.remote_cache_spec:
            self._context.messenger.warn(
                "Cache Storage Service is configured, pulled artifacts may not be available in the local cache"
            )

        elements = self._load(
            targets,
            selection=selection,
            ignore_junction_targets=ignore_junction_targets,
            load_artifacts=True,
            attempt_artifact_metadata=True,
            connect_artifact_cache=True,
            artifact_remotes=artifact_remotes,
            ignore_project_artifact_remotes=ignore_project_artifact_remotes,
        )

        if not self._artifacts.has_fetch_remotes():
            raise StreamError("No artifact caches available for pulling artifacts")

        _pipeline.assert_consistent(self._context, elements)

        self.query_cache(elements)

        self._reset()
        self._add_queue(PullQueue(self._scheduler))
        self._enqueue_plan(elements)
        self._run(announce_session=True)

    # push()
    #
    # Pushes artifacts to remote artifact server(s), pulling them first if necessary,
    # possibly from different remotes.
    #
    # Args:
    #    targets (list of str): Targets to push
    #    selection (_PipelineSelection): The selection mode for the specified targets
    #    ignore_junction_targets (bool): Whether junction targets should be filtered out
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #
    # If any of the given targets are missing their expected buildtree artifact,
    # a pull queue will be created if user context and available remotes allow for
    # attempting to fetch them.
    #
    def push(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        ignore_junction_targets: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
    ):

        elements = self._load(
            targets,
            selection=selection,
            ignore_junction_targets=ignore_junction_targets,
            load_artifacts=True,
            connect_artifact_cache=True,
            artifact_remotes=artifact_remotes,
            ignore_project_artifact_remotes=ignore_project_artifact_remotes,
        )

        if not self._artifacts.has_push_remotes():
            raise StreamError("No artifact caches available for pushing artifacts")

        _pipeline.assert_consistent(self._context, elements)

        self.query_cache(elements)

        self._reset()
        self._add_queue(PullQueue(self._scheduler))
        self._add_queue(ArtifactPushQueue(self._scheduler))
        self._enqueue_plan(elements)
        self._run(announce_session=True)

    # checkout()
    #
    # Checkout target artifact to the specified location
    #
    # Args:
    #    target: Target to checkout
    #    location: Location to checkout the artifact to
    #    force: Whether files can be overwritten if necessary
    #    selection: The selection mode for the specified targets (_PipelineSelection)
    #    integrate: Whether to run integration commands
    #    hardlinks: Whether checking out files hardlinked to
    #               their artifacts is acceptable
    #    tar: If true, a tarball from the artifact contents will
    #         be created, otherwise the file tree of the artifact
    #         will be placed at the given location. If true and
    #         location is '-', the tarball will be dumped on the
    #         standard output.
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #
    def checkout(
        self,
        target: str,
        *,
        location: Optional[str] = None,
        force: bool = False,
        selection: str = _PipelineSelection.RUN,
        integrate: bool = True,
        hardlinks: bool = False,
        compression: str = "",
        tar: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
    ):

        elements = self._load(
            (target,),
            selection=selection,
            load_artifacts=True,
            attempt_artifact_metadata=True,
            connect_artifact_cache=True,
            artifact_remotes=artifact_remotes,
            ignore_project_artifact_remotes=ignore_project_artifact_remotes,
        )

        # self.targets contains a list of the loaded target objects
        # if we specify --deps build, Stream._load() will return a list
        # of build dependency objects, however, we need to prepare a sandbox
        # with the target (which has had its appropriate dependencies loaded)
        element: Element = self.targets[0]

        self._check_location_writable(location, force=force, tar=tar)

        # Check whether the required elements are cached, and then
        # try to pull them if they are not already cached.
        #
        self.query_cache(elements)
        self._pull_missing_artifacts(elements)

        try:
            scope = {
                _PipelineSelection.RUN: _Scope.RUN,
                _PipelineSelection.BUILD: _Scope.BUILD,
                _PipelineSelection.NONE: _Scope.NONE,
                _PipelineSelection.ALL: _Scope.ALL,
            }
            with element._prepare_sandbox(scope=scope[selection], integrate=integrate) as sandbox:
                # Copy or move the sandbox to the target directory
                virdir = sandbox.get_virtual_directory()
                self._export_artifact(tar, location, compression, element, hardlinks, virdir)
        except BstError as e:
            raise StreamError(
                "Error while staging dependencies into a sandbox" ": '{}'".format(e), detail=e.detail, reason=e.reason
            ) from e

    # _export_artifact()
    #
    # Export the files of the artifact/a tarball to a virtual directory
    #
    # Args:
    #    tar (bool): Whether we want to create a tarfile
    #    location (str): The name of the directory/the tarfile we want to export to/create
    #    compression (str): The type of compression for the tarball
    #    target (Element/ArtifactElement): The Element/ArtifactElement we want to checkout
    #    hardlinks (bool): Whether to checkout hardlinks instead of copying
    #    virdir (Directory): The sandbox's root directory as a virtual directory
    #
    def _export_artifact(self, tar, location, compression, target, hardlinks, virdir):
        if not tar:
            with target.timed_activity("Checking out files in '{}'".format(location)):
                try:
                    if hardlinks:
                        try:
                            utils.safe_remove(location)
                        except OSError as e:
                            raise StreamError("Failed to remove checkout directory: {}".format(e)) from e
                        virdir._export_files(location, can_link=True, can_destroy=True)
                    else:
                        virdir._export_files(location)
                except OSError as e:
                    raise StreamError("Failed to checkout files: '{}'".format(e)) from e
        else:
            to_stdout = location == "-"
            mode = _handle_compression(compression, to_stream=to_stdout)
            with target.timed_activity("Creating tarball"):
                if to_stdout:
                    # Save the stdout FD to restore later
                    saved_fd = os.dup(sys.stdout.fileno())
                    try:
                        with os.fdopen(sys.stdout.fileno(), "wb") as fo:
                            with tarfile.open(fileobj=fo, mode=mode) as tf:
                                virdir.export_to_tar(tf, ".")
                    finally:
                        # No matter what, restore stdout for further use
                        os.dup2(saved_fd, sys.stdout.fileno())
                        os.close(saved_fd)
                else:
                    with tarfile.open(location, mode=mode) as tf:
                        virdir.export_to_tar(tf, ".")

    # artifact_show()
    #
    # Show cached artifacts
    #
    # Args:
    #    targets (str): Targets to show the cached state of
    #
    def artifact_show(self, targets, *, selection=_PipelineSelection.NONE):
        # Obtain list of Element and/or ArtifactElement objects
        target_objects = self.load_selection(
            targets, selection=selection, connect_artifact_cache=True, load_artifacts=True
        )

        self.query_cache(target_objects)

        if self._artifacts.has_fetch_remotes():
            self._resolve_cached_remotely(target_objects)

        return target_objects

    # artifact_log()
    #
    # Show the full log of an artifact
    #
    # Args:
    #    targets (str): Targets to view the logs of
    #
    # Returns:
    #    logsdir (list): A list of CasBasedDirectory objects containing artifact logs
    #
    def artifact_log(self, targets):
        # Return list of Element and/or ArtifactElement objects
        target_objects = self.load_selection(targets, selection=_PipelineSelection.NONE, load_artifacts=True)

        self.query_cache(target_objects)

        artifact_logs = {}
        for obj in target_objects:
            ref = obj.get_artifact_name()
            if not obj._cached():
                self._context.messenger.warn("{} is not cached".format(ref))
                continue
            if not obj._cached_logs():
                self._context.messenger.warn("{} is cached without log files".format(ref))
                continue

            artifact_logs[obj.name] = obj._get_logs()

        return artifact_logs

    # artifact_list_contents()
    #
    # Show a list of content of an artifact
    #
    # Args:
    #    targets (str): Targets to view the contents of
    #
    # Returns:
    #    elements_to_files (Dict[str, Directory]): A list of tuples of the artifact name and it's contents
    #
    def artifact_list_contents(self, targets):
        # Return list of Element and/or ArtifactElement objects
        target_objects = self.load_selection(targets, selection=_PipelineSelection.NONE, load_artifacts=True)

        self.query_cache(target_objects)

        elements_to_files = {}
        for obj in target_objects:
            ref = obj.get_artifact_name()
            if not obj._cached():
                self._context.messenger.warn("{} is not cached".format(ref))
                obj.name = {ref: "No artifact cached"}
                continue
            if isinstance(obj, ArtifactElement):
                obj.name = ref

            # Just hand over a Directory here
            artifact = obj._get_artifact()
            files = artifact.get_files()
            elements_to_files[obj.name] = files

        return elements_to_files

    # artifact_delete()
    #
    # Remove artifacts from the local cache
    #
    # Args:
    #    targets (str): Targets to remove
    #
    def artifact_delete(self, targets, *, selection=_PipelineSelection.NONE):
        # Return list of Element and/or ArtifactElement objects
        target_objects = self.load_selection(targets, selection=selection, load_artifacts=True)

        self.query_cache(target_objects)

        # Some of the targets may refer to the same key, so first obtain a
        # set of the refs to be removed.
        remove_refs = set()
        for obj in target_objects:
            for key_strength in [_KeyStrength.STRONG, _KeyStrength.WEAK]:
                key = obj._get_cache_key(strength=key_strength)
                remove_refs.add(obj.get_artifact_name(key=key))

        ref_removed = False
        for ref in remove_refs:
            try:
                self._artifacts.remove(ref)
            except ArtifactError as e:
                self._context.messenger.warn(str(e))
                continue

            self._context.messenger.info("Removed: {}".format(ref))
            ref_removed = True

        if not ref_removed:
            self._context.messenger.info("No artifacts were removed")

    # source_checkout()
    #
    # Checkout sources of the target element to the specified location
    #
    # Args:
    #    target: The target element whose sources to checkout
    #    location: Location to checkout the sources to
    #    force: Whether to overwrite existing directories/tarfiles
    #    deps: The selection mode for the specified targets (_PipelineSelection)
    #    except_targets: List of targets to except from staging
    #    tar: Whether to write a tarfile holding the checkout contents
    #    compression: The type of compression for tarball
    #    include_build_scripts: Whether to include build scripts in the checkout
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    def source_checkout(
        self,
        target: str,
        *,
        location: Optional[str] = None,
        force: bool = False,
        deps=_PipelineSelection.NONE,
        except_targets: Iterable[str] = (),
        tar: bool = False,
        compression: Optional[str] = None,
        include_build_scripts: bool = False,
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_source_remotes: bool = False,
    ):

        self._check_location_writable(location, force=force, tar=tar)

        elements = self._load(
            (target,),
            selection=deps,
            except_targets=except_targets,
            connect_source_cache=True,
            source_remotes=source_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        # Assert all sources are cached in the source dir
        self.query_cache(elements, only_sources=True)
        self._fetch(elements)
        _pipeline.assert_sources_cached(self._context, elements)

        # Stage all sources determined by scope
        try:
            self._source_checkout(elements, location, force, deps, tar, compression, include_build_scripts)
        except BstError as e:
            raise StreamError(
                "Error while writing sources" ": '{}'".format(e), detail=e.detail, reason=e.reason
            ) from e

        self._context.messenger.info("Checked out sources to '{}'".format(location))

    # workspace_open
    #
    # Open a project workspace
    #
    # Args:
    #    targets (list): List of target elements to open workspaces for
    #    no_checkout (bool): Whether to skip checking out the source
    #    force (bool): Whether to ignore contents in an existing directory
    #    custom_dir (str): Custom location to create a workspace or false to use default location.
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    def workspace_open(
        self,
        targets: Iterable[str],
        *,
        no_checkout: bool = False,
        force: bool = False,
        custom_dir: Optional[str] = None,
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_source_remotes: bool = False,
    ):
        # This function is a little funny but it is trying to be as atomic as possible.

        elements = self._load(
            targets,
            selection=_PipelineSelection.REDIRECT,
            connect_source_cache=True,
            source_remotes=source_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        workspaces = self._context.get_workspaces()

        # If we're going to checkout, we need at least a fetch,
        #
        if not no_checkout:
            self.query_cache(elements, only_sources=True)
            self._fetch(elements, fetch_original=True)

        expanded_directories = []
        #  To try to be more atomic, loop through the elements and raise any errors we can early
        for target in elements:

            if not list(target.sources()):
                build_depends = [x.name for x in target._dependencies(_Scope.BUILD, recurse=False)]
                if not build_depends:
                    raise StreamError("The element {}  has no sources".format(target.name))
                detail = "Try opening a workspace on one of its dependencies instead:\n"
                detail += "  \n".join(build_depends)
                raise StreamError("The element {} has no sources".format(target.name), detail=detail)

            # Check for workspace config
            workspace = workspaces.get_workspace(target._get_full_name())
            if workspace:
                if not force:
                    raise StreamError(
                        "Element '{}' already has an open workspace defined at: {}".format(
                            target.name, workspace.get_absolute_path()
                        )
                    )
                if not no_checkout:
                    target.warn(
                        "Replacing existing workspace for element '{}' defined at: {}".format(
                            target.name, workspace.get_absolute_path()
                        )
                    )
                self.workspace_close(target._get_full_name(), remove_dir=not no_checkout)

            if not custom_dir:
                directory = os.path.abspath(os.path.join(self._context.workspacedir, target.name))
                if directory[-4:] == ".bst":
                    directory = directory[:-4]
                expanded_directories.append(directory)

        if custom_dir:
            if len(elements) != 1:
                raise StreamError(
                    "Exactly one element can be given if --directory is used",
                    reason="directory-with-multiple-elements",
                )
            directory = os.path.abspath(custom_dir)
            expanded_directories = [
                directory,
            ]
        else:
            # If this fails it is a bug in what ever calls this, usually cli.py and so can not be tested for via the
            # run bst test mechanism.
            assert len(elements) == len(expanded_directories)

        for target, directory in zip(elements, expanded_directories):
            if os.path.exists(directory):
                if not os.path.isdir(directory):
                    raise StreamError(
                        "For element '{}', Directory path is not a directory: {}".format(target.name, directory),
                        reason="bad-directory",
                    )

                if not (no_checkout or force) and os.listdir(directory):
                    raise StreamError(
                        "For element '{}', Directory path is not empty: {}".format(target.name, directory),
                        reason="bad-directory",
                    )
                if os.listdir(directory):
                    if force and not no_checkout:
                        utils._force_rmtree(directory)

        # So far this function has tried to catch as many issues as possible with out making any changes
        # Now it does the bits that can not be made atomic.
        targetGenerator = zip(elements, expanded_directories)
        for target, directory in targetGenerator:
            self._context.messenger.info("Creating workspace for element {}".format(target.name))

            workspace = workspaces.get_workspace(target._get_full_name())
            if workspace and not no_checkout:
                workspaces.delete_workspace(target._get_full_name())
                workspaces.save_config()
                utils._force_rmtree(directory)
            try:
                os.makedirs(directory, exist_ok=True)
            except OSError as e:
                todo_elements = " ".join([str(target.name) for target, directory_dict in targetGenerator])
                if todo_elements:
                    # This output should make creating the remaining workspaces as easy as possible.
                    todo_elements = "\nDid not try to create workspaces for " + todo_elements
                raise StreamError(
                    "Failed to create workspace directory: {}".format(e),
                    reason="workspace-directory-failure",
                    detail=todo_elements,
                ) from e

            workspaces.create_workspace(target, directory, checkout=not no_checkout)
            self._context.messenger.info("Created a workspace for element: {}".format(target._get_full_name()))

    # workspace_close
    #
    # Close a project workspace
    #
    # Args:
    #    element_name (str): The element name to close the workspace for
    #    remove_dir (bool): Whether to remove the associated directory
    #
    def workspace_close(self, element_name, *, remove_dir):
        self._assert_project("Unable to locate workspaces")

        workspaces = self._context.get_workspaces()
        workspace = workspaces.get_workspace(element_name)

        # Remove workspace directory if prompted
        if remove_dir:
            with self._context.messenger.timed_activity(
                "Removing workspace directory {}".format(workspace.get_absolute_path())
            ):
                try:
                    shutil.rmtree(workspace.get_absolute_path())
                except OSError as e:
                    raise StreamError("Could not remove  '{}': {}".format(workspace.get_absolute_path(), e)) from e

        # Delete the workspace and save the configuration
        workspaces.delete_workspace(element_name)
        workspaces.save_config()
        self._context.messenger.info("Closed workspace for {}".format(element_name))

    # workspace_reset
    #
    # Reset a workspace to its original state, discarding any user
    # changes.
    #
    # Args:
    #    targets (list of str): The target elements to reset the workspace for
    #    soft (bool): Only set the workspace state to not prepared
    #
    def workspace_reset(self, targets, *, soft):
        self._assert_project("Unable to locate workspaces")

        elements = self._load(targets, selection=_PipelineSelection.REDIRECT)

        nonexisting = []
        for element in elements:
            if not self.workspace_exists(element.name):
                nonexisting.append(element.name)
        if nonexisting:
            raise StreamError("Workspace does not exist", detail="\n".join(nonexisting))

        workspaces = self._context.get_workspaces()
        for element in elements:
            workspace = workspaces.get_workspace(element._get_full_name())
            workspace_path = workspace.get_absolute_path()

            if soft:
                workspace.last_build = None
                self._context.messenger.info(
                    "Reset workspace state for {} at: {}".format(element.name, workspace_path)
                )
                continue

            self.workspace_close(element._get_full_name(), remove_dir=True)
            workspaces.save_config()
            self.workspace_open([element._get_full_name()], no_checkout=False, force=True, custom_dir=workspace_path)

    # workspace_exists
    #
    # Check if a workspace exists
    #
    # Args:
    #    element_name (str): The element name to close the workspace for, or None
    #
    # Returns:
    #    (bool): True if the workspace exists
    #
    # If None is specified for `element_name`, then this will return
    # True if there are any existing workspaces.
    #
    def workspace_exists(self, element_name=None):
        self._assert_project("Unable to locate workspaces")

        workspaces = self._context.get_workspaces()
        if element_name:
            workspace = workspaces.get_workspace(element_name)
            if workspace:
                return True
        elif any(workspaces.list()):
            return True

        return False

    # workspace_list
    #
    # Serializes the workspaces and dumps them in YAML to stdout.
    #
    def workspace_list(self):
        self._assert_project("Unable to locate workspaces")

        workspaces = []
        for element_name, workspace_ in self._context.get_workspaces().list():
            workspace_detail = {
                "element": element_name,
                "directory": workspace_.get_absolute_path(),
            }
            workspaces.append(workspace_detail)

        _yaml.roundtrip_dump({"workspaces": workspaces})

    # redirect_element_names()
    #
    # Takes a list of element names and returns a list where elements have been
    # redirected to their source elements if the element file exists, and just
    # the name, if not.
    #
    # Args:
    #    elements (list of str): The element names to redirect
    #
    # Returns:
    #    (list of str): The element names after redirecting
    #
    def redirect_element_names(self, elements):
        element_dir = self._project.element_path
        load_elements = []
        output_elements = set()

        for e in elements:
            element_path = os.path.join(element_dir, e)
            if os.path.exists(element_path):
                load_elements.append(e)
            else:
                output_elements.add(e)
        if load_elements:
            loaded_elements = self._load(load_elements, selection=_PipelineSelection.REDIRECT)

            for e in loaded_elements:
                output_elements.add(e.name)

        return list(output_elements)

    # get_state()
    #
    # Get the State object owned by Stream
    #
    # Returns:
    #    State: The State object
    def get_state(self):
        return self._state

    #############################################################
    #                 Scheduler API forwarding                  #
    #############################################################

    # running
    #
    # Whether the scheduler is running
    #
    @property
    def running(self):
        return self._running

    # suspended
    #
    # Whether the scheduler is currently suspended
    #
    @property
    def suspended(self):
        return self._suspended

    # terminated
    #
    # Whether the scheduler is currently terminated
    #
    @property
    def terminated(self):
        return self._terminated

    # terminate()
    #
    # Terminate jobs
    #
    def terminate(self):
        self._scheduler.terminate()
        self._terminated = True

    # quit()
    #
    # Quit the session, this will continue with any ongoing
    # jobs, use Stream.terminate() instead for cancellation
    # of ongoing jobs
    #
    def quit(self):
        self._scheduler.stop()

    # suspend()
    #
    # Context manager to suspend ongoing jobs
    #
    @contextmanager
    def suspend(self):
        self._scheduler.suspend()
        self._suspended = True
        yield
        self._suspended = False
        self._scheduler.resume()

    # retry_job()
    #
    # Retry the indicated job
    #
    # Args:
    #    action_name: The unique identifier of the task
    #    unique_id: A unique_id to load an Element instance
    #
    def retry_job(self, action_name: str, unique_id: str) -> None:
        element = Plugin._lookup(unique_id)

        #
        # Update the state task group, remove the failed element
        #
        group = self._state.task_groups[action_name]
        group.failed_tasks.remove(element._get_full_name())

        #
        # Find the queue for this action name and requeue the element
        #
        queue = None
        for q in self.queues:
            if q.action_name == action_name:
                queue = q
        assert queue
        queue.enqueue([element])

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

    # _assert_project()
    #
    # Raises an assertion of a project was not loaded
    #
    # Args:
    #    message: The user facing error message, e.g. "Unable to load elements"
    #
    # Raises:
    #    A StreamError with reason "project-not-loaded" is raised if no project was loaded
    #
    def _assert_project(self, message: str) -> None:
        if not self._project:
            raise StreamError(
                message, detail="No project.conf or active workspace was located", reason="project-not-loaded"
            )

    # _fetch_subprojects()
    #
    # Fetch subprojects as part of the project and element loading process.
    #
    # Args:
    #    junctions (list of Element): The junctions to fetch
    #
    def _fetch_subprojects(self, junctions):
        self._reset()
        queue = FetchQueue(self._scheduler)
        queue.enqueue(junctions)
        self.queues = [queue]
        self._run()

    # _load_artifacts()
    #
    # Loads artifacts from target artifact refs
    #
    # Args:
    #    artifact_names (list): List of target artifact names to load
    #
    # Returns:
    #    (list): A list of loaded ArtifactElement
    #
    def _load_artifacts(self, artifact_names):
        with self._context.messenger.simple_task("Loading artifacts") as task:

            # Use a set here to avoid duplicates.
            #
            # ArtifactElement.new_from_artifact_name() will take care of ensuring
            # uniqueness of multiple artifact names which refer to the same artifact
            # (e.g., if both weak and strong names happen to be requested), here we
            # still need to ensure we generate a list that does not contain duplicates.
            #
            artifacts = set()
            for artifact_name in artifact_names:
                artifact = ArtifactElement.new_from_artifact_name(artifact_name, self._context, task)
                artifacts.add(artifact)

        ArtifactElement.clear_artifact_name_cache()
        ArtifactProject.clear_project_cache()
        return list(artifacts)

    # _load_elements()
    #
    # Loads elements from target names.
    #
    # This function is called with a list of lists, such that multiple
    # target groups may be specified. Element names specified in `targets`
    # are allowed to be redundant.
    #
    # Args:
    #    target_groups (list of lists): Groups of toplevel targets to load
    #
    # Returns:
    #    (tuple of lists): A tuple of Element object lists, grouped corresponding to target_groups
    #
    def _load_elements(self, target_groups):

        # First concatenate all the lists for the loader's sake
        targets = list(itertools.chain(*target_groups))

        with PROFILER.profile(Topics.LOAD_PIPELINE, "_".join(t.replace(os.sep, "-") for t in targets)):
            elements = self._project.load_elements(targets)

            # Now create element groups to match the input target groups
            elt_iter = iter(elements)
            element_groups = [[next(elt_iter) for i in range(len(group))] for group in target_groups]

            return tuple(element_groups)

    # _load_elements_from_targets
    #
    # Given the usual set of target element names/artifact refs, load
    # the `Element` objects required to describe the selection.
    #
    # The result is returned as a truple - firstly the loaded normal
    # elements, secondly the loaded "excepting" elements and lastly
    # the loaded artifact elements.
    #
    # Args:
    #    targets - The target element names/artifact refs
    #    except_targets - The names of elements to except
    #    rewritable - Whether to load the elements in re-writable mode
    #    valid_artifact_names: Whether artifact names are valid
    #
    # Returns:
    #    ([elements], [except_elements], [artifact_elements])
    #
    def _load_elements_from_targets(
        self,
        targets: Iterable[str],
        except_targets: Iterable[str],
        *,
        rewritable: bool = False,
        valid_artifact_names: bool = False,
    ) -> Tuple[List[Element], List[Element], List[Element]]:

        # First determine which of the user specified targets are artifact
        # names and which are element names.
        element_names, artifact_names = self._expand_and_classify_targets(
            targets, valid_artifact_names=valid_artifact_names
        )

        # We need a project in order to load elements
        if element_names:
            self._assert_project("Unable to load elements: {}".format(", ".join(element_names)))

        if self._project:
            self._project.load_context.set_rewritable(rewritable)

        # Load elements and except elements
        if element_names:
            elements, except_elements = self._load_elements([element_names, except_targets])
        else:
            elements, except_elements = [], []

        # Load artifacts
        if artifact_names:
            artifacts = self._load_artifacts(artifact_names)
        else:
            artifacts = []

        return elements, except_elements, artifacts

    # _resolve_cached_remotely()
    #
    # Checks whether the listed elements are currently cached in
    # any of their respectively configured remotes.
    #
    # Args:
    #    targets (list [Element]): The list of element targets
    #
    def _resolve_cached_remotely(self, targets):
        with self._context.messenger.simple_task("Querying remotes for cached status", silent_nested=True) as task:
            task.set_maximum_progress(len(targets))
            for element in targets:
                element._cached_remotely()
                task.add_current_progress()

    # _pull_missing_artifacts()
    #
    # Pull missing artifacts from available remotes, this runs the scheduler
    # just to pull the artifacts if any of the artifacts are missing locally,
    # and is used in commands which need to use the artifacts.
    #
    # This function requires Stream.query_cache() to be called in advance
    # in order to determine which artifacts to try and pull.
    #
    # Args:
    #    elements (list [Element]): The selected list of required elements
    #
    def _pull_missing_artifacts(self, elements):
        uncached_elts = [elt for elt in elements if elt._pull_pending()]
        if uncached_elts:
            self._context.messenger.info("Attempting to fetch missing or incomplete artifact(s)")
            self._reset()
            self._add_queue(PullQueue(self._scheduler))
            self._enqueue_plan(uncached_elts)
            self._run(announce_session=True)

    # _load_tracking()
    #
    # A variant of _load() to be used when the elements should be used
    # for tracking
    #
    # If `targets` is not empty used project configuration will be
    # fully loaded.
    #
    # Args:
    #    targets (list of str): Targets to load
    #    selection (_PipelineSelection): The selection mode for the specified targets
    #    except_targets (list of str): Specified targets to except
    #    cross_junctions (bool): Whether tracking should cross junction boundaries
    #
    # Returns:
    #    (list of Element): The tracking element selection
    #
    def _load_tracking(self, targets, *, selection=_PipelineSelection.NONE, except_targets=(), cross_junctions=False):
        elements, except_elements, artifacts = self._load_elements_from_targets(
            targets, except_targets, rewritable=True
        )

        # We can't track artifact refs, since they have no underlying
        # elements or sources to interact with. Abort if the user asks
        # us to do that.
        if artifacts:
            detail = "\n".join(artifact.get_artifact_name() for artifact in artifacts)
            raise ArtifactElementError("Cannot perform this operation with artifact refs:", detail=detail)

        # Hold on to the targets
        self.targets = elements

        track_projects = {}
        for element in elements:
            project = element._get_project()
            if project not in track_projects:
                track_projects[project] = [element]
            else:
                track_projects[project].append(element)

        track_selected = []

        for project, project_elements in track_projects.items():
            selected = _pipeline.get_selection(self._context, project_elements, selection)
            selected = self._track_cross_junction_filter(project, selected, cross_junctions)
            track_selected.extend(selected)

        return _pipeline.except_elements(elements, track_selected, except_elements)

    # _track_cross_junction_filter()
    #
    # Filters out elements which are across junction boundaries,
    # otherwise asserts that there are no such elements.
    #
    # This is currently assumed to be only relevant for element
    # lists targetted at tracking.
    #
    # Args:
    #    project (Project): Project used for cross_junction filtering.
    #                       All elements are expected to belong to that project.
    #    elements (list of Element): The list of elements to filter
    #    cross_junction_requested (bool): Whether the user requested
    #                                     cross junction tracking
    #
    # Returns:
    #    (list of Element): The filtered or asserted result
    #
    def _track_cross_junction_filter(self, project, elements, cross_junction_requested):

        # First filter out cross junctioned elements
        if not cross_junction_requested:
            elements = [element for element in elements if element._get_project() is project]

        # We can track anything if the toplevel project uses project.refs
        #
        if self._project.ref_storage == ProjectRefStorage.PROJECT_REFS:
            return elements

        # Ideally, we would want to report every cross junction element but not
        # their dependencies, unless those cross junction elements dependencies
        # were also explicitly requested on the command line.
        #
        # But this is too hard, lets shoot for a simple error.
        for element in elements:
            element_project = element._get_project()
            if element_project is not self._project:
                detail = (
                    "Requested to track sources across junction boundaries\n"
                    + "in a project which does not use project.refs ref-storage."
                )
                raise StreamError("Untrackable sources", detail=detail, reason="untrackable-sources")

        return elements

    # _load()
    #
    # A convenience method for loading element lists
    #
    # If `targets` is not empty used project configuration will be
    # fully loaded.
    #
    # Args:
    #    targets: Main targets to load
    #    selection: The selection mode for the specified targets  (_PipelineSelection)
    #    except_targets: Specified targets to except from fetching
    #    ignore_junction_targets (bool): Whether junction targets should be filtered out
    #    dynamic_plan: Require artifacts as needed during the build
    #    load_artifacts: Whether to load artifacts with artifact names
    #    attempt_artifact_metadata: Whether to attempt to download artifact metadata in
    #                                      order to deduce build dependencies and reload.
    #    connect_artifact_cache: Whether to try to contact remote artifact caches
    #    connect_source_cache: Whether to try to contact remote source caches
    #    artifact_remotes: Artifact cache remotes specified on the commmand line
    #    source_remotes: Source cache remotes specified on the commmand line
    #    ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
    #    ignore_project_source_remotes: Whether to ignore source remotes specified by projects
    #
    # Returns:
    #    (list of Element): The primary element selection
    #
    def _load(
        self,
        targets: Iterable[str],
        *,
        selection: str = _PipelineSelection.NONE,
        except_targets: Iterable[str] = (),
        ignore_junction_targets: bool = False,
        dynamic_plan: bool = False,
        load_artifacts: bool = False,
        attempt_artifact_metadata: bool = False,
        connect_artifact_cache: bool = False,
        connect_source_cache: bool = False,
        artifact_remotes: Iterable[RemoteSpec] = (),
        source_remotes: Iterable[RemoteSpec] = (),
        ignore_project_artifact_remotes: bool = False,
        ignore_project_source_remotes: bool = False,
    ):
        elements, except_elements, artifacts = self._load_elements_from_targets(
            targets, except_targets, rewritable=False, valid_artifact_names=load_artifacts
        )

        if artifacts:
            if selection in (_PipelineSelection.ALL, _PipelineSelection.RUN):
                raise StreamError(
                    "Error: '--deps {}' is not supported for artifact names".format(selection),
                    reason="deps-not-supported",
                )

        if ignore_junction_targets:
            elements = [e for e in elements if e.get_kind() != "junction"]

        # Hold on to the targets
        self.targets = elements

        # Connect to remote caches, this needs to be done before resolving element state
        self._context.initialize_remotes(
            connect_artifact_cache,
            connect_source_cache,
            artifact_remotes,
            source_remotes,
            ignore_project_artifact_remotes=ignore_project_artifact_remotes,
            ignore_project_source_remotes=ignore_project_source_remotes,
        )

        # In some cases we need to have an actualized artifact, with all of
        # it's metadata, such that we can derive attributes about the artifact
        # like it's build dependencies.
        if artifacts and attempt_artifact_metadata:
            #
            # FIXME: We need a semantic here to download only the metadata
            #
            for element in artifacts:
                element._set_required(_Scope.NONE)

            self.query_cache(artifacts)

            self._reset()
            self._add_queue(PullQueue(self._scheduler))
            self._enqueue_plan(artifacts)
            self._run()

            #
            # After obtaining the metadata for the toplevel specified artifact
            # targets, we need to reload just the artifacts.
            #
            artifact_targets = [e.get_artifact_name() for e in artifacts]
            _, _, artifacts = self._load_elements_from_targets(
                artifact_targets, [], rewritable=False, valid_artifact_names=True
            )

            # It can be that new remotes have been added by way of loading new
            # projects referenced by the new artifact elements, so we need to
            # ensure those remotes are also initialized.
            #
            self._context.initialize_remotes(
                connect_artifact_cache,
                connect_source_cache,
                artifact_remotes,
                source_remotes,
                ignore_project_artifact_remotes=ignore_project_artifact_remotes,
                ignore_project_source_remotes=ignore_project_source_remotes,
            )

        self.targets += artifacts

        # Now move on to loading primary selection.
        #
        selected = _pipeline.get_selection(
            self._context, self.targets, selection, silent=False, depth_sort=dynamic_plan
        )
        selected = _pipeline.except_elements(self.targets, selected, except_elements)

        # Mark the appropriate required elements
        #
        required_elements: List[Element] = []
        if dynamic_plan:
            #
            # In a dynamic build plan, we only require the top-level targets and
            # rely on state changes during processing to determine which elements
            # must be processed.
            #
            if selection == _PipelineSelection.NONE:
                required_elements = elements
            elif selection == _PipelineSelection.BUILD:
                required_elements = list(_pipeline.dependencies(elements, _Scope.BUILD, recurse=False))

        # Without a dynamic build plan, or if `all` selection was made, then everything is required
        if not required_elements:
            required_elements = selected

        for element in required_elements:
            element._set_required()

        return selected

    # _reset()
    #
    # Resets the internal state related to a given scheduler run.
    #
    # Invocations to the scheduler should start with a _reset() and end
    # with _run() like so:
    #
    #  self._reset()
    #  self._add_queue(...)
    #  self._add_queue(...)
    #  self._enqueue_plan(...)
    #  self._run()
    #
    def _reset(self):
        self._scheduler.clear_queues()
        self.session_elements = []
        self.total_elements = []

    # _add_queue()
    #
    # Adds a queue to the stream
    #
    # Args:
    #    queue (Queue): Queue to add to the pipeline
    #
    def _add_queue(self, queue, *, track=False):
        if not track and not self.queues:
            # First non-track queue
            queue.set_required_element_check()

        self.queues.append(queue)

    # _enqueue_plan()
    #
    # Enqueues planned elements to the specified queue.
    #
    # Args:
    #    plan (list of Element): The list of elements to be enqueued
    #    queue (Queue): The target queue, defaults to the first queue
    #
    def _enqueue_plan(self, plan, *, queue=None):
        queue = queue or self.queues[0]
        queue.enqueue(plan)
        self.session_elements += plan

    # _run()
    #
    # Common function for running the scheduler
    #
    # Args:
    #    announce_session (bool): Whether to announce the session in the frontend.
    #
    def _run(self, *, announce_session: bool = False):

        # Inform the frontend of the full list of elements
        # and the list of elements which will be processed in this run
        #
        self.total_elements = list(_pipeline.dependencies(self.targets, _Scope.ALL))

        if announce_session and self._session_start_callback is not None:
            self._session_start_callback()

        self._running = True
        status = self._scheduler.run(self.queues, self._context.get_cascache().get_casd_process_manager())
        self._running = False

        if status == SchedStatus.ERROR:
            raise StreamError()
        if status == SchedStatus.TERMINATED:
            raise StreamError(terminated=True)

    # _fetch()
    #
    # Performs the fetch job, the body of this function is here because
    # it is shared between a few internals.
    #
    # Args:
    #    elements (list of Element): Elements to fetch
    #    fetch_original (bool): Whether to fetch original unstaged
    #    announce_session (bool): Whether to announce the session in the frontend
    #
    def _fetch(self, elements: List[Element], *, fetch_original: bool = False, announce_session: bool = False):

        # Assert consistency for the fetch elements
        _pipeline.assert_consistent(self._context, elements)

        # Construct queues, enqueue and run
        #
        self._reset()
        self._add_queue(FetchQueue(self._scheduler, fetch_original=fetch_original))
        self._enqueue_plan(elements)
        self._run(announce_session=announce_session)

    # _check_location_writable()
    #
    # Check if given location is writable.
    #
    # Args:
    #    location (str): Destination path
    #    force (bool): Allow files to be overwritten
    #    tar (bool): Whether destination is a tarball
    #
    # Raises:
    #    (StreamError): If the destination is not writable
    #
    def _check_location_writable(self, location, force=False, tar=False):
        if not tar:
            try:
                os.makedirs(location, exist_ok=True)
            except OSError as e:
                raise StreamError("Failed to create destination directory: '{}'".format(e)) from e
            if not os.access(location, os.W_OK):
                raise StreamError("Destination directory '{}' not writable".format(location))
            if not force and os.listdir(location):
                raise StreamError("Destination directory '{}' not empty".format(location))
        elif os.path.exists(location) and location != "-":
            if not os.access(location, os.W_OK):
                raise StreamError("Output file '{}' not writable".format(location))
            if not force and os.path.exists(location):
                raise StreamError("Output file '{}' already exists".format(location))

    # Helper function for source_checkout()
    def _source_checkout(
        self,
        elements,
        location=None,
        force=False,
        deps="none",
        tar=False,
        compression=None,
        include_build_scripts=False,
    ):
        location = os.path.abspath(location)

        # Stage all our sources in a temporary directory. The this
        # directory can be used to either construct a tarball or moved
        # to the final desired location.
        temp_source_dir = tempfile.TemporaryDirectory(dir=self._context.tmpdir)  # pylint: disable=consider-using-with
        try:
            self._write_element_sources(temp_source_dir.name, elements)
            if include_build_scripts:
                self._write_build_scripts(temp_source_dir.name, elements)
            if tar:
                self._create_tarball(temp_source_dir.name, location, compression)
            else:
                self._move_directory(temp_source_dir.name, location, force)
        except OSError as e:
            raise StreamError("Failed to checkout sources to {}: {}".format(location, e)) from e
        finally:
            with suppress(FileNotFoundError):
                temp_source_dir.cleanup()

    # Move a directory src to dest. This will work across devices and
    # may optionaly overwrite existing files.
    def _move_directory(self, src, dest, force=False):
        def is_empty_dir(path):
            return os.path.isdir(dest) and not os.listdir(dest)

        try:
            os.rename(src, dest)
            return
        except OSError:
            pass

        if force or is_empty_dir(dest):
            try:
                utils.link_files(src, dest)
            except utils.UtilError as e:
                raise StreamError("Failed to move directory: {}".format(e)) from e

    # Write the element build script to the given directory
    def _write_element_script(self, directory, element):
        try:
            element._write_script(directory)
        except ImplError:
            return False
        return True

    # Write all source elements to the given directory
    def _write_element_sources(self, directory, elements):
        for element in elements:
            element_source_dir = self._get_element_dirname(directory, element)
            if list(element.sources()):
                os.makedirs(element_source_dir)
                element._stage_sources_at(element_source_dir)

    # Create a tarball from the content of directory
    def _create_tarball(self, directory, tar_name, compression):
        if compression is None:
            compression = ""
        mode = _handle_compression(compression)
        try:
            with utils.save_file_atomic(tar_name, mode="wb") as f, tarfile.open(fileobj=f, mode=mode) as tarball:
                for item in os.listdir(str(directory)):
                    file_to_add = os.path.join(directory, item)
                    tarball.add(file_to_add, arcname=item)
        except OSError as e:
            raise StreamError("Failed to create tar archive: {}".format(e)) from e

    # Write all the build_scripts for elements in the directory location
    def _write_build_scripts(self, location, elements):
        for element in elements:
            self._write_element_script(location, element)
        self._write_master_build_script(location, elements)

    # Write a master build script to the sandbox
    def _write_master_build_script(self, directory, elements):

        module_string = ""
        for element in elements:
            module_string += shlex.quote(element.normal_name) + " "

        script_path = os.path.join(directory, "build.sh")

        with open(_site.build_all_template, "r", encoding="utf-8") as f:
            script_template = f.read()

        with utils.save_file_atomic(script_path, "w") as script:
            script.write(script_template.format(modules=module_string))

        os.chmod(script_path, stat.S_IEXEC | stat.S_IREAD)

    # _get_element_dirname()
    #
    # Get path to directory for an element based on its normal name.
    #
    # For cross-junction elements, the path will be prefixed with the name
    # of the junction element.
    #
    # Args:
    #    directory (str): path to base directory
    #    element (Element): the element
    #
    # Returns:
    #    (str): Path to directory for this element
    #
    def _get_element_dirname(self, directory, element):
        parts = [element.normal_name]
        while element._get_project() != self._project:
            element = element._get_project().junction
            parts.append(element.normal_name)

        return os.path.join(directory, *reversed(parts))

    # _expand_and_classify_targets()
    #
    # Takes the user provided targets, expand any glob patterns, and
    # return a new list of targets.
    #
    # If valid_artifact_names is specified, then glob patterns will
    # also be checked for locally existing artifact names, and the
    # targets will be classified into separate lists, any targets
    # which are found to be an artifact name will be returned in
    # the list of artifact names.
    #
    # Args:
    #    targets: A list of targets
    #    valid_artifact_names: Whether artifact names are valid
    #
    # Returns:
    #    (list): element names present in the targets
    #    (list): artifact names present in the targets
    #
    def _expand_and_classify_targets(
        self, targets: Iterable[str], valid_artifact_names: bool = False
    ) -> Tuple[List[str], List[str]]:
        #
        # We use dicts here instead of sets, in order to deduplicate any possibly duplicate
        # entries, while also retaining the original order of element specification/discovery,
        # (which we cannot do with sets).
        #
        element_names = {}
        artifact_names = {}
        element_globs = {}
        artifact_globs = {}

        # First sort out globs and targets
        for target in targets:
            if any(c in "*?[" for c in target):
                if target.endswith(".bst"):
                    element_globs[target] = True
                else:
                    artifact_globs[target] = True
            elif target.endswith(".bst"):
                element_names[target] = True
            else:
                artifact_names[target] = True

        # Bail out in commands which don't support artifacts if any of the targets
        # or globs did not end with the expected '.bst' suffix.
        #
        if (artifact_names or artifact_globs) and not valid_artifact_names:
            raise StreamError(
                "Invalid element names or element glob patterns were specified: {}".format(
                    ", ".join(list(artifact_names) + list(artifact_globs))
                ),
                reason="invalid-element-names",
                detail="Element names and element glob expressions must end in '.bst'",
            )

        # Verify targets which were not classified as elements
        for artifact_name in artifact_names:
            try:
                verify_artifact_ref(artifact_name)
            except ArtifactElementError as e:
                raise StreamError(
                    "Specified target does not appear to be an artifact or element name: {}".format(artifact_name),
                    reason="unrecognized-target-format",
                    detail="Element names and element glob expressions must end in '.bst'",
                ) from e

        # Expand globs for elements
        if element_globs:

            # Bail out if an element glob is specified without providing a project directory
            if not self._project:
                raise StreamError(
                    "Element glob expressions were specified without any project directory: {}".format(
                        ", ".join(element_globs)
                    ),
                    reason="glob-elements-without-project",
                )

            # Collect a list of `all_elements` in the project, stripping out the leading
            # project directory and element path prefix, to produce only element names.
            #
            all_elements = []
            element_path_length = len(self._project.element_path) + 1
            for dirpath, _, filenames in os.walk(self._project.element_path):
                for filename in filenames:
                    if filename.endswith(".bst"):
                        element_name = os.path.join(dirpath, filename)
                        element_name = element_name[element_path_length:]
                        all_elements.append(element_name)

            # Glob the elements and add the results to the set
            #
            for glob in element_globs:
                glob_results = list(utils.glob(all_elements, glob))
                for element_name in glob_results:
                    element_names[element_name] = True
                if not glob_results:
                    self._context.messenger.warn("No elements matched the glob expression: {}".format(glob))

        # Glob the artifact names and add the results to the set
        #
        for glob in artifact_globs:
            glob_results = self._artifacts.list_artifacts(glob=glob)
            for artifact_name in glob_results:
                artifact_names[artifact_name] = True
            if not glob_results:
                self._context.messenger.warn("No artifact names matched the glob expression: {}".format(glob))

        return list(element_names), list(artifact_names)


# _handle_compression()
#
# Return the tarfile mode str to be used when creating a tarball
#
# Args:
#    compression (str): The type of compression (either 'gz', 'xz' or 'bz2')
#    to_stdout (bool): Whether we want to open a stream for writing
#
# Returns:
#    (str): The tarfile mode string
#
def _handle_compression(compression, *, to_stream=False):
    mode_prefix = "w|" if to_stream else "w:"
    return mode_prefix + compression
