# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

"""Top-level presubmit script for Dart.

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""

import imp
import os
import os.path
import scm
import subprocess
import tempfile


def _CheckFormat(input_api, identification, extension, windows,
    hasFormatErrors):
  local_root = input_api.change.RepositoryRoot()
  upstream = input_api.change._upstream
  unformatted_files = []
  for git_file in input_api.AffectedTextFiles():
    filename = git_file.AbsoluteLocalPath()
    if filename.endswith(extension) and hasFormatErrors(filename=filename):
      old_version_has_errors = False
      try:
        path = git_file.LocalPath()
        if windows:
          # Git expects a linux style path.
          path = path.replace(os.sep, '/')
        old_contents = scm.GIT.Capture(
          ['show', upstream + ':' + path],
          cwd=local_root,
          strip_out=False)
        if hasFormatErrors(contents=old_contents):
          old_version_has_errors = True
      except subprocess.CalledProcessError as e:
        old_version_has_errors = False

      if old_version_has_errors:
        print("WARNING: %s has existing and possibly new %s issues" %
          (git_file.LocalPath(), identification))
      else:
        unformatted_files.append(filename)

  return unformatted_files


def _CheckBuildStatus(input_api, output_api):
  results = []
  status_check = input_api.canned_checks.CheckTreeIsOpen(
      input_api,
      output_api,
      json_url='http://dart-status.appspot.com/current?format=json')
  results.extend(status_check)
  return results


def _CheckDartFormat(input_api, output_api):
  local_root = input_api.change.RepositoryRoot()
  upstream = input_api.change._upstream
  utils = imp.load_source('utils',
      os.path.join(local_root, 'tools', 'utils.py'))

  prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')

  windows = utils.GuessOS() == 'win32'
  if windows:
    prebuilt_dartfmt += '.bat'

  if not os.path.isfile(prebuilt_dartfmt):
    print('WARNING: dartfmt not found: %s' % (prebuilt_dartfmt))
    return []

  def HasFormatErrors(filename=None, contents=None):
    args = [prebuilt_dartfmt, '--set-exit-if-changed']
    if not contents:
      args += [filename, '-n']

    process = subprocess.Popen(args,
                               stdout=subprocess.PIPE,
                               stdin=subprocess.PIPE
                               )
    process.communicate(input=contents)

    # Check for exit code 1 explicitly to distinguish it from a syntax error
    # in the file (exit code 65). The repo contains many Dart files that are
    # known to have syntax errors for testing purposes and which can't be
    # parsed and formatted. Don't treat those as errors.
    return process.returncode == 1

  unformatted_files = _CheckFormat(input_api, "dartfmt", ".dart", windows,
      HasFormatErrors)

  if unformatted_files:
    lineSep = " \\\n"
    if windows:
      lineSep = " ^\n";
    return [output_api.PresubmitError(
        'File output does not match dartfmt.\n'
        'Fix these issues with:\n'
        '%s -w%s%s' % (prebuilt_dartfmt, lineSep,
            lineSep.join(unformatted_files)))]

  return []


def _CheckStatusFiles(input_api, output_api):
  local_root = input_api.change.RepositoryRoot()
  upstream = input_api.change._upstream
  utils = imp.load_source('utils',
      os.path.join(local_root, 'tools', 'utils.py'))

  dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
  lint = os.path.join(local_root, 'pkg', 'status_file', 'bin', 'lint.dart')

  windows = utils.GuessOS() == 'win32'
  if windows:
    dart += '.exe'

  if not os.path.isfile(dart):
    print('WARNING: dart not found: %s' % dart)
    return []

  if not os.path.isfile(lint):
    print('WARNING: Status file linter not found: %s' % lint)
    return []

  def HasFormatErrors(filename=None, contents=None):
    args = [dart, lint] + (['-t'] if contents else [filename])
    process = subprocess.Popen(args,
                               stdout=subprocess.PIPE,
                               stdin=subprocess.PIPE)
    process.communicate(input=contents)
    return process.returncode != 0

  unformatted_files = _CheckFormat(input_api, "status file", ".status",
      windows, HasFormatErrors)

  if unformatted_files:
    normalize = os.path.join(local_root, 'pkg', 'status_file', 'bin',
        'normalize.dart')
    lineSep = " \\\n"
    if windows:
      lineSep = " ^\n";
    return [output_api.PresubmitError(
        'Status files are not normalized.\n'
        'Fix these issues with:\n'
        '%s %s -w%s%s' % (dart, normalize, lineSep,
            lineSep.join(unformatted_files)))]

  return []


def _CheckValidHostsInDEPS(input_api, output_api):
  """Checks that DEPS file deps are from allowed_hosts."""
  # Run only if DEPS file has been modified to annoy fewer bystanders.
  if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
    return []
  # Outsource work to gclient verify
  try:
    input_api.subprocess.check_output(['gclient', 'verify'])
    return []
  except input_api.subprocess.CalledProcessError, error:
    return [output_api.PresubmitError(
        'DEPS file must have only dependencies from allowed hosts.',
        long_text=error.output)]


def CheckChangeOnCommit(input_api, output_api):
  return (_CheckValidHostsInDEPS(input_api, output_api) +
          _CheckBuildStatus(input_api, output_api) +
          _CheckDartFormat(input_api, output_api) +
          _CheckStatusFiles(input_api, output_api))


def CheckChangeOnUpload(input_api, output_api):
  return (_CheckValidHostsInDEPS(input_api, output_api) +
          _CheckDartFormat(input_api, output_api) +
          _CheckStatusFiles(input_api, output_api))
