# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Update CIPD ensure files in a Git repository."""

from PB.recipes.fuchsia.cipd_ensure_file_roller import InputProperties

DEPS = [
    "fuchsia/auto_roller",
    "fuchsia/buildbucket_util",
    "fuchsia/cipd_ensure",
    "fuchsia/cipd_resolver",
    "fuchsia/git_checkout",
    "recipe_engine/cipd",
    "recipe_engine/json",
    "recipe_engine/path",
    "recipe_engine/properties",
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    props.tag = props.tag or "version"
    props.ref = props.ref or "latest"
    # Note that we only support Git checkouts. Jiri checkouts are not expected
    # to have CIPD ensure files.
    checkout_dir = api.path.mkdtemp("checkout")
    api.git_checkout(props.remote, path=checkout_dir)

    all_packages = []
    for ensure_file, packages in props.packages_by_ensure_file.items():
        platforms = api.cipd_ensure.get_platforms(
            f"get platforms for {ensure_file}",
            ensure_file=checkout_dir / ensure_file,
        )
        all_packages += api.cipd_ensure.expand_packages_by_platforms(
            packages=packages,
            platforms=platforms,
        )

    all_packages = sorted(all_packages)

    candidate_versions = api.cipd_resolver.resolve_common_tags(
        ref=props.ref,
        tag_name=props.tag,
        packages=all_packages,
    )
    version = candidate_versions[0]

    for ensure_file, packages in props.packages_by_ensure_file.items():
        api.cipd_ensure.update_packages(
            f"update {ensure_file}",
            ensure_file=checkout_dir / ensure_file,
            packages=packages,
            version=version,
        )
        api.cipd.ensure_file_resolve(checkout_dir / ensure_file)

    commit_message = api.auto_roller.generate_package_roll_message(
        packages=all_packages,
        version=version,
        dry_run=props.roll_options.dry_run,
    )

    change = api.auto_roller.attempt_roll(
        props.roll_options,
        repo_dir=checkout_dir,
        commit_message=commit_message,
    )
    return api.auto_roller.raw_result(change)


def GenTests(api):
    ensure_file = "foo.ensure"
    packages = ["fuchsia/foo/${platform}", "fuchsia/bar/${platform}"]
    default_props = api.properties(
        packages_by_ensure_file={ensure_file: packages},
        remote="https://fuchsia.googlesource.com/integration",
        roll_options=api.auto_roller.Options(
            remote="https://fuchsia.googlesource.com/integration",
        ),
    )

    def resolved_tags(tags):
        return api.step_data("resolve common tags", api.json.output(tags))

    yield (
        api.buildbucket_util.test("roll", builder="cipd-roller")
        + resolved_tags(["version:newest", "version:newer"])
        + api.cipd_ensure.get_platforms(
            f"get platforms for {ensure_file}",
            ["linux-amd64", "linux-arm64", "mac-amd64"],
        )
        + api.cipd_ensure.update_packages(f"update {ensure_file}", packages)
        + api.auto_roller.success()
        + default_props
    )
