# Copyright 2017 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Build stages related to a secondary workspace directory.

A workspace is a compelete ChromeOS checkout and may contain it's own chroot,
.cache directory, etc. Conceptually, cbuildbot_launch creates a workspace for
the intitial ChromeOS build, but these stages are for creating a secondary
build.

This might be useful if a build needs to work with more than one branch at a
time, or make changes to ChromeOS code without changing the code it is currently
running.

A secondary workspace may not be inside an existing ChromeOS repo checkout.
Also, the initial sync will usually take about 40 minutes, so performance should
be considered carefully.
"""

import dataclasses
import logging
import os
from pathlib import Path
import re
from typing import Tuple

from chromite.cbuildbot import cbuildbot_alerts
from chromite.cbuildbot import cbuildbot_run
from chromite.cbuildbot import commands
from chromite.cbuildbot import manifest_version
from chromite.cbuildbot import trybot_patch_pool
from chromite.cbuildbot.stages import artifact_stages
from chromite.cbuildbot.stages import generic_stages
from chromite.lib import buildbucket_v2
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import cros_sdk_lib
from chromite.lib import failures_lib
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import portage_util
from chromite.lib import request_build
from chromite.lib import timeout_util
from chromite.lib.parser import package_info
from chromite.service import android


BUILD_PACKAGES_PREBUILTS = "10774.0.0"
BUILD_IMAGE_BUILDER_PATH = "8183.0.0"
BUILD_IMAGE_ECLEAN_FLAG = "8318.0.0"
ANDROID_BREAKPAD = "9667.0.0"
PORTAGE_2_3_75_UPDATE = "12693.0.0"
SETUP_BOARD_PORT_COMPLETE = "11802.0.0"
BUILD_PACKAGES_PORT_COMPLETE = "14950.0.0"


class InvalidWorkspace(failures_lib.StepFailure):
    """Raised when a workspace isn't usable."""


def ChrootArgs(options):
    """cros_sdk command line arguments.

    To ensure consistent arguments passed into cros_sdk for workspace stages,
    compute them here.

    Args:
        options: self._run.options

    Returns:
        List of command line arguments, normally passed into run as chroot_args.
    """
    chroot_args = ["--cache-dir", options.cache_dir]
    if options.chrome_root:
        chroot_args += ["--chrome_root", options.chrome_root]

    return chroot_args


class WorkspaceStageBase(generic_stages.BuilderStage):
    """Base class for Workspace stages."""

    def __init__(self, builder_run, buildstore, build_root, **kwargs) -> None:
        """Initializer.

        Properties for subclasses:
          self._build_root to access the workspace directory,
          self._orig_root to access the original buildroot.

        Args:
            builder_run: BuilderRun object.
            buildstore: BuildStore instance to make DB calls with.
            build_root: Fully qualified path to use as a string.
        """
        super().__init__(
            builder_run, buildstore, build_root=build_root, **kwargs
        )

        self._orig_root = builder_run.buildroot

    def GetWorkspaceRepo(self):
        """Fetch a repo object for the workspace.

        Returns:
            repository.RepoRepository instance for the workspace.
        """
        # TODO: Properly select the manifest. Currently hard coded to internal
        # branch checkouts.
        manifest_url = config_lib.GetSiteParams().MANIFEST_INT_URL

        # Workspace repos use the workspace URL / branch.
        return self.GetRepoRepository(
            manifest_repo_url=manifest_url,
            branch=self._run.config.workspace_branch,
        )

    def GetWorkspaceVersionInfo(self):
        """Fetch a VersionInfo for the workspace.

        Only valid after the workspace has been synced.

        Returns:
            manifest-version.VersionInfo object based on the workspace checkout.
        """
        return commands.GetBuildrootVersionInfo(self._build_root)

    def AfterLimit(self, limit):
        """Is workspace version newer than cutoff limit?

        Args:
            limit: String version of format '123.0.0'

        Returns:
            bool: True if workspace has newer version than limit.
        """
        return commands.IsBuildRootAfterLimit(self._build_root, limit)

    # Standardize manifest_versions paths for workspaces.

    @property
    def int_manifest_versions_path(self):
        """Path to use for internal manifest_versions."""
        return os.path.join(
            self._orig_root,
            config_lib.GetSiteParams().INTERNAL_MANIFEST_VERSIONS_PATH,
        )

    @property
    def ext_manifest_versions_path(self):
        """Path to use for external manifest_versions."""
        return os.path.join(
            self._orig_root,
            config_lib.GetSiteParams().EXTERNAL_MANIFEST_VERSIONS_PATH,
        )

    def GetWorkspaceReleaseTag(self):
        workspace_version_info = self.GetWorkspaceVersionInfo()

        if self._run.options.debug:
            build_identifier, _ = self._run.GetCIDBHandle()
            build_id = build_identifier.cidb_id
            return "R%s-%s-b%s" % (
                workspace_version_info.chrome_branch,
                workspace_version_info.VersionString(),
                build_id,
            )
        else:
            return "R%s-%s" % (
                workspace_version_info.chrome_branch,
                workspace_version_info.VersionString(),
            )


