githooks: enter the chroot in presubmits
In general, running tests is likely best done in a consistent
environment. The more pressing concern here is that depot_tools doesn't
fully support python3 yet, so things like our `yapf` check always fail
outside of the chroot, if they happen to pick up on depot_tools' yapf.
BUG=chromium:1030828
TEST=Ran presubmits on files with type annotations. They now work inside
or outside of the chroot.
Change-Id: If22a3766e01ea26ebc9e78bc4b40d90ad5d49049
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2182163
Reviewed-by: Tiancong Wang <tcwang@google.com>
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Tested-by: George Burgess <gbiv@chromium.org>
diff --git a/toolchain_utils_githooks/check-presubmit.py b/toolchain_utils_githooks/check-presubmit.py
index fc6ec9f..8f20405 100755
--- a/toolchain_utils_githooks/check-presubmit.py
+++ b/toolchain_utils_githooks/check-presubmit.py
@@ -23,6 +23,7 @@
import sys
import threading
import traceback
+import typing as t
def run_command_unchecked(command, cwd, env=None):
@@ -459,13 +460,69 @@
'some lints may now be fixed')
+def find_repo_root(base_dir: str) -> t.Optional[str]:
+ current = base_dir
+ while current != '/':
+ if os.path.isdir(os.path.join(current, '.repo')):
+ return current
+ current = os.path.dirname(current)
+ return None
+
+
+def maybe_reexec_inside_chroot(autofix: bool, files: t.List[str]) -> None:
+ if os.path.exists('/etc/cros_chroot_version'):
+ return
+
+ enter_chroot = True
+ toolchain_utils = detect_toolchain_utils_root()
+ if find_repo_root(toolchain_utils) is None:
+ print('Standalone toolchain-utils checkout detected; cannot enter chroot.')
+ enter_chroot = False
+
+ if not has_executable_on_path('cros_sdk'):
+ print('No `cros_sdk` detected on $PATH; cannot enter chroot.')
+ enter_chroot = False
+
+ if not enter_chroot:
+ print('Giving up on entering the chroot; be warned that some presubmits '
+ 'may be broken.')
+ return
+
+ # We'll be changing ${PWD}, so make everything relative to toolchain-utils,
+ # which resides at a well-known place inside of the chroot.
+ chroot_toolchain_utils = '/mnt/host/source/src/third_party/toolchain-utils'
+
+ def rebase_path(path: str) -> str:
+ return os.path.join(chroot_toolchain_utils,
+ os.path.relpath(path, toolchain_utils))
+
+ args = [
+ 'cros_sdk',
+ '--enter',
+ '--',
+ rebase_path(__file__),
+ ]
+
+ if not autofix:
+ args.append('--no_autofix')
+ args.extend(rebase_path(x) for x in files)
+
+ print('Attempting to enter the chroot...')
+ os.execvp(args[0], args)
+
+
def main(argv):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'--no_autofix',
dest='autofix',
action='store_false',
- help="Don't run any autofix commands")
+ help="Don't run any autofix commands.")
+ parser.add_argument(
+ '--no_enter_chroot',
+ dest='enter_chroot',
+ action='store_false',
+ help="Prevent auto-entering the chroot if we're not already in it.")
parser.add_argument('files', nargs='*')
opts = parser.parse_args(argv)
@@ -473,6 +530,9 @@
if not files:
return 0
+ if opts.enter_chroot:
+ maybe_reexec_inside_chroot(opts.autofix, opts.files)
+
files = [os.path.abspath(f) for f in files]
# Note that we extract .__name__s from these, so please name them in a