# Copyright 2018 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.
"""Recipe for building and publishing CIPD prebuilts"""

from recipe_engine.config import Enum, List
from recipe_engine.recipe_api import Property

DEPS = [
    'fuchsia/build',
    'fuchsia/buildbucket_util',
    'fuchsia/checkout',
    'fuchsia/fuchsia',
    'fuchsia/jiri',
    'fuchsia/upload',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/context',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
]

TARGETS = ['arm64', 'x64']

PROPERTIES = {
    'cipd_pkg_prefix':
        Property(
            kind=str,
            help='The CIPD prefix where the tool binaries should be uploaded',
            default=None),
    'cipd_pkg_name':
        Property(
            kind=str,
            help='The exact CIPD path where the tool binaries should be uploaded (overrides cipd_pkg_prefix)',
            default=None),
    'manifest':
        Property(kind=str, help='Jiri manifest to use'),
    'ninja_targets':
        Property(
            kind=List(basestring),
            help='Extra target args to pass to ninja',
            default=[]),
    'packages':
        Property(kind=List(basestring), help='Packages to build', default=[]),
    'product':
        Property(kind=str, help='Product to build', default=None),
    'board':
        Property(kind=str, help='Board to build', default=None),
    'target':
        Property(kind=Enum(*TARGETS), help='Target to build'),
    'remote':
        Property(kind=str, help='Remote manifest repository'),
}


def get_bin_path_components(api, build_dir, ninja_target):
  """Returns a binary's path based on its ninja target.

  Args:
    api: The RecipeApi object
    build_dir: The Fuchsia build output directory
    ninja_target: A specific Ninja target that was built

  Returns:
    bin_dir: The absolute path to the parent directory of bin_name.
    bin_name: The name of the tool binary
  """
  if ninja_target.endswith('/'):
    # This shouldn't happen and would be considered an user error
    # Just in case, sanitize ninja_target for api.path.split()
    # to prevent returning empty string as target_name
    ninja_target = ninja_target[:-1]

  # ninja_target can be expressed in two formats
  #   1) path to binary (e.g. "tools/json_validator")
  #   2) path to ninja target (e.g. "tools:validator.zip")
  # The following logic supports both of these formats
  target_dir, target_name = api.path.split(ninja_target)
  bin_dir = build_dir if ':' in ninja_target else build_dir.join(target_dir)
  bin_name = target_name.split(':')[-1]
  return bin_dir, bin_name


def RunSteps(api, cipd_pkg_prefix, cipd_pkg_name, manifest, target,
             ninja_targets, packages, product, board, remote):

  with api.context(infra_steps=True):
    assert manifest
    assert remote
    build = api.buildbucket.build
    checkout = api.checkout.fuchsia_with_options(
        path=api.path['start_dir'],
        manifest=manifest,
        remote=remote,
        build=build)

    revision = str(build.input.gitiles_commit.id)
    assert revision

  build = api.build.with_options(
      build_dir=api.path['start_dir'].join('out'),
      checkout=checkout,
      target=target,
      build_type='release',
      packages=packages,
      board=board,
      product=product,
      ninja_targets=ninja_targets,
      build_images=False,
  )

  if not api.buildbucket_util.is_tryjob:
    platform = '${platform}'
    for ninja_target in ninja_targets:
      bin_dir, bin_name = get_bin_path_components(api, build.fuchsia_build_dir,
                                                  ninja_target)
      api.upload.cipd_package(
          cipd_pkg_name or '%s/%s/%s' % (cipd_pkg_prefix, bin_name, platform),
          bin_dir, [api.upload.FilePath(bin_dir.join(bin_name))],
          {'git_revision': revision},
          repository=remote,
          install_mode=None)


def GenTests(api):
  revision = api.jiri.example_revision
  ci_build = api.buildbucket.ci_build(
      git_repo='https://fuchsia.googlesource.com/build',
      revision=revision,
  )

  yield api.test('default') + ci_build + api.properties(
      cipd_pkg_prefix='fuchsia/tools',
      manifest='manifest/build',
      ninja_targets=['tools/json_validator'],
      target='x64',
      packages=['//build/packages:json_validator'],
      project='build',
      remote='https://fuchsia.googlesource.com/build',
  ) + api.step_data(
      # Mock api.cipd.search(cipd_pkg_name, 'git_revision:' + revision)
      # by expanding the internal step name and providing a result for the step
      'cipd.cipd search fuchsia/tools/json_validator/${platform} git_revision:%s'
      % revision,
      api.json.output({'result': []}),
  )
  yield api.test(
      'gn_target_with_trailing_fwd_slash'
  ) + ci_build + api.properties(
      cipd_pkg_prefix='fuchsia/tools',
      manifest='manifest/build',
      ninja_targets=['tools/json_validator/'],
      target='x64',
      packages=['//build/packages:json_validator'],
      project='build',
      remote='https://fuchsia.googlesource.com/build',
  ) + api.step_data(
      # Mock api.cipd.search(cipd_pkg_name, 'git_revision:' + revision)
      # by expanding the internal step name and providing a result for the step
      'cipd.cipd search fuchsia/tools/json_validator/${platform} git_revision:%s'
      % revision,
      api.json.output({'result': []}),
  )
  yield api.test('cipd_has_revision') + ci_build + api.properties(
      cipd_pkg_prefix='fuchsia/tools',
      manifest='manifest/build',
      ninja_targets=['tools/json_validator'],
      target='x64',
      packages=['//build/packages:json_validator'],
      project='build',
      remote='https://fuchsia.googlesource.com/build',
  ) + api.step_data(
      'cipd.cipd search fuchsia/tools/json_validator/${platform} git_revision:%s'
      % revision,
      api.cipd.example_search(
          'fuchsia/tools/json_validator/${platform}:%s' % revision),
  )
  yield api.test('no_revision') + ci_build + api.properties(
      cipd_pkg_prefix='fuchsia/tools',
      manifest='manifest/build',
      ninja_targets=['tools/json_validator'],
      target='x64',
      packages=['//build/packages:json_validator'],
      project='build',
      remote='https://fuchsia.googlesource.com/build',
  )
