Bazel: Add EE8 servlet bridge targets

Add Bazel-only generated EE8 targets for the HTTP servlet and LFS
server modules. The generated jars keep the original JGit Java
packages and rewrite only servlet API references from jakarta.servlet
to javax.servlet.

The rewrite uses the shared servlet-flavour transform toolchain from
bazlets (transform_srcjar + generated_srcs_test.sh under //tools). It
is a plain sed package-prefix substitution; the universal servlet and
Jetty package mapping lives in bazlets and this consumer selects only
the direction (to_javax), so it carries no renames data and adds no
Maven dependency (no Eclipse Transformer CLI).

This supports source consumers that still run on EE8 while JGit master
uses Jakarta servlet APIs. Gerrit is the known downstream consumer in
that state today and consumes JGit from source through a git submodule.
With these targets, Gerrit can track JGit master without a dedicated
servlet-4 maintenance branch.

The goal is to let the servlet-4 branch be retired for Gerrit's
maintenance purposes. That branch was not offered as a stable JGit
release line. Keeping Gerrit on it makes JGit updates hard for Gerrit,
including updates for important fixes and improvements, and forces
repeated merge work from master onto a parallel branch.

Keep the maintenance surface small. The EE8 targets consume canonical
srcs filegroups backed by glob(["src/**/*.java"]), so new Java sources
flow into the generated jars without per-file BUILD updates. Resources
are also shared through canonical filegroups.

This Bazel change intentionally does not add Maven, Tycho/p2, or Maven
Central publication machinery. Maven support is added by the follow-up
Maven commit; Tycho/p2 remains out of scope because the EE8 jars export
the same packages as their canonical Jakarta counterparts and are not
co-installable with them.

Also avoid relocating Java packages to org.eclipse.jgit.*.ee8. Keeping
the same package names avoids source-consumer import churn, but means
the canonical Jakarta jars and generated EE8 jars must not share a
classpath.

Possible follow-ups are duplicate-classpath enforcement for source
consumers and additional generated EE8 modules only when a consumer
needs them.

Verify generated source layout, line counts, javax servlet rewriting,
and the absence of package-renamed .ee8 sources.

Change-Id: I897e4facbbae79349e8d1853ea4dab8d7087ba5b
diff --git a/BUILD b/BUILD
index b8d8b9f..b9be9cb 100644
--- a/BUILD
+++ b/BUILD
@@ -10,8 +10,10 @@
         "//org.eclipse.jgit.archive:jgit-archive",
         "//org.eclipse.jgit.http.apache:http-apache",
         "//org.eclipse.jgit.http.server:jgit-servlet",
+        "//org.eclipse.jgit.http.server.ee8:jgit-servlet-ee8",
         "//org.eclipse.jgit.lfs:jgit-lfs",
         "//org.eclipse.jgit.lfs.server:jgit-lfs-server",
+        "//org.eclipse.jgit.lfs.server.ee8:jgit-lfs-server-ee8",
         "//org.eclipse.jgit.junit:junit",
         "//org.eclipse.jgit.ssh.apache:ssh-apache",
         "//org.eclipse.jgit.ssh.apache.agent:ssh-apache-agent",
diff --git a/MODULE.bazel b/MODULE.bazel
index 37077bc..e95290a 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -2,6 +2,7 @@
 
 bazel_dep(name = "rules_java", version = "8.11.0")
 bazel_dep(name = "rules_jvm_external", version = "6.10")
+bazel_dep(name = "rules_shell", version = "0.6.1")
 bazel_dep(name = "rbe_autoconfig")
 git_override(
     module_name = "rbe_autoconfig",
@@ -17,7 +18,7 @@
 
 git_repository(
     name = "com_googlesource_gerrit_bazlets",
-    commit = "f9c119e45d9a241bee720b7fbd6c7fdbc952da5f",
+    commit = "156bae8bb0d329d8886f681c723979cbdb39d37c",
     remote = "https://gerrit.googlesource.com/bazlets",
 )
 
@@ -49,6 +50,7 @@
         "commons-io:commons-io:2.21.0",
         "commons-logging:commons-logging:1.3.5",
         "jakarta.servlet:jakarta.servlet-api:6.1.0",
+        "javax.servlet:javax.servlet-api:4.0.1",
         "junit:junit:4.13.2",
         "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
         "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index 5717851..fd0c91e 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -191,7 +191,8 @@
     "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
     "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
     "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592",
-    "https://bcr.bazel.build/modules/rules_shell/0.4.1/source.json": "4757bd277fe1567763991c4425b483477bb82e35e777a56fd846eb5cceda324a",
+    "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
+    "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
     "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
     "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
     "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186",
diff --git a/lib/BUILD b/lib/BUILD
index a84d93b..2bd9209 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -59,6 +59,7 @@
     visibility = [
         "//org.eclipse.jgit.lfs:__pkg__",
         "//org.eclipse.jgit.lfs.server:__pkg__",
+        "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
     ],
     exports = ["@external_deps//:com_google_code_gson_gson"],
 )
@@ -79,6 +80,7 @@
         "//org.eclipse.jgit.http.apache:__pkg__",
         "//org.eclipse.jgit.http.test:__pkg__",
         "//org.eclipse.jgit.lfs.server:__pkg__",
+        "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
         "//org.eclipse.jgit.lfs.server.test:__pkg__",
         "//org.eclipse.jgit.pgm:__pkg__",
     ],
