# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import re
"""Presubmit for build/util"""




def _GetFilesToSkip(input_api):
  files_to_skip = []
  affected_files = input_api.change.AffectedFiles()
  version_script_change = next(
      (f for f in affected_files
       if re.search('\\/version\\.py$|\\/version_test\\.py$', f.LocalPath())),
      None)

  if version_script_change is None:
    files_to_skip.append('version_test\\.py$')

  android_chrome_version_script_change = next(
      (f for f in affected_files if re.search(
          '\\/android_chrome_version\\.py$|'
          '\\/android_chrome_version_test\\.py$', f.LocalPath())), None)

  if android_chrome_version_script_change is None:
    files_to_skip.append('android_chrome_version_test\\.py$')

  return files_to_skip


def _GetPythonUnitTests(input_api, output_api):
  # No need to test if files are unchanged
  files_to_skip = _GetFilesToSkip(input_api)

  return input_api.canned_checks.GetUnitTestsRecursively(
      input_api,
      output_api,
      input_api.PresubmitLocalPath(),
      files_to_check=['.*_test\\.py$'],
      files_to_skip=files_to_skip)


def CommonChecks(input_api, output_api):
  """Presubmit checks run on both upload and commit.
  """
  checks = []
  checks.extend(_GetPythonUnitTests(input_api, output_api))
  return input_api.RunTests(checks, False)


def CheckChangeOnUpload(input_api, output_api):
  """Presubmit checks on CL upload."""
  return CommonChecks(input_api, output_api)


def CheckChangeOnCommit(input_api, output_api):
  """Presubmit checks on commit."""
  return CommonChecks(input_api, output_api)
