# 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 _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 = []
  for git_file in input_api.AffectedTextFiles():
    filename = git_file.AbsoluteLocalPath()
    if filename.endswith('.dart'):
      if 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:
          # TODO(jacobr): verify that the error really is that the file was
          # added for this CL.
          old_version_has_errors = False

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

  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 _CheckNewTests(input_api, output_api):
  testsDirectories = [
      #    Dart 1 tests                DDC tests
      # =================       ==========================
      ("tests/language/",       "tests/language_2/"),
      ("tests/lib/",            "tests/lib_2/"),
      ("tests/html/",           "tests/lib_2/html/"),
  ]

  result = []
  # Tuples of (new Dart 1 test path, expected DDC test path)
  dart1TestsAdded = []
  # Tuples of (original Dart test path, expected DDC test path)
  ddcTestsExists = []
  for f in input_api.AffectedFiles():
    for oldPath, newPath in testsDirectories:
      if f.LocalPath().startswith(oldPath):
        if f.Action() == 'A':
          # Compute where the new test should live.
          ddcTestPath = f.LocalPath().replace(oldPath, newPath)
          dart1TestsAdded.append((f.LocalPath(), ddcTestPath))
        elif f.Action() == 'M':
          # Find all modified tests in Dart 1.0
          filename = f.LocalPath()
          for oldPath, newPath in testsDirectories:
            if filename.find(oldPath) == 0:
              ddcTestFilePathAbs = "%s" % \
                  f.AbsoluteLocalPath().replace(oldPath, newPath)
              if os.path.isfile(ddcTestFilePathAbs):
                #originalDart1Test.append(f.LocalPath())
                ddcTestsExists.append((f.LocalPath(),
                    f.LocalPath().replace(oldPath, newPath)))

  # Does a Dart 2.0 DDC test exist if so it must be changed too.
  missingDDCTestsChange = []
  for (dartTest, ddcTest) in ddcTestsExists:
    foundDDCTestModified = False
    for f in input_api.AffectedFiles():
      if f.LocalPath() == ddcTest:
        # Found corresponding DDC test - great.
        foundDDCTestModified = True
        break
    if not foundDDCTestModified:
      # Add the tuple (dart 1 test path, DDC test path)
      missingDDCTestsChange.append((dartTest, ddcTest))

  if missingDDCTestsChange:
    errorList = []
    for idx, (orginalTest, ddcTest) in enumerate(missingDDCTestsChange):
      errorList.append(
          '%s. Dart 1.0 test changed: %s\n%s. DDC  test must change: ' \
          '%s\n' % (idx + 1, orginalTest, idx + 1, ddcTest))
    result.append(output_api.PresubmitError(
        'Error: If you change a Dart 1.0 test, you must also update the DDC '
        'test:\n%s' % ''.join(errorList)))

  if dart1TestsAdded:
    errorList = []
    for idx, (oldTestPath, newTestPath) in enumerate(dart1TestsAdded):
      errorList.append('%s. New Dart 1.0  test: %s\n'
          '%s. Should be DDC test: %s\n' % \
          (idx + 1, oldTestPath, idx + 1, newTestPath))
    result.append(output_api.PresubmitError(
        'Error: New Dart 1.0 test can not be added the test must be added as '
        'a DDC test:\n'
        'Fix tests:\n%s' % ''.join(errorList)))

  return result

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

def CheckChangeOnUpload(input_api, output_api):
  return (_CheckNewTests(input_api, output_api) +
          _CheckDartFormat(input_api, output_api))
