diff --git a/MODULE.bazel b/MODULE.bazel index b53443c6..e77ad3c2 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -37,3 +37,6 @@ use_repo(as_extension_test_ext, "bar", "foo") use_all_repos_test_ext = use_extension("//tests:modules_test.bzl", "use_all_repos_test_ext", dev_dependency = True) use_repo(use_all_repos_test_ext, "baz", "qux") + +apparent_repo_name_test_ext = use_extension("//tests:extensions/apparent_repo_name.bzl", "apparent_repo_name_test_ext", dev_dependency = True) +use_repo(apparent_repo_name_test_ext, "apparent-repo-name-test") diff --git a/WORKSPACE b/WORKSPACE index 3a4d21f5..9f3a1000 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -81,3 +81,7 @@ load("//tests/directory:external_directory_tests.bzl", "external_directory_tests external_directory_tests(name = "external_directory_tests") register_unittest_toolchains() + +load("//tests:extensions/apparent_repo_name.bzl", "apparent_repo_name_test_macro") + +apparent_repo_name_test_macro() diff --git a/docs/modules_doc.md b/docs/modules_doc.md index 18042eed..17e3088b 100755 --- a/docs/modules_doc.md +++ b/docs/modules_doc.md @@ -2,6 +2,48 @@ Skylib module containing utilities for Bazel modules and module extensions. + + +## modules.apparent_repo_name + +
+modules.apparent_repo_name(repository_ctx) ++ +Generates a repository's apparent name from a repository_ctx object. + +Useful when generating the default top level `BUILD` target for the +repository. + +Example: +```starlark +_ALIAS_TARGET_TEMPLATE = """alias( + name = "{name}", + actual = "@{target_repo_name}", + visibility = ["//visibility:public"], +) +""" + +def _alias_repository_impl(repository_ctx): + repository_ctx.file("BUILD", _ALIAS_TARGET_TEMPLATE.format( + name = apparent_repo_name(rctx), + target = rctx.attr.target_repo_name, + )) +``` + + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| repository_ctx | a repository_ctx object | none | + +**RETURNS** + +An apparent repo name derived from repository_ctx.name + + ## modules.as_extension diff --git a/lib/modules.bzl b/lib/modules.bzl index 61c8f87f..347e7db1 100644 --- a/lib/modules.bzl +++ b/lib/modules.bzl @@ -114,7 +114,47 @@ def _use_all_repos(module_ctx, reproducible = False): **extension_metadata_kwargs ) +def _apparent_repo_name(repository_ctx): + """Generates a repository's apparent name from a repository_ctx object. + + Useful when generating the default top level `BUILD` target for the + repository. + + Example: + ```starlark + _ALIAS_TARGET_TEMPLATE = \"\"\"alias( + name = "{name}", + actual = "@{target_repo_name}", + visibility = ["//visibility:public"], + ) + \"\"\" + + def _alias_repository_impl(repository_ctx): + repository_ctx.file("BUILD", _ALIAS_TARGET_TEMPLATE.format( + name = apparent_repo_name(rctx), + target = rctx.attr.target_repo_name, + )) + ``` + + Args: + repository_ctx: a repository_ctx object + + Returns: + An apparent repo name derived from repository_ctx.name + """ + repo_name = repository_ctx.name + + # Bazed on this pattern from the Bazel source: + # com.google.devtools.build.lib.cmdline.RepositoryName.VALID_REPO_NAME + for i in range(len(repo_name) - 1, -1, -1): + c = repo_name[i] + if not (c.isalnum() or c in "_-."): + return repo_name[i + 1:] + + return repo_name + modules = struct( as_extension = _as_extension, use_all_repos = _use_all_repos, + apparent_repo_name = _apparent_repo_name, ) diff --git a/tests/extensions/apparent_repo_name.bzl b/tests/extensions/apparent_repo_name.bzl new file mode 100644 index 00000000..cdf883e8 --- /dev/null +++ b/tests/extensions/apparent_repo_name.bzl @@ -0,0 +1,22 @@ +"""Repo rule and module extension used to test modules.apparent_repo_name""" + +load("//lib:modules.bzl", "modules") + +def _apparent_repo_name_test_repo_impl(repository_ctx): + repo_name = modules.apparent_repo_name(repository_ctx) + test_file = "repo-name.bzl" + repository_ctx.file("WORKSPACE") + repository_ctx.file("BUILD", """exports_files(["%s"])""" % test_file) + repository_ctx.file(test_file, "REPO_NAME = \"%s\"" % repo_name) + +apparent_repo_name_test_repo = repository_rule( + _apparent_repo_name_test_repo_impl, +) + +def apparent_repo_name_test_macro(): + apparent_repo_name_test_repo(name = "apparent-repo-name-test") + +apparent_repo_name_test_ext = module_extension( + lambda _: apparent_repo_name_test_macro(), + doc = "Only used for testing modules.apparent_repo_name()", +) diff --git a/tests/modules_test.bzl b/tests/modules_test.bzl index 0887463c..7e4b8657 100644 --- a/tests/modules_test.bzl +++ b/tests/modules_test.bzl @@ -14,9 +14,13 @@ """Test usage of modules.bzl.""" +load("@apparent-repo-name-test//:repo-name.bzl", "REPO_NAME") load("//lib:modules.bzl", "modules") +load("//lib:unittest.bzl", "asserts", "unittest") load("//rules:build_test.bzl", "build_test") +_is_bzlmod_enabled = str(Label("//tests:module_tests.bzl")).startswith("@@") + def _repo_rule_impl(repository_ctx): repository_ctx.file("WORKSPACE") repository_ctx.file("BUILD", """exports_files(["hello"])""") @@ -45,12 +49,34 @@ use_all_repos_test_ext = module_extension( doc = "Only used for testing modules.use_all_repos().", ) +def _apparent_repo_name_test(ctx): + """Unit tests for modules.apparent_repo_name.""" + env = unittest.begin(ctx) + + asserts.equals( + env, + "apparent-repo-name-test", + REPO_NAME, + msg = " ".join([ + "Returns the original name unchanged under WORKSPACE, and", + "the apparent repo name under Bzlmod.", + ]), + ) + + return unittest.end(env) + +apparent_repo_name_test = unittest.make(_apparent_repo_name_test) + # buildifier: disable=unnamed-macro def modules_test_suite(): """Creates the tests for modules.bzl if Bzlmod is enabled.""" - is_bzlmod_enabled = str(Label("//tests:module_tests.bzl")).startswith("@@") - if not is_bzlmod_enabled: + unittest.suite( + "modules_tests", + apparent_repo_name_test, + ) + + if not _is_bzlmod_enabled: return build_test(