class SyncStage(WorkspaceStageBase):
    """Perform a repo sync."""

    category = constants.CI_INFRA_STAGE

    def __init__(
        self,
        builder_run,
        buildstore,
        build_root,
        external=False,
        branch=None,
        version=None,
        patch_pool=None,
        copy_repo=None,
        **kwargs,
    ) -> None:
        """Initializer.

        Args:
            builder_run: BuilderRun object.
            buildstore: BuildStore instance to make DB calls with.
            build_root: Path to sync into.
            external: Boolean telling if this an internal or external checkout.
            branch: Branch to sync, with default to master.
            version: Version number to sync too.
            patch_pool: None or a list of lib.patch.GerritPatch objects.
            copy_repo: None, or the copy of a repo to seed the sync from.
        """
        super().__init__(
            builder_run, buildstore, build_root=build_root, **kwargs
        )

        self.external = external
        self.branch = branch
        self.version = version
        self.patch_pool = patch_pool
        self.copy_repo = copy_repo

    def PerformStage(self) -> None:
        """Sync stuff!"""
        logging.info("SubWorkspaceSync")

        cmd = [
            constants.CHROMITE_DIR / "scripts" / "repo_sync_manifest",
            "--repo-root",
            self._build_root,
            "--manifest-versions-int",
            self.int_manifest_versions_path,
            "--manifest-versions-ext",
            self.ext_manifest_versions_path,
        ]

        if self.external:
            cmd += ["--external"]

        if self.branch and not self.version:
            cmd += ["--branch", self.branch]

        if self.version:
            cbuildbot_alerts.PrintBuildbotStepText("Version: %s" % self.version)
            cmd += ["--version", self.version]

        if self.patch_pool:
            patch_options = []
            for patch in self.patch_pool:
                cbuildbot_alerts.PrintBuildbotLink(str(patch), patch.url)
                patch_options += ["--gerrit-patches", patch.gerrit_number_str]

            cmd += patch_options

        if self.copy_repo:
            cmd += ["--copy-repo", self.copy_repo]

        assert not (
            self.version and self.patch_pool
        ), 'Can\'t cherry-pick "%s" into an official version "%s."' % (
            patch_options,
            self.version,
        )

        cros_build_lib.run(cmd)


class WorkspaceSyncStage(WorkspaceStageBase):
    """Checkout both infra and workspace repos."""

    category = constants.CI_INFRA_STAGE

    def PerformStage(self) -> None:
        """Sync all the stuff!"""
        # Select changes to cherry-pick into the build, and filter them into
        # chromite versus branch changes.
        patch_pool = trybot_patch_pool.TrybotPatchPool.FromOptions(
            gerrit_patches=self._run.options.gerrit_patches
        )

        infra_pool = patch_pool.FilterFn(trybot_patch_pool.ChromiteFilter)
        branch_pool = patch_pool.FilterFn(
            trybot_patch_pool.ChromiteFilter, negate=True
        )

        infra_branch = self._run.manifest_branch

        SyncStage(
            self._run,
            self.buildstore,
            build_root=self._orig_root,
            external=True,
            branch=infra_branch,
            patch_pool=infra_pool,
            suffix=" [Infra %s]" % infra_branch,
        ).Run()

        branch = self._run.config.workspace_branch

        SyncStage(
            self._run,
            self.buildstore,
            build_root=self._build_root,
            external=not self._run.config.internal,
            branch=branch,
            version=self._run.options.force_version,
            patch_pool=branch_pool,
            copy_repo=self._orig_root,
            suffix=" [%s]" % branch,
        ).Run()


