Add gerrit_plugin_library() for splitting a plugin into internal layers

gerrit_plugin() bundles a plugin from a single srcs glob, which keeps
the whole plugin in one java_library (`<name>__plugin`) with no way to
express or enforce dependency edges between its own packages. For larger
plugins it is useful to split production code into per-package libraries
so the internal DAG is explicit -- for example to keep a native/protocol
layer from importing a dependency the rest of the plugin uses, enforced
by Bazel rather than by convention.

In-tree, Gerrit does this with tools/bzl:plugin.bzl's
PLUGIN_DEPS_NEVERLINK constant. bazlets dropped its
PLUGIN_DEPS/PLUGIN_DEPS_NEVERLINK/PLUGIN_TEST_DEPS constants as
WORKSPACE-era dead code, leaving only the lower-level
gerrit_api_neverlink() function, so today an internal library must
hand-roll `deps = gerrit_api_neverlink(name) + _artifacts(...)` and
repeat the standalone/in-tree handling per library.

Add gerrit_plugin_library() to encapsulate that once, mirroring
gerrit_plugin_test_util() but for production code:

 - puts the Gerrit plugin API on the compile-only (neverlink) classpath
   via gerrit_api_neverlink(), so the API is not bundled twice and both
   build modes (Gerrit in-tree and standalone plugin) work;
 - resolves Maven ext_deps against the plugin's rules_jvm_external repo
   (`<plugin>_plugin_deps` by default) -- the same repo gerrit_plugin()
   and gerrit_plugin_tests() use -- so a split library sees the same
   artifacts in both modes;
 - supports the same ext_deps / ext_deps_label / ext_repo options as the
   sibling helpers.

Unlike gerrit_plugin_test_util() the result is not testonly, does not
pull in the acceptance framework, and does not prepend
`:<plugin>__plugin`: an internal library is a lower layer than the
plugin wiring, so depending on the plugin would invert the DAG and,
since gerrit_plugin() depends back on the library, create a cycle. The
aggregating gerrit_plugin() references these libraries with a
package-relative label (no leading `//`) so it resolves under both the
//plugins/<name> in-tree mount and the standalone repo root.

No behavior change for existing plugins; this only adds a new helper.

Change-Id: Ib15033c455e75366458e117dcd89cf451ed4e805
diff --git a/gerrit_plugin.bzl b/gerrit_plugin.bzl
index 5bef560..3d76788 100644
--- a/gerrit_plugin.bzl
+++ b/gerrit_plugin.bzl
@@ -362,6 +362,76 @@
         **kwargs
     )
 
+def gerrit_plugin_library(
+        name,
+        srcs = [],
+        deps = [],
+        plugin = None,
+        ext_deps = [],
+        ext_deps_label = None,
+        ext_repo = None,
+        **kwargs):
+    """Creates a production java_library that is one internal layer of a Gerrit plugin.
+
+    Use this for plugin packages split out of the monolithic gerrit_plugin()
+    `srcs` glob so their dependency edges can be constrained explicitly -- i.e.
+    to control who-depends-on-whom inside the plugin's own DAG (for example, to
+    keep a native/protocol layer from importing a dependency the rest of the
+    plugin uses). The aggregating gerrit_plugin() target lists these libraries
+    in its `deps`.
+
+    The library gets the Gerrit plugin API on its compile-only (neverlink)
+    classpath via gerrit_api_neverlink(), so the API is not bundled twice, and
+    it works in both build modes (Gerrit in-tree and standalone plugin). Any
+    Maven `ext_deps` are resolved against the plugin's rules_jvm_external
+    repository (`<plugin>_plugin_deps` by default) -- the same repository the
+    plugin's gerrit_plugin()/gerrit_plugin_tests() targets use -- so a split
+    library sees the same artifacts in both build modes. The aggregating
+    gerrit_plugin() should reference these libraries with a package-relative
+    label (no leading `//`) so it resolves under both mounts.
+
+    This differs from gerrit_plugin_test_util() in three ways: the result is
+    production code (not `testonly`), it does not pull in the acceptance-test
+    framework, and it does NOT prepend the `:<plugin>__plugin` target -- an
+    internal library is a *lower* layer than the plugin's wiring, so depending
+    on the plugin would invert the intended DAG (and, since gerrit_plugin()
+    depends back on the library, would create a cycle).
+
+    Args:
+      name: Name of the library.
+      srcs: Java source files for the library.
+      deps: Additional Bazel dependencies, typically sibling plugin libraries
+        created by this macro.
+      plugin: Plugin name, used only to derive `ext_repo`
+        (`<plugin>_plugin_deps`) when `ext_deps` is set. Optional.
+      ext_deps: Maven coordinates resolved against `ext_repo`. Only one of
+        `ext_deps` or `ext_deps_label` may be provided.
+      ext_deps_label: Label of a java_library that exports Maven dependencies.
+        Only one of `ext_deps` or `ext_deps_label` may be provided.
+      ext_repo: Name of the rules_jvm_external repository. Defaults to
+        `<plugin>_plugin_deps` when `plugin` is set.
+      **kwargs: Additional arguments passed to the underlying java_library
+        (for example `visibility` or `resources`).
+    """
+    if ext_deps and ext_deps_label:
+        fail("Only one of `ext_deps` or `ext_deps_label` may be provided.")
+
+    if ext_deps:
+        if ext_repo == None:
+            if plugin == None:
+                fail("gerrit_plugin_library: `plugin` or `ext_repo` must be set when `ext_deps` is provided")
+            ext_repo = plugin + "_plugin_deps"
+        deps = deps + _artifacts(ext_deps, ext_repo)
+    elif ext_deps_label:
+        deps = deps + [ext_deps_label]
+
+    java_library(
+        name = name,
+        srcs = srcs,
+        deps = deps + gerrit_api_neverlink(name),
+        **kwargs
+    )
+
 def gerrit_plugin_test_util(
         name,
         srcs = [],