This commit is contained in:
Reid 'arrdem' McKenzie 2024-02-12 18:57:45 -07:00
parent f7bce623bf
commit edec17510e
2 changed files with 25 additions and 42 deletions

View file

@ -1,3 +1,4 @@
py_project( py_project(
name = "bazelshim", name = "bazelshim",
main = "src/bazelshim/__main__.py",
) )

View file

@ -1,32 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""
A Bazel wrapper
===============
This script exists to allow for the setting of environment viariables and other context flags to
Bazel on behalf of the user. Consequently it has some magical (partial) knowledge of Bazel's CLI
options since it's really a CLI shim. This allows for user(s) to define their own Bazel CLI
middleware machinery while using structured and testable parsing rather than BASH nonsense.
It's important that this script stands "alone" because it needs to be usable mostly in isolation
with a non-hermetic interpreter before we can do Bazel builds.
For instance this script could be used as a basis to define custom Bazel tasks such as 'repl' (run
with some magic) or 'watch' as an alias for punting to ibazel/bazel-watcher.
Such a middleware can also be used to provide configurations which are hard to autodetect from
within Bazel in an appropriately structured way such as
`--action_env=GLIBC_VERSION=$(ldd --version)`
or
`--action_env=PLATFORM_FEATURE_POSTGRESQL=$(which pg_ctl >/dev/null 2>&1 && echo 'true' || echo 'false')`
I suggest using a `bazel` and maybe `bazelisk` shim script on your $PATH like
exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" \
--bazelshim_exclude="$(dirname $(realpath $0))" \
"$@"
"""
# Since this can't run under Bazel, we have to set up the sys.path ourselves # Since this can't run under Bazel, we have to set up the sys.path ourselves
import os import os
import sys import sys
@ -40,6 +13,7 @@ if (p := str(Path(sys.argv[0]).absolute().parent.parent)) not in sys.path:
from dataclasses import dataclass from dataclasses import dataclass
from shlex import quote, split as shlex from shlex import quote, split as shlex
import sys import sys
import tomllib
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import List, Optional
from itertools import chain from itertools import chain
@ -61,6 +35,7 @@ VERBS = [
"run", "run",
"sync", "sync",
"test", "test",
"watch",
] ]
@ -169,8 +144,11 @@ class BazelCli:
*self.startup_opts, *self.startup_opts,
] ]
if self.command: if self.command:
acc.append(self.command) if self.command == "watch":
acc.extend(self.command_opts) acc.extend(self.command_opts)
else:
acc.append(self.command)
acc.extend(self.command_opts)
if self.command == "test": if self.command == "test":
acc.extend(["--test_arg=" + it for it in self.subprocess_opts]) acc.extend(["--test_arg=" + it for it in self.subprocess_opts])
@ -190,23 +168,27 @@ class BazelCli:
def executable(self, exclude: List[Path]): def executable(self, exclude: List[Path]):
"""Try to resolve as via which() an executable to delegate to.""" """Try to resolve as via which() an executable to delegate to."""
for p in chain(which("bazelisk"), which("bazel")): if self.command == "watch":
if p.parent not in exclude: for p in chain(which("ibazel")):
return str(p) if p.parent not in exclude:
return str(p)
else:
for p in chain(which("bazelisk"), which("bazel")):
if p.parent not in exclude:
return str(p)
def render_text(self, next): def render_text(self, next):
lines = [] lines = []
lines.append(" " + next) lines.append(" " + next)
for arg in self.startup_opts: base_prefix = " "
lines.append(" " + arg) for arg in self.render_cli()[1:]:
if self.command: prefix = base_prefix
lines.append(" " + self.command) if arg in VERBS or arg == self.command:
for arg in self.command_opts: prefix = " "
lines.append(" " + arg) elif arg == "--":
if self.subprocess_opts: base_prefix += " "
lines.append(" --") lines.append(prefix + arg)
for arg in self.subprocess_opts:
lines.append(" " + arg)
return "\\\n".join(lines) return "\\\n".join(lines)