# 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/go',
    'fuchsia/gsutil',
    'fuchsia/jiri',
    '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',
]


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

  api.checkout.with_options(
      path=api.path['start_dir'],
      manifest='third_party/go',
      project='integration',
      remote='https://fuchsia.googlesource.com/integration',
  )
  with api.context(infra_steps=True):
    project = api.jiri.project(['third_party/go']).json.output[0]
  go_dir = api.path['start_dir'].join(project['path'])
  repository = project['remote']
  revision = project['revision']

  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=repository,
      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:' + api.jiri.example_revision,
               api.cipd.example_search('fuchsia/go/' + platform, [])))
