# Copyright 2017 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 Go toolchain."""

from recipe_engine.recipe_api import Property

DEPS = [
    'fuchsia/buildbucket_util',
    'fuchsia/checkout',
    'fuchsia/gerrit',
    'fuchsia/git',
    'fuchsia/go',
    'fuchsia/gsutil',
    'fuchsia/upload',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = {
    'platform':
        Property(kind=str, help='CIPD platform for the target', default=None),
}

# Files and directories to clean up before and after a build, mirroring what go
# itself does for a release.
# See https://github.com/golang/build/blob/6c34d49dff4864185cb351d06518ce3a76efb6a2/cmd/release/release.go#L240:L248
PREBUILD_CLEAN_FILES = [
    '.gitattributes',
    '.gitignore',
    '.hgignore',
    '.hgtags',
    'misc/dashboard',
    'misc/makerelease',
]
PREBUILD_CLEAN_DIRS = [
    '.git',
    '.github',
]
# See https://github.com/golang/build/blob/6c34d49dff4864185cb351d06518ce3a76efb6a2/cmd/release/release.go#L464:L467
POSTBUILD_CLEAN_FILES = [
    'VERSION.cache',
]
POSTBUILD_CLEAN_DIRS = [
    'pkg/bootstrap',
]

FUCHSIA_THIRD_PARTY_GO_REPO = 'https://fuchsia.googlesource.com/third_party/go'


def RunSteps(api, platform):
  # TODO: factor this out into a host_build recipe module.
  host_platform = '%s-%s' % (api.platform.name.replace('win', 'windows'), {
      'intel': {
          32: '386',
          64: 'amd64',
      },
      'arm': {
          32: 'armv6',
          64: 'arm64',
      },
  }[api.platform.arch][api.platform.bits])
  target_platform = platform or host_platform

  go_dir = api.path['start_dir'].join('go')
  build_input = api.buildbucket.build.input
  if build_input.gerrit_changes:
    cl = build_input.gerrit_changes[0]
    revision = api.git.checkout_cl(cl, path=go_dir)
  else:
    revision = api.git.checkout(
        FUCHSIA_THIRD_PARTY_GO_REPO,
        path=go_dir,
        ref='HEAD',
    )

  cipd_os, cipd_cpu = target_platform.split('-')
  goos = cipd_os.replace('mac', 'darwin')
  goarch = cipd_cpu.replace('armv6', 'arm')
  env = {'GOOS': goos, 'GOARCH': goarch, 'GOROOT_BOOTSTRAP': api.go.go_root}

  with api.context(cwd=go_dir.join('src'), env=env):
    with api.step.nest('pre-build file removal'):
      for filename in PREBUILD_CLEAN_FILES:
        api.file.remove(filename, go_dir.join(filename))
      for dirname in PREBUILD_CLEAN_DIRS:
        api.file.rmtree(dirname, go_dir.join(dirname))

    api.step('build', [go_dir.join('src', 'make.bash')])

    if host_platform == target_platform:
      with api.context(env_prefixes={'PATH': [go_dir.join('bin')]}):
        run_bash = go_dir.join('src', 'run.bash')
        api.step('test', [run_bash, '--no-rebuild'])

  # Remove after testing, as some tests may rely on the contents.
  with api.step.nest('post-build file removal'):
    for filename in POSTBUILD_CLEAN_FILES:
      api.file.remove(filename, go_dir.join(filename))
    for dirname in POSTBUILD_CLEAN_DIRS:
      api.file.rmtree(dirname, go_dir.join(dirname))

  if api.buildbucket_util.is_tryjob:
    return

  go_version = api.file.read_text(
      'read go version', go_dir.join('VERSION'), test_data='go1.8').strip()
  assert go_version, 'Cannot determine Go version'

  api.upload.cipd_package(
      'fuchsia/go/' + target_platform,
      go_dir, [api.upload.DirectoryPath(go_dir)], {'git_revision': revision},
      repository=FUCHSIA_THIRD_PARTY_GO_REPO,
      extra_tags={'version': go_version})


def GenTests(api):

  def props(platform):
    return {
        'platform': platform,
        'checkout.project': 'integration',
        'checkout.manifest': 'third_party/go',
        'checkout.remote': 'https://fuchsia.googlesource.com/third_party/go',
    }

  def name(platform):
    return api.platform.name(platform.split('-')[0])

  for platform in ('linux-amd64', 'linux-arm64', 'mac-amd64'):
    yield (
        api.checkout.test(platform, properties=props(platform), tryjob=False) +
        name(platform))
    yield (api.checkout.test(
        platform + '_cq', properties=props(platform), tryjob=True) +
           name(platform))
    yield (
        api.checkout.test(
            platform + '_new', properties=props(platform), tryjob=False) +
        name(platform) + api.step_data(
            'cipd.cipd search fuchsia/go/' + platform + ' ' + 'git_revision:' +
            'deadbeef', api.cipd.example_search('fuchsia/go/' + platform, [])))
