alchemist: Generate an @portage symlink in workspace root

It's kind of a pain right now to find the generated @portage repo.
Especially with the migration to bzlmod. The @portage repo doesn't exist
in any of the generated `bazel-` directories. This change
creates a @portage symlink in the workspace root. This makes it easier
for people to browse the generated repo. As a nice side effect, it also
fixes tab completion!

The alternative to this CL is to do the following:
    $ ls bazel-out/../../../external/_main~portage~portage/

This will be difficult for people to discover and remember.

In order to prevent `bazel build //...` from unexpectedly building
this repository, I'm guarding it behind an environment flag. This way
people will be aware of this case.

BUG=b:264578578
TEST=BOARD=arm64-generic bazel query @portage//:all
TEST=BOARD=arm64-generic bazel query @portage//<tab><tab>

Change-Id: I3cd809e25d3dd527a6400a4785cb3e0a3ff8b37f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/bazel/+/4595138
Reviewed-by: Matt Stark <msta@google.com>
Commit-Queue: Raul Rangel <rrangel@chromium.org>
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
Tested-by: Raul Rangel <rrangel@chromium.org>
Reviewed-by: Tim Bain <tbain@google.com>
diff --git a/module_extensions/portage/portage.bzl b/module_extensions/portage/portage.bzl
index f931420..ffc4516 100644
--- a/module_extensions/portage/portage.bzl
+++ b/module_extensions/portage/portage.bzl
@@ -11,6 +11,19 @@
 )
 """
 
+def _write_portage_symlink(repo_ctx, out):
+    # Generate an @portage symlink in the workspace root for easy access.
+    args = [
+        "ln",
+        "-fs",
+        out,
+        "%s/@portage" % (repo_ctx.workspace_root),
+    ]
+
+    st = repo_ctx.execute(args)
+    if st.return_code:
+        fail("Error running command %s:\n%s%s" % (args, st.stdout, st.stderr))
+
 def _portage_impl(repo_ctx):
     """Repository rule to generate the board's bazel BUILD files."""
 
@@ -58,6 +71,9 @@
         repo_ctx.file(out.get_child("settings.bzl"), content = "BOARD = None")
         repo_ctx.file(out.get_child("BUILD.bazel"), content = _EMPTY_PORTAGE_BUILD)
 
+    if repo_ctx.os.environ.get("ENABLE_PORTAGE_TAB_COMPLETION", "") == "1":
+        _write_portage_symlink(repo_ctx, out)
+
 portage = repository_rule(
     implementation = _portage_impl,
     attrs = dict(
@@ -69,6 +85,17 @@
         ),
         alchemist = attr.label(allow_single_file = True),
     ),
+    environ = [
+        # This will generate an @portage symlink in the workspace_root. This
+        # makes it easy to find the generated BUILD files, and also allows
+        # tab completion to work correctly. It's guarded because it's possible
+        # to accidentally try and build from this repo by doing the following:
+        #     bazel build //...
+        # Only enable this flag if you are aware of this edge case.
+        #
+        # Set this flag to 1 to enable the @portage symlink.
+        "ENABLE_PORTAGE_TAB_COMPLETION",
+    ],
     # Do not set this to true. It will force the evaluation to happen every
     # bazel invocation for unknown reasons...
     local = False,