Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Unified Diff: PRESUBMIT.py

Issue 1846103005: Reland of Include isolate.py in data for Android unit tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: even more cautious Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | PRESUBMIT_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: PRESUBMIT.py
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index fb3d60f0e2407a658872f671900bd39b3b9984a1..8308310257763930b7a570f3c21a1ce258898df9 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -298,6 +298,17 @@ _VALID_OS_MACROS = (
)
+_ANDROID_SPECIFIC_PYDEPS_FILES = [
+ 'build/android/test_runner.pydeps',
+]
+
+_GENERIC_PYDEPS_FILES = [
+ 'build/secondary/tools/swarming_client/isolate.pydeps',
+]
+
+_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
+
+
def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
"""Attempts to prevent use of functions intended only for testing in
non-testing code. For now this is just a best-effort implementation
@@ -1501,6 +1512,99 @@ def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
return results
+class PydepsChecker(object):
+ def __init__(self, input_api, pydeps_files):
+ self._file_cache = {}
+ self._input_api = input_api
+ self._pydeps_files = pydeps_files
+
+ def _LoadFile(self, path):
+ """Returns the list of paths within a .pydeps file relative to //."""
+ if path not in self._file_cache:
+ with open(path) as f:
+ self._file_cache[path] = f.read()
+ return self._file_cache[path]
+
+ def _ComputeNormalizedPydepsEntries(self, pydeps_path):
+ """Returns an interable of paths within the .pydep, relativized to //."""
+ os_path = self._input_api.os_path
+ pydeps_dir = os_path.dirname(pydeps_path)
+ entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
+ if not l.startswith('*'))
+ return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
+
+ def _CreateFilesToPydepsMap(self):
+ """Returns a map of local_path -> list_of_pydeps."""
+ ret = {}
+ for pydep_local_path in self._pydeps_files:
+ for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
+ ret.setdefault(path, []).append(pydep_local_path)
+ return ret
+
+ def ComputeAffectedPydeps(self):
+ """Returns an iterable of .pydeps files that might need regenerating."""
+ affected_pydeps = set()
+ file_to_pydeps_map = None
+ for f in self._input_api.AffectedFiles(include_deletes=True):
+ local_path = f.LocalPath()
+ if local_path == 'DEPS':
+ return self._pydeps_files
+ elif local_path.endswith('.pydeps'):
+ if local_path in self._pydeps_files:
+ affected_pydeps.add(local_path)
+ elif local_path.endswith('.py'):
+ if file_to_pydeps_map is None:
+ file_to_pydeps_map = self._CreateFilesToPydepsMap()
+ affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
+ return affected_pydeps
+
+ def DetermineIfStale(self, pydeps_path):
+ """Runs print_python_deps.py to see if the files is stale."""
+ old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
+ cmd = old_pydeps_data[1][1:].strip()
+ new_pydeps_data = self._input_api.subprocess.check_output(
+ cmd + ' --output ""', shell=True)
+ if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
+ return cmd
+
+
+def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
+ """Checks if a .pydeps file needs to be regenerated."""
+ # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
+ is_android = input_api.os_path.exists('third_party/android_tools')
+ pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
+ results = []
+ # First, check for new / deleted .pydeps.
+ for f in input_api.AffectedFiles(include_deletes=True):
+ if f.LocalPath().endswith('.pydeps'):
+ if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
+ results.append(output_api.PresubmitError(
+ 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
+ 'remove %s' % f.LocalPath()))
+ elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
+ results.append(output_api.PresubmitError(
+ 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
+ 'include %s' % f.LocalPath()))
+
+ if results:
+ return results
+
+ checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
+
+ for pydep_path in checker.ComputeAffectedPydeps():
+ try:
+ cmd = checker.DetermineIfStale(pydep_path)
+ if cmd:
+ results.append(output_api.PresubmitError(
+ 'File is stale: %s\nTo regenerate, run:\n\n %s' %
+ (pydep_path, cmd)))
+ except input_api.subprocess.CalledProcessError as error:
+ return [output_api.PresubmitError('Error running: %s' % error.cmd,
+ long_text=error.output)]
+
+ return results
+
+
def _CheckForCopyrightedCode(input_api, output_api):
"""Verifies that newly added code doesn't contain copyrighted material
and is properly licensed under the standard Chromium license.
@@ -1704,6 +1808,7 @@ def _CommonChecks(input_api, output_api):
results.extend(_CheckForWindowsLineEndings(input_api, output_api))
results.extend(_CheckSingletonInHeaders(input_api, output_api))
results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
+ results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
« no previous file with comments | « no previous file | PRESUBMIT_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698