blob: 536cc65ff6ef3b54c98e4fb398611aa52d8187c7 [file] [log] [blame]
Mike Frysingerb847c562020-02-26 16:37:13 +00001#!/usr/bin/env python3
Jack Rosenthal54e86432023-07-25 19:22:55 +00002# Copyright 2011 The ChromiumOS Authors
ferringb@google.com0230d912012-03-23 19:33:18 +00003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
ferringb@google.com0230d912012-03-23 19:33:18 +00005"""Wrapper for chromite tools.
6
7The script is intend to be symlinked to any number of chromite tools, attempts
8to find the path for chromite, and hands off to the right tool via exec if
9possible.
10
11It is intended to used strictly outside of the chroot.
ferringb@google.com0230d912012-03-23 19:33:18 +000012"""
13
Mike Frysingercd9f6dc2023-10-27 18:40:02 +000014import enum
ferringb@google.com0230d912012-03-23 19:33:18 +000015import os
Mike Frysingerfa9968d2023-10-27 17:04:54 +000016from pathlib import Path
Brian Ryner252b1982023-01-03 22:56:22 +000017import subprocess
ferringb@google.com0230d912012-03-23 19:33:18 +000018import sys
Mike Frysingercd9f6dc2023-10-27 18:40:02 +000019from typing import List, NamedTuple, Optional, Tuple
ferringb@google.com0230d912012-03-23 19:33:18 +000020
Mike Frysingerb847c562020-02-26 16:37:13 +000021# Min version of Python that we *want*. We warn for older versions.
Mike Frysinger5decb172022-12-16 00:21:38 +000022MIN_PYTHON_VER_SOFT = (3, 8)
Mike Frysingerb847c562020-02-26 16:37:13 +000023# Min version of Python that we *require*. We abort for older versions.
Jack Rosenthalb5eff1c2023-04-27 21:39:03 +000024MIN_PYTHON_VER_HARD = (3, 8)
Mike Frysingerb847c562020-02-26 16:37:13 +000025
Mike Frysingerfa9968d2023-10-27 17:04:54 +000026DEPOT_TOOLS_DIR = Path(__file__).resolve().parent
Brian Ryner252b1982023-01-03 22:56:22 +000027
28# Directory where cros-specific CIPD packages are installed.
29CIPD_CACHE_DIR = DEPOT_TOOLS_DIR / '.cipd_bin_cros_python2'
30
Mike Frysingerb847c562020-02-26 16:37:13 +000031
Mike Frysingercd9f6dc2023-10-27 18:40:02 +000032class Checkout(NamedTuple):
33 """Some details about this checkout."""
34
35 root: Path
36 chromite_dir: Path
37
38
39def _FindChromite(path: Path) -> Optional[Checkout]:
Mike Frysinger124bb8e2023-09-06 05:48:55 +000040 """Find the chromite dir in a repo, gclient, or submodule checkout."""
Mike Frysingerfa9968d2023-10-27 17:04:54 +000041 path = path.resolve()
Mike Frysinger124bb8e2023-09-06 05:48:55 +000042 # Depending on the checkout type (whether repo chromeos or gclient chrome)
43 # Chromite lives in a different location.
44 roots = (
Mike Frysingerffd07cc2023-10-09 16:34:09 +000045 # CrOS checkout using normal manifest.
Mike Frysinger124bb8e2023-09-06 05:48:55 +000046 ('.repo', 'chromite/.git'),
Mike Frysingerffd07cc2023-10-09 16:34:09 +000047 # CrOS checkout using CitC.
48 ('../.citc', 'chromite/__init__.py'),
49 # Chromium checkout using gclient+DEPS.
Mike Frysinger124bb8e2023-09-06 05:48:55 +000050 ('.gclient', 'src/third_party/chromite/.git'),
Mike Frysingerffd07cc2023-10-09 16:34:09 +000051 # Chromium checkout using git submodules.
Mike Frysinger124bb8e2023-09-06 05:48:55 +000052 ('src/.gitmodules', 'src/third_party/chromite/.git'),
Mike Frysingerffd07cc2023-10-09 16:34:09 +000053 # Chromium checkout using CitC.
54 ('../.citc', 'third_party/chromite/__init__.py'),
Mike Frysinger124bb8e2023-09-06 05:48:55 +000055 )
rcui@google.com3f4f3fb2013-02-08 22:29:53 +000056
Mike Frysingerfa9968d2023-10-27 17:04:54 +000057 while path != Path("/"):
Mike Frysinger124bb8e2023-09-06 05:48:55 +000058 for root, chromite_git_dir in roots:
Mike Frysingercd9f6dc2023-10-27 18:40:02 +000059 if all((path / x).exists() for x in [root, chromite_git_dir]):
60 return Checkout(path, (path / chromite_git_dir).parent)
Mike Frysingerfa9968d2023-10-27 17:04:54 +000061 path = path.parent
Mike Frysinger124bb8e2023-09-06 05:48:55 +000062 return None
ferringb@google.com0230d912012-03-23 19:33:18 +000063
64
65def _MissingErrorOut(target):
Mike Frysinger124bb8e2023-09-06 05:48:55 +000066 sys.stderr.write("""ERROR: Couldn't find the chromite tool %s.
ferringb@google.com0230d912012-03-23 19:33:18 +000067
Jack Rosenthal54e86432023-07-25 19:22:55 +000068Please change to a directory inside your ChromiumOS source tree
69and retry. If you need to setup a ChromiumOS source tree, see
Mike Frysingerea98ebb2019-10-23 20:24:33 +000070 https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_guide.md
ferringb@google.com0230d912012-03-23 19:33:18 +000071""" % target)
Mike Frysinger124bb8e2023-09-06 05:48:55 +000072 return 127
ferringb@google.com0230d912012-03-23 19:33:18 +000073
74
Mike Frysingerb847c562020-02-26 16:37:13 +000075def _CheckPythonVersion():
Mike Frysinger124bb8e2023-09-06 05:48:55 +000076 """Verify active Python is new enough."""
77 if sys.version_info >= MIN_PYTHON_VER_SOFT:
78 return
Mike Frysingerb847c562020-02-26 16:37:13 +000079
Mike Frysinger124bb8e2023-09-06 05:48:55 +000080 progname = os.path.basename(sys.argv[0])
81 print('%s: ChromiumOS requires Python-%s+, but "%s" is "%s"' %
82 (progname, '.'.join(str(x) for x in MIN_PYTHON_VER_SOFT),
83 sys.executable, sys.version.replace('\n', ' ')),
Mike Frysingerb847c562020-02-26 16:37:13 +000084 file=sys.stderr)
Mike Frysinger124bb8e2023-09-06 05:48:55 +000085 if sys.version_info < MIN_PYTHON_VER_HARD:
86 print('%s: fatal: giving up since Python is too old.' % (progname, ),
87 file=sys.stderr)
88 sys.exit(1)
Mike Frysingerb847c562020-02-26 16:37:13 +000089
Mike Frysinger124bb8e2023-09-06 05:48:55 +000090 print(
91 'warning: temporarily continuing anyways; you must upgrade soon to '
92 'maintain support.',
93 file=sys.stderr)
Mike Frysingerb847c562020-02-26 16:37:13 +000094
95
Brian Ryner252b1982023-01-03 22:56:22 +000096def _BootstrapVpython27():
Mike Frysinger124bb8e2023-09-06 05:48:55 +000097 """Installs the vpython2.7 packages into the cipd cache directory."""
98 subprocess.run([
99 'cipd', 'ensure', '-log-level', 'info', '-ensure-file',
100 DEPOT_TOOLS_DIR / 'cipd_manifest_cros_python2.txt', '-root',
101 CIPD_CACHE_DIR
102 ],
103 check=True)
Brian Ryner252b1982023-01-03 22:56:22 +0000104
105
ferringb@google.com0230d912012-03-23 19:33:18 +0000106def main():
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000107 _CheckPythonVersion()
Mike Frysingerb847c562020-02-26 16:37:13 +0000108
Mike Frysingercd9f6dc2023-10-27 18:40:02 +0000109 result = _FindChromite(Path.cwd())
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000110 target = os.path.basename(sys.argv[0])
Mike Frysingercd9f6dc2023-10-27 18:40:02 +0000111 if result is None:
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000112 return _MissingErrorOut(target)
Mike Frysingercd9f6dc2023-10-27 18:40:02 +0000113 root, chromite_dir = result
114
115 is_citc = (root.parent / ".citc").is_dir()
116 if is_citc:
117 # citc workspaces don't like dirty files like pyc.
118 os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
rcui@google.com3f4f3fb2013-02-08 22:29:53 +0000119
Mike Frysingerfa9968d2023-10-27 17:04:54 +0000120 path = chromite_dir / "bin" / target
Brian Ryner252b1982023-01-03 22:56:22 +0000121
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000122 # Check to see if this is a script requiring vpython2.7.
Mike Frysingerfa9968d2023-10-27 17:04:54 +0000123 with path.open("rb") as fp:
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000124 shebang = next(fp).strip()
125 interpreter = shebang.split()[-1]
126 if interpreter in (b'python', b'python2', b'python2.7', b'vpython'):
127 _BootstrapVpython27()
128 vpython = CIPD_CACHE_DIR / 'vpython'
129 args = [vpython]
130 if interpreter != b'vpython':
131 args.extend(
132 ['-vpython-spec', DEPOT_TOOLS_DIR / 'cros_python2.vpython'])
133 args.append(path)
134 path = vpython
135 else:
136 args = [path]
Brian Ryner252b1982023-01-03 22:56:22 +0000137
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000138 os.execv(path, args + sys.argv[1:])
ferringb@google.com0230d912012-03-23 19:33:18 +0000139
ferringb@google.com0230d912012-03-23 19:33:18 +0000140
141if __name__ == '__main__':
Mike Frysinger124bb8e2023-09-06 05:48:55 +0000142 sys.exit(main())