# 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/macos_sdk',
    '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, rebase_merges=True)
  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))

    with api.macos_sdk():
      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, [])))
