From 1ffccfae5b473ae6359195e8edb6fe1d23a5ff87 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Mon, 12 Feb 2024 18:57:45 -0700
Subject: [PATCH] M0ar

---
 projects/bazelshim/BUILD.bazel               |  1 +
 projects/bazelshim/src/bazelshim/__main__.py | 66 +++++++-------------
 2 files changed, 25 insertions(+), 42 deletions(-)

diff --git a/projects/bazelshim/BUILD.bazel b/projects/bazelshim/BUILD.bazel
index f5177f6..5013a2e 100644
--- a/projects/bazelshim/BUILD.bazel
+++ b/projects/bazelshim/BUILD.bazel
@@ -1,3 +1,4 @@
 py_project(
     name = "bazelshim",
+    main = "src/bazelshim/__main__.py",
 )
diff --git a/projects/bazelshim/src/bazelshim/__main__.py b/projects/bazelshim/src/bazelshim/__main__.py
index 5a0a6fb..62923ca 100755
--- a/projects/bazelshim/src/bazelshim/__main__.py
+++ b/projects/bazelshim/src/bazelshim/__main__.py
@@ -1,32 +1,5 @@
 #!/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
 import os
 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 shlex import quote, split as shlex
 import sys
+import tomllib
 from pathlib import Path
 from typing import List, Optional
 from itertools import chain
@@ -61,6 +35,7 @@ VERBS = [
     "run",
     "sync",
     "test",
+    "watch",
 ]
 
 
@@ -169,8 +144,11 @@ class BazelCli:
             *self.startup_opts,
         ]
         if self.command:
-            acc.append(self.command)
-            acc.extend(self.command_opts)
+            if self.command == "watch":
+                acc.extend(self.command_opts)
+            else:
+                acc.append(self.command)
+                acc.extend(self.command_opts)
 
             if self.command == "test":
                 acc.extend(["--test_arg=" + it for it in self.subprocess_opts])
@@ -190,23 +168,27 @@ class BazelCli:
     def executable(self, exclude: List[Path]):
         """Try to resolve as via which() an executable to delegate to."""
 
-        for p in chain(which("bazelisk"), which("bazel")):
-            if p.parent not in exclude:
-                return str(p)
+        if self.command == "watch":
+            for p in chain(which("ibazel")):
+                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):
         lines = []
         lines.append("  " + next)
-        for arg in self.startup_opts:
-            lines.append("    " + arg)
-        if self.command:
-            lines.append("    " + self.command)
-            for arg in self.command_opts:
-                lines.append("      " + arg)
-        if self.subprocess_opts:
-            lines.append("    --")
-            for arg in self.subprocess_opts:
-                lines.append("      " + arg)
+        base_prefix = "      "
+        for arg in self.render_cli()[1:]:
+            prefix = base_prefix
+            if arg in VERBS or arg == self.command:
+                prefix = "    "
+            elif arg == "--":
+                base_prefix += "  "
+            lines.append(prefix + arg)
         return "\\\n".join(lines)