# 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:
    return [output_api.PresubmitError(
        'File output does not match dartfmt.\n'
        'Fix these issues with:\n'
        '%s -w \\\n%s' % (prebuilt_dartfmt, ' \\\n'.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))