class WorkspaceSyncChromeStage(WorkspaceStageBase):
    """Stage that syncs Chrome sources if needed."""

    category = constants.PRODUCT_CHROME_STAGE

    # 12 hours in seconds should be long enough to fetch Chrome. I hope.
    SYNC_CHROME_TIMEOUT = 12 * 60 * 60

    def DetermineChromeVersion(self):
        pkg_info = portage_util.PortageqBestVisible(
            constants.CHROME_CP, cwd=self._build_root
        )
        return pkg_info.version.partition("_")[0]

    @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
    def PerformStage(self) -> None:
        chrome_version = self.DetermineChromeVersion()

        cbuildbot_alerts.PrintBuildbotStepText("tag %s" % chrome_version)

        git_cache_dir = (
            self._run.options.chrome_preload_dir
            or self._run.options.git_cache_dir
        )
        with timeout_util.Timeout(self.SYNC_CHROME_TIMEOUT):
            commands.SyncChrome(
                self._orig_root,
                self._run.options.chrome_root,
                self._run.config.useflags,
                tag=chrome_version,
                git_cache_dir=git_cache_dir,
                workspace=self._build_root,
            )


class WorkspaceUprevStage(WorkspaceStageBase):
    """Uprev ebuilds.

    This stage updates ebuilds to top of branch with no verification, or
    prebuilt generation. This is generally intended only for branch builds.
    """

    config_name = "uprev"

    def __init__(self, builder_run, buildstore, boards=None, **kwargs) -> None:
        super().__init__(builder_run, buildstore, **kwargs)
        if boards is not None:
            self._boards = boards

    def PerformStage(self) -> None:
        """Perform the uprev."""
        commands.UprevPackages(
            self._orig_root,
            self._boards,
            overlay_type=self._run.config.overlays,
            workspace=self._build_root,
        )


class WorkspacePublishStage(WorkspaceStageBase):
    """Publish ebuilds."""

    config_name = "push_overlays"

    def PerformStage(self) -> None:
        """Perform the push."""
        logging.info("Pushing.")
        commands.UprevPush(
            self._orig_root,
            overlay_type=self._run.config.push_overlays,
            dryrun=self._run.options.debug,
            workspace=self._build_root,
        )


class WorkspacePublishBuildspecStage(WorkspaceStageBase):
    """Increment the ChromeOS version, and publish a buildspec."""

    def PerformStage(self) -> None:
        """Increment ChromeOS version, and publish buildpec."""
        repo = self.GetWorkspaceRepo()

        # TODO: Add 'patch' support somehow,
        if repo.branch in ("main", "master"):
            incr_type = "build"
        else:
            incr_type = "branch"

        build_spec_path = manifest_version.GenerateAndPublishOfficialBuildSpec(
            repo,
            incr_type,
            manifest_versions_int=self.int_manifest_versions_path,
            manifest_versions_ext=self.ext_manifest_versions_path,
            dryrun=self._run.options.debug,
        )

        if self._run.options.debug:
            msg = "DEBUG: Would have defined: %s" % build_spec_path
        else:
            msg = "Defined: %s" % build_spec_path

        cbuildbot_alerts.PrintBuildbotStepText(msg)


class WorkspaceScheduleChildrenStage(WorkspaceStageBase):
    """Schedule child builds for this buildspec."""

    def PerformStage(self) -> None:
        """Schedule child builds for this buildspec."""
        # build_identifier, _ = self._run.GetCIDBHandle()
        # build_id = build_identifier.cidb_id
        # master_buildbucket_id = self._run.options.buildbucket_id
        version_info = self.GetWorkspaceVersionInfo()

        extra_args = [
            "--buildbot",
            "--version",
            version_info.VersionString(),
        ]

        if self._run.options.debug:
            extra_args.append("--debug")

        for child_name in self._run.config.slave_configs:
            raw_request = request_build.RequestBuild(
                build_config=child_name,
                branch=self._run.manifest_branch,
                # See crbug.com/940969. These id's get children killed during
                # multiple quick builds.
                # master_cidb_id=build_id,
                # master_buildbucket_id=master_buildbucket_id,
                extra_args=extra_args,
            )
            request = raw_request.CreateBuildRequest()
            buildbucket_client = buildbucket_v2.BuildbucketV2()

            if self._run.options.debug:
                logging.info(
                    "Build_name %s request_branch %s",
                    child_name,
                    raw_request.branch,
                )
                continue
            result = buildbucket_client.ScheduleBuild(
                request_id=str(request["request_id"]),
                builder=request["builder"],
                properties=request["properties"],
                tags=request["tags"],
                dimensions=request["dimensions"],
            )

            logging.info(
                "Build_name %s buildbucket_id %s created_timestamp %s",
                child_name,
                result.id,
                result.create_time.ToJsonString(),
            )
            cbuildbot_alerts.PrintBuildbotLink(
                child_name, f"{constants.CHROMEOS_MILO_HOST}{result.id}"
            )


