Prepare for Bazel Bzlmod build

Working towards: https://github.com/bazelbuild/bazel/issues/18957

- Updated MODULE.bazel and distdir_deps.bzl to match all dependencies
- Introduced the repo_cach_tar rule to help with boostrap build later.
- Introduced the test_repo_extension extension to prefetch testing dependencies.
- Use --experimental_downloader_config to overcome potential github.com instability.

RELNOTES: None.
PiperOrigin-RevId: 563045981
Change-Id: I8726a838bfe55908d87d17063121863f604e6211
diff --git a/extensions.bzl b/extensions.bzl
index de87962..83acdcd 100644
--- a/extensions.bzl
+++ b/extensions.bzl
@@ -16,33 +16,73 @@
 
 """
 
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
+load("//:distdir.bzl", "dist_http_archive", "repo_cache_tar")
+load("//:distdir_deps.bzl", "DIST_ARCHIVE_REPOS", "TEST_REPOS")
 load("//:repositories.bzl", "embedded_jdk_repositories")
-load("//:distdir.bzl", "dist_http_archive", "dist_http_jar")
-load("//tools/distributions/debian:deps.bzl", "debian_deps")
-load("//src/test/shell/bazel:list_source_repository.bzl", "list_source_repository")
 load("//src/main/res:winsdk_configure.bzl", "winsdk_configure")
+load("//src/test/shell/bazel:list_source_repository.bzl", "list_source_repository")
+load("//src/tools/bzlmod:utils.bzl", "parse_http_artifacts")
+load("//tools/distributions/debian:deps.bzl", "debian_deps")
 
-### Extra dependencies for building Bazel
-
-def _bazel_internal_deps(_ctx):
+### Dependencies for building Bazel
+def _bazel_build_deps(_ctx):
     embedded_jdk_repositories()
     debian_deps()
+    repo_cache_tar(name = "bootstrap_repo_cache", repos = DIST_ARCHIVE_REPOS, dirname = "derived/repository_cache")
 
-bazel_internal_deps = module_extension(implementation = _bazel_internal_deps)
+bazel_build_deps = module_extension(implementation = _bazel_build_deps)
 
-### Extra dependencies for testing Bazel
-
-def _bazel_dev_deps(_ctx):
+### Dependencies for testing Bazel
+def _bazel_test_deps(_ctx):
     list_source_repository(name = "local_bazel_source_list")
     dist_http_archive(name = "bazelci_rules")
     winsdk_configure(name = "local_config_winsdk")
 
-bazel_dev_deps = module_extension(implementation = _bazel_dev_deps)
+bazel_test_deps = module_extension(implementation = _bazel_test_deps)
 
-### Extra dependencies for Bazel Android tools
+_HUB_TEST_REPO_BUILD = """
+filegroup(
+  name="srcs",
+  srcs = {srcs},
+  visibility = ["//visibility:public"],
+)
+"""
 
+def _hub_test_repo_impl(ctx):
+    ctx.file(
+        "BUILD",
+        _HUB_TEST_REPO_BUILD.format(srcs = ["@%s//file" % repo for repo in ctx.attr.repos]),
+    )
+
+hub_test_repo = repository_rule(
+    implementation = _hub_test_repo_impl,
+    attrs = {"repos": attr.string_list()},
+)
+
+def _test_repo_extension_impl(ctx):
+    """This module extension is used to fetch http artifacts required for generating TEST_REPOS."""
+    lockfile_path = ctx.path(Label("//:MODULE.bazel.lock"))
+    http_artifacts = parse_http_artifacts(ctx, lockfile_path, TEST_REPOS)
+    name = "test_repo_"
+    cnt = 1
+    for artifact in http_artifacts:
+        # Define one http_file for each artifact so that we can fetch them in parallel.
+        http_file(
+            name = name + str(cnt),
+            url = artifact["url"],
+            sha256 = artifact["sha256"] if "sha256" in artifact else None,
+            integrity = artifact["integrity"] if "integrity" in artifact else None,
+        )
+        cnt += 1
+
+    # write a repo rule that depends on all the http_file rules
+    hub_test_repo(name = "test_repos", repos = [(name + str(i)) for i in range(1, cnt)])
+
+test_repo_extension = module_extension(implementation = _test_repo_extension_impl)
+
+### Dependencies for Bazel Android tools
 def _bazel_android_deps(_ctx):
-    dist_http_jar(name = "android_gmaven_r8")
     dist_http_archive(name = "desugar_jdk_libs")
 
 bazel_android_deps = module_extension(implementation = _bazel_android_deps)