@@ -309,6 +311,15 @@
 )
 
 java_library(
+    name = "javax-servlet-api",
+    visibility = [
+        "//org.eclipse.jgit.http.server.ee8:__pkg__",
+        "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
+    ],
+    exports = ["@external_deps//:javax_servlet_javax_servlet_api"],
+)
+
+java_library(
     name = "slf4j-api",
     visibility = ["//visibility:public"],
     exports = ["@external_deps//:org_slf4j_slf4j_api"],
diff --git a/org.eclipse.jgit.http.server.ee8/BUILD b/org.eclipse.jgit.http.server.ee8/BUILD
new file mode 100644
index 0000000..df39628
--- /dev/null
+++ b/org.eclipse.jgit.http.server.ee8/BUILD
@@ -0,0 +1,27 @@
+load("@rules_java//java:defs.bzl", "java_library")
+load("@com_googlesource_gerrit_bazlets//tools:servlet_transform.bzl", "transform_srcjar")
+
+package(default_visibility = ["//visibility:public"])
+
+transform_srcjar(
+    name = "jgit-http-server-ee8-srcs",
+    direction = "to_javax",
+    sources = ["//org.eclipse.jgit.http.server:srcs"],
+    src_prefix = "org.eclipse.jgit.http.server/src/",
+)
+
+filegroup(
+    name = "jgit-servlet-ee8-srcjar",
+    srcs = [":jgit-http-server-ee8-srcs"],
+)
+
+java_library(
+    name = "jgit-servlet-ee8",
+    srcs = [":jgit-http-server-ee8-srcs"],
+    resource_strip_prefix = "org.eclipse.jgit.http.server/resources",
+    resources = ["//org.eclipse.jgit.http.server:jgit-servlet-resources"],
+    deps = [
+        "//lib:javax-servlet-api",
+        "//org.eclipse.jgit:jgit",
+    ],
+)
diff --git a/org.eclipse.jgit.http.server/BUILD b/org.eclipse.jgit.http.server/BUILD
index cae8d88..f6b4a10 100644
--- a/org.eclipse.jgit.http.server/BUILD
+++ b/org.eclipse.jgit.http.server/BUILD
@@ -3,13 +3,22 @@
 package(default_visibility = ["//visibility:public"])
 
 filegroup(
+    name = "srcs",
+    srcs = glob(["src/**/*.java"]),
+    visibility = [
+        "//org.eclipse.jgit.http.server.ee8:__pkg__",
+        "//tools/jgit-ee8:__pkg__",
+    ],
+)
+
+filegroup(
     name = "jgit-servlet-resources",
     srcs = glob(["resources/**"]),
 )
 
 java_library(
     name = "jgit-servlet",
-    srcs = glob(["src/**/*.java"]),
+    srcs = [":srcs"],
     resource_strip_prefix = "org.eclipse.jgit.http.server/resources",
     resources = [":jgit-servlet-resources"],
     deps = [
diff --git a/org.eclipse.jgit.lfs.server.ee8/BUILD b/org.eclipse.jgit.lfs.server.ee8/BUILD
new file mode 100644
index 0000000..b07dae2
--- /dev/null
+++ b/org.eclipse.jgit.lfs.server.ee8/BUILD
@@ -0,0 +1,32 @@
+load("@rules_java//java:defs.bzl", "java_library")
+load("@com_googlesource_gerrit_bazlets//tools:servlet_transform.bzl", "transform_srcjar")
+
+package(default_visibility = ["//visibility:public"])
+
+transform_srcjar(
+    name = "jgit-lfs-server-ee8-srcs",
+    direction = "to_javax",
+    sources = ["//org.eclipse.jgit.lfs.server:srcs"],
+    src_prefix = "org.eclipse.jgit.lfs.server/src/",
+)
+
+filegroup(
+    name = "jgit-lfs-server-ee8-srcjar",
+    srcs = [":jgit-lfs-server-ee8-srcs"],
+)
+
+java_library(
+    name = "jgit-lfs-server-ee8",
+    srcs = [":jgit-lfs-server-ee8-srcs"],
+    resource_strip_prefix = "org.eclipse.jgit.lfs.server/resources",
+    resources = ["//org.eclipse.jgit.lfs.server:jgit-lfs-server-resources"],
+    deps = [
+        "//lib:gson",
+        "//lib:httpcore",
+        "//lib:javax-servlet-api",
+        "//lib:slf4j-api",
+        "//org.eclipse.jgit.http.apache:http-apache",
+        "//org.eclipse.jgit:jgit",
+        "//org.eclipse.jgit.lfs:jgit-lfs",
+    ],
+)
diff --git a/org.eclipse.jgit.lfs.server/BUILD b/org.eclipse.jgit.lfs.server/BUILD
index c363d52..d6b08a6 100644
--- a/org.eclipse.jgit.lfs.server/BUILD
+++ b/org.eclipse.jgit.lfs.server/BUILD
@@ -2,11 +2,25 @@
 
 package(default_visibility = ["//visibility:public"])
 
+filegroup(
+    name = "srcs",
+    srcs = glob(["src/**/*.java"]),
+    visibility = [
+        "//org.eclipse.jgit.lfs.server.ee8:__pkg__",
+        "//tools/jgit-ee8:__pkg__",
+    ],
+)
+
+filegroup(
+    name = "jgit-lfs-server-resources",
+    srcs = glob(["resources/**"]),
+)
+
 java_library(
     name = "jgit-lfs-server",
-    srcs = glob(["src/**/*.java"]),
+    srcs = [":srcs"],
     resource_strip_prefix = "org.eclipse.jgit.lfs.server/resources",
-    resources = glob(["resources/**"]),
+    resources = [":jgit-lfs-server-resources"],
     deps = [
         "//lib:gson",
         "//lib:httpcore",
diff --git a/tools/jgit-ee8/BUILD b/tools/jgit-ee8/BUILD
new file mode 100644
index 0000000..df5c27c
--- /dev/null
+++ b/tools/jgit-ee8/BUILD
@@ -0,0 +1,28 @@
+load("@rules_shell//shell:sh_test.bzl", "sh_test")
+
+sh_test(
+    name = "generated_srcs_test",
+    srcs = ["@com_googlesource_gerrit_bazlets//tools:generated_srcs_test.sh"],
+    args = [
+        "--forbid",
+        "jakarta\\.servlet",
+        "--forbid",
+        "org\\.eclipse\\.jgit\\..*\\.ee8",
+        "--require",
+        "javax\\.servlet",
+        "--module",
+        "org.eclipse.jgit.http.server/src/",
+        "$(location //org.eclipse.jgit.http.server.ee8:jgit-http-server-ee8-srcs)",
+        "$(locations //org.eclipse.jgit.http.server:srcs)",
+        "--module",
+        "org.eclipse.jgit.lfs.server/src/",
+        "$(location //org.eclipse.jgit.lfs.server.ee8:jgit-lfs-server-ee8-srcs)",
+        "$(locations //org.eclipse.jgit.lfs.server:srcs)",
+    ],
+    data = [
+        "//org.eclipse.jgit.http.server.ee8:jgit-http-server-ee8-srcs",
+        "//org.eclipse.jgit.http.server:srcs",
+        "//org.eclipse.jgit.lfs.server.ee8:jgit-lfs-server-ee8-srcs",
+        "//org.eclipse.jgit.lfs.server:srcs",
+    ],
+)
diff --git a/tools/jgit-ee8/README.md b/tools/jgit-ee8/README.md
new file mode 100644
index 0000000..5578d65
--- /dev/null
+++ b/tools/jgit-ee8/README.md
@@ -0,0 +1,50 @@
+# JGit EE8 Bazel bridge
+
+This package contains the Bazel-only bridge for source consumers that still run
+on EE8 and `javax.servlet` while JGit master uses `jakarta.servlet`.
+
+JGit hosts this bridge because Gerrit is a known downstream that consumes JGit
+from source through a git submodule and still runs Jetty 12 EE8. Keeping the
+bridge in JGit lets Gerrit track JGit master and avoids maintaining a long-lived
+servlet-4 branch just for Gerrit. That branch was never a stable JGit release
+line, so it is not a sustainable way for Gerrit to receive JGit maintenance
+updates.
+
+The bridge intentionally keeps the original JGit package names. It rewrites only
+servlet API references from `jakarta.servlet` to `javax.servlet`, then compiles
+generated jars from the rewritten source jars.
+
+Generated targets:
+
+* `//org.eclipse.jgit.http.server.ee8:jgit-servlet-ee8`
+* `//org.eclipse.jgit.lfs.server.ee8:jgit-lfs-server-ee8`
+
+Do not put one of these generated jars and its canonical Jakarta counterpart on
+the same classpath. They contain the same JGit classes.
+
+This is intentionally limited to Bazel source consumers. It does not add Maven,
+Tycho, p2, or Maven Central publication machinery. Those should be added only if
+a non-Bazel consumer needs published EE8 artifacts.
+
+Run:
+
+```sh
+bazelisk test //tools/jgit-ee8:generated_srcs_test
+```
+
+The test checks:
+
+* generated sources are derived from the canonical source filegroups
+* generated srcjar entries use Java package paths
+* generated sources preserve line counts for debugger breakpoints
+* generated sources contain `javax.servlet`, not `jakarta.servlet`
+* generated sources do not move JGit classes to an `.ee8` package
+
+Next steps:
+
+* Keep this source-consumer bridge while Gerrit runs on Jetty 12 EE8.
+* Reuse these targets for other Bazel source consumers that need EE8 output.
+* Add Maven/Tycho/p2 generation only when a non-Bazel consumer needs published
+  EE8 artifacts.
+* Keep the canonical `srcs` filegroups aligned with each servlet-facing
+  `java_library` so new Java sources are transformed automatically.