class WorkspaceInitSDKStage(WorkspaceStageBase):
    """Stage that is responsible for initializing the SDK."""

    category = constants.CI_INFRA_STAGE

    def PerformStage(self) -> None:
        chroot_path = os.path.join(
            self._build_root, constants.DEFAULT_CHROOT_DIR
        )

        # Worksapce chroots are always wiped by cleanup stage, no need to
        # update.
        cmd = ["cros_sdk", "--create"] + ChrootArgs(self._run.options)

        commands.RunBuildScript(
            self._build_root,
            cmd,
            chromite_cmd=True,
            extra_env=self._portage_extra_env,
        )

        post_ver = cros_sdk_lib.GetChrootVersion(chroot_path)
        cbuildbot_alerts.PrintBuildbotStepText(post_ver)


@dataclasses.dataclass
class MountPathInfo:
    """Simple object to hold data about where a chroot path gets mounted.

    Attributes:
        chroot_path: The absolute path inside the chroot that gets mounted.
        old_style_path: The host-absolute path to which the chroot_path was
            mounted for older branches.
        new_style_path: The host-absolute path to which the chroot_path is
            mounted for new branches (and tip-of-tree).
    """

    chroot_path: Path
    old_style_path: Path
    new_style_path: Path


class WorkspaceLinkMountPathsStage(WorkspaceStageBase):
    """Stage that sets up symlinks to let us access new-style mount paths.

    Paths inside the chroot are accessible from outside the chroot via
    well-known mount paths. However, in 2023 several of those mount paths have
    changed.

    This causes a problem when cbuildbot tries to convert an inside-path to a
    host-absolute path for a workspace branch. Cbuildbot runs from tip-of-tree,
    so it will return the new-style mounted path, even if the workspace branch's
    chroot still uses old-style mounting logic.

    This stage solves that problem by creating symlinks from the new-style mount
    paths to the old-style paths. That way, if tip-of-tree cbuildbot reports
    that a file should be found at a new-style location, it will work even if
    the file is actually mounted to the old-style location.

    This is a quick fix, because workspace builders are expected to be fully
    deleted in 2023.

    This class currently ignores `/out` mounting, because cbuildbot doesn't seem
    to rely on `/out`, and because the symlink would need to somehow contain
    other symlinks, which seems gnarly. `/out` mounting was added in 15439.0.0;
    see http://crrev.com/c/4477625.
    """

    category = constants.CI_INFRA_STAGE

    def __init__(self, *args, **kwargs) -> None:
        """Set up attributes needed for this class."""
        # super().__init__() must come first, since it creates self._build_root.
        super().__init__(*args, **kwargs)

        self.chroot_path = Path(self._build_root) / constants.DEFAULT_CHROOT_DIR
        self.out_path = Path(self._build_root) / constants.DEFAULT_OUT_DIR

        self._required_mount_paths: Tuple[MountPathInfo] = (
            # Previously, /tmp in the chroot was mounted at ${CHROOT}/tmp.
            # Since 15483.0.0, it has been mounted at ${OUT}/tmp.
            # See https://crrev.com/c/4522313.
            MountPathInfo(
                chroot_path=Path("/tmp"),
                old_style_path=self.chroot_path / "tmp",
                new_style_path=self.out_path / "tmp",
            ),
            # Previously, /home in the chroot was mounted at ${CHROOT}/home.
            # Since 15588.0.0, it has been mounted at ${OUT}/home.
            # See https://crrev.com/c/4522314.
            MountPathInfo(
                chroot_path=Path("/home"),
                old_style_path=self.chroot_path / "home",
                new_style_path=self.out_path / "home",
            ),
            # Previously, /build in the chroot was mounted at ${CHROOT}/build.
            # Since 15613, it has been mounted at ${OUT}/build.
            # See https://crrev.com/c/4808858.
            MountPathInfo(
                chroot_path=Path("/build"),
                old_style_path=self.chroot_path / "build",
                new_style_path=self.out_path / "build",
            ),
        )

    def PerformStage(self) -> None:
        """Create the symlinks, and prove that they worked right."""
        self._CreateOutDir()
        self._CreateLinks()
        self._VerifyLinks()

    def _CreateOutDir(self) -> None:
        """Make an out-dir next to the workspace chroot, if it doesn't exist."""
        if self.out_path.exists():
            return
        osutils.SafeMakedirs(self.out_path)

    def _CreateLinks(self) -> None:
        """Create the symlinks."""
        for mount_path in self._required_mount_paths:
            self._CreateLink(mount_path)

    def _CreateLink(self, mount_path: MountPathInfo) -> None:
        """Create a link from the new-style path pointing to the old-style path.

        If the new-style mount path already exists, assume that the workspace
        branch is already mounting to that new path, so return early.

        If the old-style mount path doesn't already exist, create it so that the
        symlink target will definitely exist.
        """
        if mount_path.new_style_path.exists():
            return
        if not mount_path.old_style_path.exists():
            logging.info(
                "Creating old-style mount path as a symlink target: %s",
                mount_path.old_style_path,
            )
            osutils.SafeMakedirs(
                mount_path.old_style_path, sudo=True, mode=0o775
            )
        logging.info(
            "Creating symlink at %s pointing to %s",
            mount_path.new_style_path,
            mount_path.old_style_path,
        )
        osutils.SafeSymlink(
            mount_path.old_style_path, mount_path.new_style_path
        )

    def _VerifyLinks(self) -> None:
        """Prove that all the symlinks work as expected.

        Factory builders take a long time to run, sometimes over 10 hours. It
        would be unfortunate to wait 10 hours before we discover that our
        builders can't find chroot files at the expected location.
        """
        for mount_path in self._required_mount_paths:
            self._VerifyLink(mount_path)

    def _VerifyLink(self, mount_path: MountPathInfo) -> None:
        """Prove that the symlink for the given mount path works as expected.

        Create a file in the chroot, and then try to find it at the new-style
        location. Then, just to be double-sure, also use
        path_util.FromChrootPath() to make sure we'll actually find it in
        practice.

        No need to double down with chroot.full_path(), since it uses the same
        logic.

        Raises:
            FileNotFoundError: If we couldn't find a newly created file in any
                of the required mount paths.
        """
        _filename = "find_me"

        # Create the file inside the SDK.
        inside_path = mount_path.chroot_path / _filename
        commands.RunBuildScript(
            self._build_root,
            ["touch", str(inside_path)],
            sudo=True,
            enter_chroot=True,
        )

        # Try to find the file in the directory that we mounted.
        new_style_filepath = mount_path.new_style_path / _filename
        if not new_style_filepath.exists():
            raise FileNotFoundError(new_style_filepath)

        # Try to find the file where path_util thinks it should be.
        path_util_filepath = path_util.FromChrootPath(
            inside_path, source_path=self._build_root
        )
        if not Path(path_util_filepath).exists():
            raise FileNotFoundError(path_util_filepath)


