diff --git a/recipes/README.recipes.md b/recipes/README.recipes.md index c15be443f..02be67380 100644 --- a/recipes/README.recipes.md +++ b/recipes/README.recipes.md @@ -26,6 +26,7 @@ * [depot_tools:examples/full](#recipes-depot_tools_examples_full) * [fetch_end_to_end_test](#recipes-fetch_end_to_end_test) * [gclient:examples/full](#recipes-gclient_examples_full) + * [gclient:tests/diff_deps](#recipes-gclient_tests_diff_deps) * [gclient:tests/patch_project](#recipes-gclient_tests_patch_project) * [gclient:tests/sync_failure](#recipes-gclient_tests_sync_failure) * [gerrit:examples/full](#recipes-gerrit_examples_full) @@ -259,28 +260,32 @@ Returns (Path): The "depot_tools" root directory.   **@property**
— **def [upload\_to\_google\_storage\_path](/recipes/recipe_modules/depot_tools/api.py#17)(self):** ### *recipe_modules* / [gclient](/recipes/recipe_modules/gclient) -[DEPS](/recipes/recipe_modules/gclient/__init__.py#1): [gitiles](#recipe_modules-gitiles), [tryserver](#recipe_modules-tryserver), [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/python][recipe_engine/recipe_modules/python], [recipe\_engine/step][recipe_engine/recipe_modules/step] +[DEPS](/recipes/recipe_modules/gclient/__init__.py#1): [git](#recipe_modules-git), [gitiles](#recipe_modules-gitiles), [tryserver](#recipe_modules-tryserver), [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/python][recipe_engine/recipe_modules/python], [recipe\_engine/raw\_io][recipe_engine/recipe_modules/raw_io], [recipe\_engine/step][recipe_engine/recipe_modules/step] -#### **class [GclientApi](/recipes/recipe_modules/gclient/api.py#65)([RecipeApi][recipe_engine/wkt/RecipeApi]):** +#### **class [GclientApi](/recipes/recipe_modules/gclient/api.py#68)([RecipeApi][recipe_engine/wkt/RecipeApi]):** -— **def [\_\_call\_\_](/recipes/recipe_modules/gclient/api.py#75)(self, name, cmd, infra_step=True, \*\*kwargs):** +  **@property**
— **def [DepsDiffException](/recipes/recipe_modules/gclient/api.py#426)(self):** + +— **def [\_\_call\_\_](/recipes/recipe_modules/gclient/api.py#78)(self, name, cmd, infra_step=True, \*\*kwargs):** Wrapper for easy calling of gclient steps. -— **def [break\_locks](/recipes/recipe_modules/gclient/api.py#271)(self):** +— **def [break\_locks](/recipes/recipe_modules/gclient/api.py#274)(self):** Remove all index.lock files. If a previous run of git crashed, bot was reset, etc... we might end up with leftover index.lock files. -— **def [checkout](/recipes/recipe_modules/gclient/api.py#231)(self, gclient_config=None, revert=RevertOnTryserver, inject_parent_got_revision=True, extra_sync_flags=None, \*\*kwargs):** +— **def [checkout](/recipes/recipe_modules/gclient/api.py#234)(self, gclient_config=None, revert=RevertOnTryserver, inject_parent_got_revision=True, extra_sync_flags=None, \*\*kwargs):** Return a step generator function for gclient checkouts. -  **@staticmethod**
— **def [config\_to\_pythonish](/recipes/recipe_modules/gclient/api.py#120)(cfg):** +  **@staticmethod**
— **def [config\_to\_pythonish](/recipes/recipe_modules/gclient/api.py#123)(cfg):** + +— **def [diff\_deps](/recipes/recipe_modules/gclient/api.py#365)(self, cwd):** -— **def [get\_config\_defaults](/recipes/recipe_modules/gclient/api.py#114)(self):** +— **def [get\_config\_defaults](/recipes/recipe_modules/gclient/api.py#117)(self):** -— **def [get\_gerrit\_patch\_root](/recipes/recipe_modules/gclient/api.py#293)(self, gclient_config=None):** +— **def [get\_gerrit\_patch\_root](/recipes/recipe_modules/gclient/api.py#296)(self, gclient_config=None):** Returns local path to the repo where gerrit patch will be applied. @@ -293,7 +298,7 @@ Instead, properly map a repository to a local path using repo_path_map. TODO(nodir): remove this. Update all recipe tests to specify a git_repo matching the recipe. -— **def [get\_repo\_path](/recipes/recipe_modules/gclient/api.py#320)(self, repo_url, gclient_config=None):** +— **def [get\_repo\_path](/recipes/recipe_modules/gclient/api.py#323)(self, repo_url, gclient_config=None):** Returns local path to the repo checkout given its url. @@ -301,7 +306,7 @@ Consults cfg.repo_path_map and fallbacks to urls in configured solutions. Returns None if not found. -  **@staticmethod**
— **def [got\_revision\_reverse\_mapping](/recipes/recipe_modules/gclient/api.py#125)(cfg):** +  **@staticmethod**
— **def [got\_revision\_reverse\_mapping](/recipes/recipe_modules/gclient/api.py#128)(cfg):** Returns the merged got_revision_reverse_mapping. @@ -309,7 +314,7 @@ Returns (dict): A mapping from property name -> project name. It merges the values of the deprecated got_revision_mapping and the new got_revision_reverse_mapping. -— **def [inject\_parent\_got\_revision](/recipes/recipe_modules/gclient/api.py#206)(self, gclient_config=None, override=False):** +— **def [inject\_parent\_got\_revision](/recipes/recipe_modules/gclient/api.py#209)(self, gclient_config=None, override=False):** Match gclient config to build revisions obtained from build_properties. @@ -319,22 +324,22 @@ Args: override (bool) - If True, will forcibly set revision and custom_vars even if the config already contains values for them. -— **def [resolve\_revision](/recipes/recipe_modules/gclient/api.py#142)(self, revision):** +— **def [resolve\_revision](/recipes/recipe_modules/gclient/api.py#145)(self, revision):** -— **def [runhooks](/recipes/recipe_modules/gclient/api.py#265)(self, args=None, name='runhooks', \*\*kwargs):** +— **def [runhooks](/recipes/recipe_modules/gclient/api.py#268)(self, args=None, name='runhooks', \*\*kwargs):** -— **def [set\_patch\_repo\_revision](/recipes/recipe_modules/gclient/api.py#350)(self, gclient_config=None):** +— **def [set\_patch\_repo\_revision](/recipes/recipe_modules/gclient/api.py#353)(self, gclient_config=None):** Updates config revision corresponding to patched project. Useful for bot_update only, as this is the only consumer of gclient's config revision map. This doesn't overwrite the revision if it was already set. -  **@spec_alias.deleter**
— **def [spec\_alias](/recipes/recipe_modules/gclient/api.py#110)(self):** +  **@spec_alias.deleter**
— **def [spec\_alias](/recipes/recipe_modules/gclient/api.py#113)(self):** -— **def [sync](/recipes/recipe_modules/gclient/api.py#147)(self, cfg, extra_sync_flags=None, \*\*kwargs):** +— **def [sync](/recipes/recipe_modules/gclient/api.py#150)(self, cfg, extra_sync_flags=None, \*\*kwargs):** -  **@use_mirror.setter**
— **def [use\_mirror](/recipes/recipe_modules/gclient/api.py#97)(self, val):** +  **@use_mirror.setter**
— **def [use\_mirror](/recipes/recipe_modules/gclient/api.py#100)(self, val):** ### *recipe_modules* / [gerrit](/recipes/recipe_modules/gerrit) [DEPS](/recipes/recipe_modules/gerrit/__init__.py#1): [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/python][recipe_engine/recipe_modules/python], [recipe\_engine/raw\_io][recipe_engine/recipe_modules/raw_io], [recipe\_engine/step][recipe_engine/recipe_modules/step] @@ -953,6 +958,11 @@ Raises: [DEPS](/recipes/recipe_modules/gclient/examples/full.py#5): [gclient](#recipe_modules-gclient), [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/step][recipe_engine/recipe_modules/step] — **def [RunSteps](/recipes/recipe_modules/gclient/examples/full.py#55)(api):** +### *recipes* / [gclient:tests/diff\_deps](/recipes/recipe_modules/gclient/tests/diff_deps.py) + +[DEPS](/recipes/recipe_modules/gclient/tests/diff_deps.py#7): [gclient](#recipe_modules-gclient), [recipe\_engine/assertions][recipe_engine/recipe_modules/assertions], [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/raw\_io][recipe_engine/recipe_modules/raw_io] + +— **def [RunSteps](/recipes/recipe_modules/gclient/tests/diff_deps.py#18)(api):** ### *recipes* / [gclient:tests/patch\_project](/recipes/recipe_modules/gclient/tests/patch_project.py) [DEPS](/recipes/recipe_modules/gclient/tests/patch_project.py#9): [gclient](#recipe_modules-gclient), [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/properties][recipe_engine/recipe_modules/properties] @@ -1036,6 +1046,7 @@ Move things around in a loop! — **def [RunSteps](/recipes/recipe_modules/windows_sdk/examples/full.py#13)(api):** +[recipe_engine/recipe_modules/assertions]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/59e7d3f289e8f160db10bbcd311b299805080c4b/README.recipes.md#recipe_modules-assertions [recipe_engine/recipe_modules/buildbucket]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/59e7d3f289e8f160db10bbcd311b299805080c4b/README.recipes.md#recipe_modules-buildbucket [recipe_engine/recipe_modules/cipd]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/59e7d3f289e8f160db10bbcd311b299805080c4b/README.recipes.md#recipe_modules-cipd [recipe_engine/recipe_modules/commit_position]: https://chromium.googlesource.com/infra/luci/recipes-py.git/+/59e7d3f289e8f160db10bbcd311b299805080c4b/README.recipes.md#recipe_modules-commit_position diff --git a/recipes/recipe_modules/gclient/__init__.py b/recipes/recipe_modules/gclient/__init__.py index 9eadd0494..d7d8b7039 100644 --- a/recipes/recipe_modules/gclient/__init__.py +++ b/recipes/recipe_modules/gclient/__init__.py @@ -1,4 +1,5 @@ DEPS = [ + 'git', 'gitiles', 'recipe_engine/context', 'recipe_engine/json', @@ -6,6 +7,7 @@ DEPS = [ 'recipe_engine/platform', 'recipe_engine/properties', 'recipe_engine/python', + 'recipe_engine/raw_io', 'recipe_engine/step', 'tryserver', ] diff --git a/recipes/recipe_modules/gclient/api.py b/recipes/recipe_modules/gclient/api.py index 4c6802415..2915a1d67 100644 --- a/recipes/recipe_modules/gclient/api.py +++ b/recipes/recipe_modules/gclient/api.py @@ -2,8 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import re from recipe_engine import recipe_api +class DepsDiffException(Exception): + pass class RevisionResolver(object): """Resolves the revision based on build properties.""" @@ -358,3 +361,68 @@ class GclientApi(recipe_api.RecipeApi): path, revision = cfg.repo_path_map.get(repo_url, (None, None)) if path and revision and path not in cfg.revisions: cfg.revisions[path] = revision + + def diff_deps(self, cwd): + cwd = cwd.join(self.get_gerrit_patch_root()) + with self.m.context(cwd=cwd): + step_result = self.m.git( + '-c', + 'core.quotePath=false', + 'checkout', + 'HEAD~', + '--', + 'DEPS', + name='checkout the previous DEPS', + stdout=self.m.raw_io.output() + ) + + try: + cfg = self.c + + step_result = self( + 'recursively git diff all DEPS', + [ + 'recurse', + self.resource('diff_deps.py'), + ], + stdout=self.m.raw_io.output_text(add_output_log=True), + ) + + paths = [] + # gclient recurse prepends a number and a > to each line + # Let's take that out + for line in step_result.stdout.strip().splitlines(): + if 'fatal: bad object' in line: + msg = "Couldn't checkout previous ref: %s" % line + step_result.presentation.logs['DepsDiffException'] = msg + raise self.DepsDiffException(msg) + elif re.match('\d+>', line): + paths.append(line[line.index('>') + 1:]) + + + # Normalize paths + if self.m.platform.is_win: + # Looks like "analyze" wants POSIX slashes even on Windows (since git + # uses that format even on Windows). + paths = [path.replace('\\', '/') for path in paths] + + if len(paths) > 0: + return paths + else: + msg = 'Unexpected result: autoroll diff found 0 files changed' + step_result.presentation.logs['DepsDiffException'] = msg + raise self.DepsDiffException(msg) + + finally: + self.m.git( + '-c', + 'core.quotePath=false', + 'checkout', + 'HEAD', + '--', + 'DEPS', + name="checkout the original DEPS") + + @property + def DepsDiffException(self): + return DepsDiffException diff --git a/recipes/recipe_modules/gclient/resources/diff_deps.py b/recipes/recipe_modules/gclient/resources/diff_deps.py new file mode 100755 index 000000000..8330cedc4 --- /dev/null +++ b/recipes/recipe_modules/gclient/resources/diff_deps.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +import os +import subprocess +import sys + +if '@' in os.environ.get('GCLIENT_URL'): + ref = os.environ.get('GCLIENT_URL').split('@')[-1] +else: + sys.exit(0) + +diff = subprocess.check_output("git diff --cached --name-only %s" % ref, shell=True) + +dep_path = os.environ.get('GCLIENT_DEP_PATH', '') +for line in diff.splitlines(): + if line: + print(os.path.join(dep_path, line)) diff --git a/recipes/recipe_modules/gclient/test_api.py b/recipes/recipe_modules/gclient/test_api.py index 58d678419..663c01e50 100644 --- a/recipes/recipe_modules/gclient/test_api.py +++ b/recipes/recipe_modules/gclient/test_api.py @@ -7,6 +7,10 @@ import hashlib from recipe_engine import recipe_test_api class GclientTestApi(recipe_test_api.RecipeTestApi): + def diff_deps_test_data(self, files): + return self.m.raw_io.stream_output( + '\n'.join(['10>%s' % fname for fname in files])) + def output_json(self, projects): """Deterministically synthesize json.output test data for gclient's --output-json option. diff --git a/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json b/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json new file mode 100644 index 000000000..d9c7266ad --- /dev/null +++ b/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json @@ -0,0 +1,55 @@ +[ + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD~", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the previous DEPS" + }, + { + "cmd": [ + "python", + "-u", + "RECIPE_REPO[depot_tools]/gclient.py", + "recurse", + "RECIPE_MODULE[depot_tools::gclient]/resources/diff_deps.py" + ], + "cwd": "[CACHE]/src", + "env_suffixes": { + "PATH": [ + "RECIPE_REPO[depot_tools]" + ] + }, + "infra_step": true, + "name": "gclient recursively git diff all DEPS", + "~followup_annotations": [ + "@@@STEP_LOG_LINE@raw_io.output_text@10>third_party/mockfile1@@@", + "@@@STEP_LOG_LINE@raw_io.output_text@10>third_party/mockfile2@@@", + "@@@STEP_LOG_END@raw_io.output_text@@@" + ] + }, + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the original DEPS" + }, + { + "name": "$result" + } +] \ No newline at end of file diff --git a/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json b/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json new file mode 100644 index 000000000..43c53f3e1 --- /dev/null +++ b/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json @@ -0,0 +1,84 @@ +[ + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD~", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the previous DEPS" + }, + { + "cmd": [ + "python", + "-u", + "RECIPE_REPO[depot_tools]/gclient.py", + "recurse", + "RECIPE_MODULE[depot_tools::gclient]/resources/diff_deps.py" + ], + "cwd": "[CACHE]/src", + "env_suffixes": { + "PATH": [ + "RECIPE_REPO[depot_tools]" + ] + }, + "infra_step": true, + "name": "gclient recursively git diff all DEPS", + "~followup_annotations": [ + "@@@STEP_LOG_LINE@raw_io.output_text@fatal: bad object abcdef1234567890@@@", + "@@@STEP_LOG_END@raw_io.output_text@@@", + "@@@STEP_LOG_LINE@DepsDiffException@Couldn't checkout previous ref: fatal: bad object abcdef1234567890@@@", + "@@@STEP_LOG_END@DepsDiffException@@@" + ] + }, + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the original DEPS" + }, + { + "cmd": [], + "name": "RECIPE CRASH (Uncaught exception)", + "~followup_annotations": [ + "@@@STEP_EXCEPTION@@@", + "The recipe has crashed at point 'Uncaught exception'!", + "", + "Traceback (most recent call last):", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/engine.py\", in run_steps", + " raw_result = recipe_obj.run_steps(api, engine)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/recipe_deps.py\", in run_steps", + " properties_def, api=api)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/property_invoker.py\", in invoke_with_properties", + " arg_names, **additional_args)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/property_invoker.py\", in _invoke_with_properties", + " return callable_obj(*props, **additional_args)", + " File \"RECIPE_REPO[depot_tools]/recipes/recipe_modules/gclient/tests/diff_deps.py\", line 33, in RunSteps", + " affected_files = api.gclient.diff_deps(api.path['cache'])", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/recipe_api.py\", in _inner", + " return func(*a, **kw)", + " File \"RECIPE_REPO[depot_tools]/recipes/recipe_modules/gclient/api.py\", line 398, in diff_deps", + " raise self.DepsDiffException(msg)", + "DepsDiffException: Couldn't checkout previous ref: fatal: bad object abcdef1234567890" + ] + }, + { + "failure": { + "humanReason": "Uncaught Exception: DepsDiffException(\"Couldn't checkout previous ref: fatal: bad object abcdef1234567890\",)" + }, + "name": "$result" + } +] \ No newline at end of file diff --git a/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json b/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json new file mode 100644 index 000000000..a4f77ef72 --- /dev/null +++ b/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json @@ -0,0 +1,83 @@ +[ + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD~", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the previous DEPS" + }, + { + "cmd": [ + "python", + "-u", + "RECIPE_REPO[depot_tools]/gclient.py", + "recurse", + "RECIPE_MODULE[depot_tools::gclient]/resources/diff_deps.py" + ], + "cwd": "[CACHE]/src", + "env_suffixes": { + "PATH": [ + "RECIPE_REPO[depot_tools]" + ] + }, + "infra_step": true, + "name": "gclient recursively git diff all DEPS", + "~followup_annotations": [ + "@@@STEP_LOG_END@raw_io.output_text@@@", + "@@@STEP_LOG_LINE@DepsDiffException@Unexpected result: autoroll diff found 0 files changed@@@", + "@@@STEP_LOG_END@DepsDiffException@@@" + ] + }, + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD", + "--", + "DEPS" + ], + "cwd": "[CACHE]/src", + "infra_step": true, + "name": "checkout the original DEPS" + }, + { + "cmd": [], + "name": "RECIPE CRASH (Uncaught exception)", + "~followup_annotations": [ + "@@@STEP_EXCEPTION@@@", + "The recipe has crashed at point 'Uncaught exception'!", + "", + "Traceback (most recent call last):", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/engine.py\", in run_steps", + " raw_result = recipe_obj.run_steps(api, engine)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/recipe_deps.py\", in run_steps", + " properties_def, api=api)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/property_invoker.py\", in invoke_with_properties", + " arg_names, **additional_args)", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/internal/property_invoker.py\", in _invoke_with_properties", + " return callable_obj(*props, **additional_args)", + " File \"RECIPE_REPO[depot_tools]/recipes/recipe_modules/gclient/tests/diff_deps.py\", line 33, in RunSteps", + " affected_files = api.gclient.diff_deps(api.path['cache'])", + " File \"RECIPE_REPO[recipe_engine]/recipe_engine/recipe_api.py\", in _inner", + " return func(*a, **kw)", + " File \"RECIPE_REPO[depot_tools]/recipes/recipe_modules/gclient/api.py\", line 414, in diff_deps", + " raise self.DepsDiffException(msg)", + "DepsDiffException: Unexpected result: autoroll diff found 0 files changed" + ] + }, + { + "failure": { + "humanReason": "Uncaught Exception: DepsDiffException('Unexpected result: autoroll diff found 0 files changed',)" + }, + "name": "$result" + } +] \ No newline at end of file diff --git a/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json b/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json new file mode 100644 index 000000000..1cf6530a6 --- /dev/null +++ b/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json @@ -0,0 +1,55 @@ +[ + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD~", + "--", + "DEPS" + ], + "cwd": "[CACHE]\\src", + "infra_step": true, + "name": "checkout the previous DEPS" + }, + { + "cmd": [ + "python", + "-u", + "RECIPE_REPO[depot_tools]\\gclient.py", + "recurse", + "RECIPE_MODULE[depot_tools::gclient]\\resources\\diff_deps.py" + ], + "cwd": "[CACHE]\\src", + "env_suffixes": { + "PATH": [ + "RECIPE_REPO[depot_tools]" + ] + }, + "infra_step": true, + "name": "gclient recursively git diff all DEPS", + "~followup_annotations": [ + "@@@STEP_LOG_LINE@raw_io.output_text@10>third_party/mockfile1@@@", + "@@@STEP_LOG_LINE@raw_io.output_text@10>third_party/mockfile2@@@", + "@@@STEP_LOG_END@raw_io.output_text@@@" + ] + }, + { + "cmd": [ + "git", + "-c", + "core.quotePath=false", + "checkout", + "HEAD", + "--", + "DEPS" + ], + "cwd": "[CACHE]\\src", + "infra_step": true, + "name": "checkout the original DEPS" + }, + { + "name": "$result" + } +] \ No newline at end of file diff --git a/recipes/recipe_modules/gclient/tests/diff_deps.py b/recipes/recipe_modules/gclient/tests/diff_deps.py new file mode 100644 index 000000000..bc31434f2 --- /dev/null +++ b/recipes/recipe_modules/gclient/tests/diff_deps.py @@ -0,0 +1,88 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from recipe_engine import post_process + +DEPS = [ + 'recipe_engine/assertions', + 'recipe_engine/buildbucket', + 'recipe_engine/path', + 'recipe_engine/platform', + 'recipe_engine/properties', + 'recipe_engine/raw_io', + + 'gclient', +] + +def RunSteps(api): + src_cfg = api.gclient.make_config(CACHE_DIR=api.path['cache'].join('git')) + + soln = src_cfg.solutions.add() + soln.name = 'src' + soln.url = 'https://chromium.googlesource.com/chromium/src.git' + src_cfg.repo_path_map.update({ + 'https://chromium.googlesource.com/src': ('src', 'HEAD'), + 'https://chromium.googlesource.com/v8/v8': ('src/v8', 'HEAD'), + # non-canonical URL + 'https://webrtc.googlesource.com/src.git': ( + 'src/third_party/webrtc', 'HEAD'), + }) + + api.gclient.c = src_cfg + affected_files = api.gclient.diff_deps(api.path['cache']) + + api.assertions.assertEqual( + affected_files, + list(api.properties.get('diff_deps_files')), + ) + +def GenTests(api): + test_files = ( + 'third_party/mockfile1', + 'third_party/mockfile2' + ) + no_test_files = [] + + yield api.test( + 'basic', + api.buildbucket.try_build(), + api.properties(diff_deps_files=test_files), + api.override_step_data( + 'gclient recursively git diff all DEPS', + api.gclient.diff_deps_test_data(test_files), + ), + api.post_process(post_process.StatusSuccess), + ) + + yield api.test( + 'no change, exception', + api.buildbucket.try_build(), + api.properties(diff_deps_files=no_test_files), + api.override_step_data( + 'gclient recursively git diff all DEPS', + api.gclient.diff_deps_test_data(no_test_files), + ), + api.expect_exception('DepsDiffException') + ) + yield api.test( + 'dont have revision yet', + api.buildbucket.try_build(), + api.properties(diff_deps_files=test_files), + api.override_step_data( + 'gclient recursively git diff all DEPS', + api.raw_io.stream_output('fatal: bad object abcdef1234567890'), + ), + api.expect_exception('DepsDiffException') + ) + yield api.test( + 'windows', + api.buildbucket.try_build(), + api.properties(diff_deps_files=test_files), + api.platform.name('win'), + api.override_step_data( + 'gclient recursively git diff all DEPS', + api.gclient.diff_deps_test_data(test_files), + ), + api.post_process(post_process.StatusSuccess), + )