# 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, should_skip = lambda path : False):
  local_root = input_api.change.RepositoryRoot()
  upstream = input_api.change._upstream
  unformatted_files = []
  for git_file in input_api.AffectedTextFiles():
    if git_file.LocalPath().startswith("pkg/front_end/testcases/"):
      continue
    if should_skip(git_file.LocalPath()):
      continue
    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):
    # Don't look for formatting errors in multitests. Since those are very
    # sensitive to whitespace, many cannot be formatted with dartfmt without
    # breaking them.
    if filename and filename.endswith('_test.dart'):
      with open(filename) as f:
        contents = f.read()
        if '//#' in contents:
          return False

    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

  def should_skip(path):
      return (path.startswith("pkg/status_file/test/data/")
              or path.startswith("pkg/front_end/"))

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

  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 _CheckLayering(input_api, output_api):
  """Run VM layering check.

  This check validates that sources from one layer do not reference sources
  from another layer accidentally.
  """
  # Run only if .cc or .h file was modified.
  def is_cpp_file(path):
    return path.endswith('.cc') or path.endswith('.h')
  if all(not is_cpp_file(f.LocalPath()) for f in input_api.AffectedFiles()):
    return []

  local_root = input_api.change.RepositoryRoot()
  layering_check = imp.load_source('layering_check',
      os.path.join(local_root, 'runtime', 'tools', 'layering_check.py'))
  errors = layering_check.DoCheck(local_root)
  if errors:
    return [output_api.PresubmitError(
        'Layering check violation for C++ sources.',
        long_text='\n'.join(errors))]
  else:
    return []


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) +
          _CheckLayering(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) +
          _CheckLayering(input_api, output_api))