class WorkspaceUpdateSDKStage(WorkspaceStageBase):
    """Stage that is responsible for updating the chroot."""

    option_name = "build"
    category = constants.CI_INFRA_STAGE

    def PerformStage(self) -> None:
        """Do the work of updating the chroot."""
        extra_env = self._portage_extra_env.copy()
        # The thinlto USE flag is fine for later steps, but drop it in the
        # SDK update step because it's not needed and can cause toolchain
        # problems. This is a hack because CBB is going away soon.
        if "thinlto" in extra_env.get("USE", ""):
            # Drop "thinlto" and "-thinlto", different toolchain packages may
            # have different thinlto settings.
            extra_env["USE"] = " ".join(
                [x for x in extra_env["USE"].split() if "thinlto" not in x]
            )
        commands.UpdateChroot(
            self._build_root,
            usepkg=not self._latest_toolchain,
            extra_env=extra_env,
            chroot_args=["--cache-dir", self._run.options.cache_dir],
        )


class WorkspaceSetupBoardStage(
    generic_stages.BoardSpecificBuilderStage, WorkspaceStageBase
):
    """Stage responsible for building host pkgs and setting up a board."""

    category = constants.CI_INFRA_STAGE

    def PerformStage(self) -> None:
        usepkg = self._run.config.usepkg_build_packages
        func = (
            commands.SetupBoard
            if self.AfterLimit(SETUP_BOARD_PORT_COMPLETE)
            else commands.LegacySetupBoard
        )
        func(
            self._build_root,
            board=self._current_board,
            usepkg=usepkg,
            force=self._run.config.board_replace,
            profile=self._run.options.profile or self._run.config.profile,
            chroot_upgrade=False,
            chroot_args=ChrootArgs(self._run.options),
            extra_env=self._portage_extra_env,
        )


