Don't deduplicate additional_coursier_options (#1596)
Co-authored-by: Nikolay <n.matyushin@tawasal.ae>
diff --git a/private/extensions/maven.bzl b/private/extensions/maven.bzl
index 1bf3487..d534bbf 100644
--- a/private/extensions/maven.bzl
+++ b/private/extensions/maven.bzl
@@ -578,6 +578,16 @@
seen.append(item)
return merged_list
+def concat_coursier_options(root_list, non_root_list):
+ """Concatenate coursier options (root first), never deduplicating.
+
+ Unlike the other repo list attributes, `additional_coursier_options` is an
+ ordered argument vector passed verbatim to coursier, not a set. It can
+ legitimately contain repeated identical tokens (e.g. coursier's repeatable
+ `--variant` flag), so deduplicating it would corrupt the argument list.
+ """
+ return root_list + non_root_list
+
def remove_fields(s):
"""Used for reducing an artifact struct down to only those fields that have values"""
return {
@@ -694,11 +704,16 @@
merged_repo["boms"] = _deduplicate_non_root_artifacts(bazel_dep_to_non_root_boms, True)
# For list attributes, concatenate but avoid duplicates (root items first)
- for list_attr in ["repositories", "excluded_artifacts", "additional_netrc_lines", "additional_coursier_options"]:
+ for list_attr in ["repositories", "excluded_artifacts", "additional_netrc_lines"]:
root_list = root_repo.get(list_attr, [])
non_root_list = non_root_repo.get(list_attr, [])
merged_repo[list_attr] = _merge_repo_lists(root_list, non_root_list)
+ merged_repo["additional_coursier_options"] = concat_coursier_options(
+ root_repo.get("additional_coursier_options", []),
+ non_root_repo.get("additional_coursier_options", []),
+ )
+
repos[repo_name] = merged_repo
# Breaking out the logic for picking lock files, because it's not terribly simple
diff --git a/tests/unit/BUILD b/tests/unit/BUILD
index ea20414..7f86a4d 100644
--- a/tests/unit/BUILD
+++ b/tests/unit/BUILD
@@ -1,5 +1,6 @@
load(":amend_artifact_test.bzl", "amend_artifact_test_suite")
load(":artifact_utilities_test.bzl", "artifact_utilities_test_suite")
+load(":concat_coursier_options_test.bzl", "concat_coursier_options_test_suite")
load(":coordinates_test.bzl", "coordinates_test_suite")
load(":coursier_test.bzl", "coursier_test_suite")
load(":coursier_utilities_test.bzl", "coursier_utilities_test_suite")
@@ -17,6 +18,8 @@
artifact_utilities_test_suite()
+concat_coursier_options_test_suite()
+
coordinates_test_suite()
coursier_test_suite()
diff --git a/tests/unit/concat_coursier_options_test.bzl b/tests/unit/concat_coursier_options_test.bzl
new file mode 100644
index 0000000..f8d72a6
--- /dev/null
+++ b/tests/unit/concat_coursier_options_test.bzl
@@ -0,0 +1,69 @@
+"""Tests for merging `additional_coursier_options` across modules.
+
+These options form an ordered argument vector passed verbatim to coursier, so
+they must be concatenated (root first) and never deduplicated.
+"""
+
+load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
+load("//private/extensions:maven.bzl", "concat_coursier_options")
+
+def _preserves_repeated_tokens_impl(ctx):
+ env = unittest.begin(ctx)
+
+ # coursier's `--variant` flag is repeatable; deduplicating would collapse
+ # the repeated `--variant` tokens and corrupt the argument list.
+ root_options = [
+ "--enable-modules",
+ "--variant",
+ "org.gradle.category=library",
+ "--variant",
+ "org.gradle.usage=runtime",
+ ]
+
+ merged = concat_coursier_options(root_options, [])
+
+ asserts.equals(env, root_options, merged)
+
+ return unittest.end(env)
+
+preserves_repeated_tokens_test = unittest.make(_preserves_repeated_tokens_impl)
+
+def _concatenates_root_first_impl(ctx):
+ env = unittest.begin(ctx)
+
+ root_options = ["--enable-modules"]
+ non_root_options = ["--variant", "org.gradle.usage=runtime"]
+
+ merged = concat_coursier_options(root_options, non_root_options)
+
+ # Root options come first, then non-root, with nothing dropped.
+ asserts.equals(
+ env,
+ ["--enable-modules", "--variant", "org.gradle.usage=runtime"],
+ merged,
+ )
+
+ return unittest.end(env)
+
+concatenates_root_first_test = unittest.make(_concatenates_root_first_impl)
+
+def _keeps_cross_module_duplicates_impl(ctx):
+ env = unittest.begin(ctx)
+
+ # The same flag declared by both a root and a non-root module is kept twice:
+ # we cannot safely deduplicate an ordered, positional argument vector.
+ merged = concat_coursier_options(["--enable-modules"], ["--enable-modules"])
+
+ asserts.equals(env, ["--enable-modules", "--enable-modules"], merged)
+
+ return unittest.end(env)
+
+keeps_cross_module_duplicates_test = unittest.make(_keeps_cross_module_duplicates_impl)
+
+def concat_coursier_options_test_suite():
+ unittest.suite(
+ "concat_coursier_options_tests",
+ preserves_repeated_tokens_test,
+ concatenates_root_first_test,
+ keeps_cross_module_duplicates_test,
+ )