# 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_resolver",
    "fuchsia/cipd_util",
    "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_util.get_platforms(
            "get platforms for %s" % ensure_file,
            ensure_file=checkout_dir.join(ensure_file),
        )
        all_packages += api.cipd_util.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_util.update_packages(
            "update %s" % ensure_file,
            ensure_file=checkout_dir.join(ensure_file),
            packages=packages,
            version=version,
        )
        api.cipd.ensure_file_resolve(checkout_dir.join(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_stream(tags))

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