class WorkspaceBuildPackagesStage(
    generic_stages.BoardSpecificBuilderStage, WorkspaceStageBase
):
    """Build Chromium OS packages."""

    category = constants.PRODUCT_OS_STAGE

    def PerformStage(self) -> None:
        usepkg = (
            self._run.config.usepkg_build_packages
            if self.AfterLimit(BUILD_PACKAGES_PREBUILTS)
            else False
        )

        build_packages_func = (
            commands.Build
            if self.AfterLimit(BUILD_PACKAGES_PORT_COMPLETE)
            else commands.LegacyBuild
        )
        build_packages_func(
            self._build_root,
            self._current_board,
            self._run.options.tests,
            usepkg,
            packages=self.GetListOfPackagesToBuild(),
            skip_chroot_upgrade=True,
            extra_env=self._portage_extra_env,
            noretry=self._run.config.nobuildretry,
            chroot_args=ChrootArgs(self._run.options),
        )


class WorkspaceUnitTestStage(
    generic_stages.BoardSpecificBuilderStage, WorkspaceStageBase
):
    """Run unit tests."""

    option_name = "tests"
    config_name = "unittests"
    category = constants.PRODUCT_OS_STAGE

    # If the unit tests take longer than 120 minutes, abort.
    UNIT_TEST_TIMEOUT = 120 * 60

    def PerformStage(self) -> None:
        extra_env = {}
        if self._run.config.useflags:
            extra_env["USE"] = " ".join(self._run.config.useflags)
        r = " Reached UnitTestStage timeout."
        with timeout_util.Timeout(self.UNIT_TEST_TIMEOUT, reason_message=r):
            try:
                commands.RunUnitTests(
                    self._build_root,
                    self._current_board,
                    build_stage=self._run.config.build_packages,
                    chroot_args=ChrootArgs(self._run.options),
                    extra_env=extra_env,
                )
            except failures_lib.BuildScriptFailure:
                cbuildbot_alerts.PrintBuildbotStepWarnings()
                logging.warning("Unittests failed. Ignored crbug.com/936123.")


class WorkspaceBuildImageStage(
    generic_stages.BoardSpecificBuilderStage, WorkspaceStageBase
):
    """Build standard Chromium OS images."""

    option_name = "build"
    config_name = "images"
    category = constants.PRODUCT_OS_STAGE

    def PerformStage(self) -> None:
        # Collect build_image arguments.
        version = self.GetWorkspaceReleaseTag()
        rootfs_verification = self._run.config.rootfs_verification
        builder_path = "/".join([self._bot_id, version])

        # We only build base, dev, and test images from this stage.
        images_can_build = set(["base", "dev", "test"])
        images_to_build = set(self._run.config.images).intersection(
            images_can_build
        )
        assert images_to_build

        # Build up command line.
        cmd = [
            "./build_image",
            "--board",
            self._current_board,
            "--replace",
            "--version",
            version,
        ]

        if self.AfterLimit(BUILD_IMAGE_ECLEAN_FLAG):
            cmd += ["--noeclean"]

        if not rootfs_verification:
            cmd += ["--noenable_rootfs_verification"]

        if self.AfterLimit(BUILD_IMAGE_BUILDER_PATH):
            cmd += ["--builder_path", builder_path]

        cmd += sorted(images_to_build)

        # Run command.
        commands.RunBuildScript(
            self._build_root,
            cmd,
            enter_chroot=True,
            extra_env=self._portage_extra_env,
            chroot_args=ChrootArgs(self._run.options),
        )


class WorkspaceDebugSymbolsStage(
    WorkspaceStageBase,
    generic_stages.BoardSpecificBuilderStage,
    generic_stages.ArchivingStageMixin,
):
    """Handles generation & upload of debug symbols."""

    config_name = "debug_symbols"
    category = constants.PRODUCT_OS_STAGE

    @failures_lib.SetFailureType(failures_lib.InfrastructureFailure)
    def PerformStage(self) -> None:
        """Generate debug symbols and upload debug.tgz."""
        buildroot = self._build_root
        board = self._current_board

        # Generate breakpad symbols of Chrome OS binaries.
        commands.GenerateBreakpadSymbols(
            buildroot,
            board,
            self._run.options.debug_forced,
            chroot_args=ChrootArgs(self._run.options),
            extra_env=self._portage_extra_env,
        )

        # Download android symbols (if this build has them), and Generate
        # breakpad symbols of Android binaries. This must be done after
        # GenerateBreakpadSymbols because it clobbers the output
        # directory.
        symbols_file = self.DownloadAndroidSymbols()

        if symbols_file:
            try:
                commands.GenerateAndroidBreakpadSymbols(
                    buildroot,
                    board,
                    symbols_file,
                    chroot_args=ChrootArgs(self._run.options),
                    extra_env=self._portage_extra_env,
                )
            except failures_lib.BuildScriptFailure:
                # Android breakpad symbol preparation is expected to work in
                # modern branches.
                if self.AfterLimit(ANDROID_BREAKPAD):
                    raise

                # For older branches, we only process them on a best effort
                # basis.
                cbuildbot_alerts.PrintBuildbotStepWarnings()
                logging.warning("Preparing Android symbols failed, ignoring..")

        # Upload them.
        self.UploadDebugTarball()
        self.UploadDebugBreakpadTarball()

        # Upload them to crash server.
        if self._run.config.upload_symbols:
            self.UploadSymbols(buildroot, board)

    def UploadDebugTarball(self) -> None:
        """Generate and upload the debug tarball."""
        filename = commands.GenerateDebugTarball(
            buildroot=self._build_root,
            board=self._current_board,
            archive_path=self.archive_path,
            gdb_symbols=self._run.config.archive_build_debug,
            archive_name="debug.tgz",
            chroot_compression=False,
        )
        self.UploadArtifact(filename, archive=False)

    def UploadDebugBreakpadTarball(self) -> None:
        """Generate and upload the debug tarball with only breakpad files."""
        filename = commands.GenerateDebugTarball(
            buildroot=self._build_root,
            board=self._current_board,
            archive_path=self.archive_path,
            gdb_symbols=False,
            archive_name="debug_breakpad.tar.xz",
            chroot_compression=False,
        )
        self.UploadArtifact(filename, archive=False)

    def UploadSymbols(self, buildroot, board) -> None:
        """Upload generated debug symbols."""
        failed_name = "failed_upload_symbols.list"
        failed_list = os.path.join(self.archive_path, failed_name)

        if self._run.options.debug:
            # For debug builds, limit ourselves to just uploading 1 symbol.
            # This way trybots and such still exercise this code.
            cnt = 1
            official = False
        else:
            cnt = None
            official = self._run.config.chromeos_official

        upload_passed = True
        try:
            commands.UploadSymbols(
                buildroot,
                board,
                official,
                cnt,
                failed_list,
                chroot_args=ChrootArgs(self._run.options),
                extra_env=self._portage_extra_env,
            )
        except failures_lib.BuildScriptFailure:
            upload_passed = False

        if os.path.exists(failed_list):
            self.UploadArtifact(failed_name, archive=False)

            logging.notice(
                "To upload the missing symbols from this build, run:"
            )
            for url in self._GetUploadUrls(filename=failed_name):
                logging.notice(
                    "upload_symbols --failed-list %s %s",
                    os.path.join(url, failed_name),
                    os.path.join(url, "debug_breakpad.tar.xz"),
                )

        # Delay throwing the exception until after we uploaded the list.
        if not upload_passed:
            raise artifact_stages.DebugSymbolsUploadException(
                "Failed to upload all symbols."
            )

    def DetermineAndroidPackage(self):
        """Returns the active Android container package in use by the board.

        Workspace version of cbuildbot_run.DetermineAndroidPackage().

        Returns:
            String identifier for a package, or None
        """
        packages = portage_util.GetPackageDependencies(
            "virtual/target-os",
            board=self._current_board,
            buildroot=self._build_root,
            set_empty_root=not self.AfterLimit(PORTAGE_2_3_75_UPDATE),
        )

        android_packages = {
            p
            for p in packages
            if p.startswith("chromeos-base/android-container-")
            or p.startswith("chromeos-base/android-vm-")
        }

        assert len(android_packages) <= 1

        if android_packages:
            return next(iter(android_packages))
        else:
            return None

    def DetermineAndroidBranch(self, package):
        """Returns the Android branch in use by the active container ebuild.

        Workspace version of cbuildbot_run.DetermineAndroidBranch().

        Args:
            package: String name of Android package to get branch of.

        Returns:
            String with the android container branch name.
        """
        ebuild_path = portage_util.FindEbuildForBoardPackage(
            package, self._current_board, buildroot=self._build_root
        )
        host_ebuild_path = path_util.FromChrootPath(
            ebuild_path, source_path=self._build_root
        )
        # We assume all targets pull from the same branch and that we always
        # have at least one of the following targets.
        targets = android.GetAllAndroidEbuildTargets()
        ebuild_content = osutils.SourceEnvironment(host_ebuild_path, targets)
        logging.info("Got ebuild env: %s", ebuild_content)
        for target in targets:
            if target in ebuild_content:
                branch = re.search(r"(.*?)-linux-", ebuild_content[target])
                if branch is not None:
                    return branch.group(1)
        raise cbuildbot_run.NoAndroidBranchError(
            "Android branch could not be determined for %s (ebuild empty?)"
            % ebuild_path
        )

    def DetermineAndroidVersion(self, package):
        """Determine the current Android version in buildroot now and return it.

        This uses the typical portage logic to determine which version of
        Android is active right now in the buildroot.

        Workspace version of cbuildbot_run.DetermineAndroidVersion().

        Args:
            package: String name of Android package to get version of.

        Returns:
            The Android build ID of the container for the boards.
        """
        cpv = package_info.SplitCPV(package)
        return cpv.version_no_rev

    def DetermineAndroidABI(self):
        """Returns the Android ABI in use by the active container ebuild.

        Workspace version of cbuildbot_run.DetermineAndroidABI().

        Args:
            package: String name of Android package to get ABI version of.

        Returns:
            string defining ABI of the container.
        """
        use_flags = portage_util.GetInstalledPackageUseFlags(
            "sys-devel/arc-build",
            self._current_board,
            buildroot=self._build_root,
        )
        if "abi_x86_64" in use_flags.get("sys-devel/arc-build", []):
            return "x86_64"
        elif "abi_x86_32" in use_flags.get("sys-devel/arc-build", []):
            return "x86"
        else:
            # ARM only supports 32-bit so it does not have abi_x86_{32,64} set.
            # But it is also the last possible ABI, so returning by default.
            return "arm"

    def DetermineAndroidVariant(self, package):
        """Returns the Android variant in use by the active container ebuild."""

        all_use_flags = portage_util.GetInstalledPackageUseFlags(
            package, self._current_board, buildroot=self._build_root
        )
        for use_flags in all_use_flags.values():
            for use_flag in use_flags:
                if (
                    "cheets_userdebug" in use_flag
                    or "cheets_sdk_userdebug" in use_flag
                ):
                    return "userdebug"
                elif "cheets_user" in use_flag or "cheets_sdk_user" in use_flag:
                    return "user"

        # We iterated through all the flags and could not find user or
        # userdebug. This should not be possible given that this code is only
        # ran by builders, which will never use local images.
        raise cbuildbot_run.NoAndroidVariantError(
            "Android Variant cannot be determined for the packge: %s" % package
        )

    def DetermineAndroidTarget(self, package):
        if package.startswith("chromeos-base/android-vm-"):
            return "bertha"
        if package.startswith("chromeos-base/android-container-"):
            return "cheets"

        raise cbuildbot_run.NoAndroidTargetError(
            "Android Target cannot be determined for the package: %s" % package
        )

    def DownloadAndroidSymbols(self):
        """Helper to download android container symbols, as needed.

        Determines which, if any, Android container this build includes, and
        downloads it's symbols.

        Returns:
            path to downloaded symbols file, or None if not downloaded.
        """
        android_package = self.DetermineAndroidPackage()
        if not android_package:
            logging.info(
                "Android is not enabled on this board. Skipping symbols."
            )
            return None

        android_build_branch = self.DetermineAndroidBranch(android_package)
        android_version = self.DetermineAndroidVersion(android_package)
        arch = self.DetermineAndroidABI()
        variant = self.DetermineAndroidVariant(android_package)
        android_target = self.DetermineAndroidTarget(android_package)

        logging.info(
            "Downloading symbols of Android %s (%s)...",
            android_version,
            android_build_branch,
        )

        symbols_file_url = constants.ANDROID_SYMBOLS_URL_TEMPLATE % {
            "branch": android_build_branch,
            "target": android_target,
            "arch": arch,
            "version": android_version,
            "variant": variant,
        }

        # Should be based on self.archive_path, but we need a path inside
        # the workspace chroot, not infra chroot.
        symbols_file = os.path.join(
            self._build_root, "buildbot_archive", constants.ANDROID_SYMBOLS_FILE
        )
        gs_context = gs.GSContext()
        gs_context.Copy(symbols_file_url, symbols_file)

        return symbols_file
