Apply Maven exclusions to generated deps (#1594)
diff --git a/private/dependency_tree_parser.bzl b/private/dependency_tree_parser.bzl
index 0b82991..d8bb74c 100644
--- a/private/dependency_tree_parser.bzl
+++ b/private/dependency_tree_parser.bzl
@@ -64,6 +64,16 @@
unique_items.append(item)
return unique_items
+def _is_excluded_dependency(dep, exclusions):
+ dep_coordinates = unpack_coordinates(dep)
+ for exclusion in exclusions:
+ exclusion_coordinates = unpack_coordinates(exclusion)
+ group_matches = exclusion_coordinates.group == "*" or exclusion_coordinates.group == dep_coordinates.group
+ artifact_matches = exclusion_coordinates.artifact == "*" or exclusion_coordinates.artifact == dep_coordinates.artifact
+ if group_matches and artifact_matches:
+ return True
+ return False
+
def _find_repository_url(artifact_url, repositories):
longest_match = None
for repository in repositories:
@@ -183,10 +193,13 @@
# Dedupe dependencies here. Sometimes coursier will return "x.y:z:aar:version" and "x.y:z:version" in the
# same list of dependencies.
+ artifact_exclusions = exclusions.get(simple_coord, [])
target_import_labels = []
for dep in artifact["deps"]:
if get_packaging(dep) == "json":
continue
+ if _is_excluded_dependency(dep, artifact_exclusions):
+ continue
stripped_dep = strip_packaging_and_classifier_and_version(dep)
dep_target_label = escape(stripped_dep)
@@ -576,7 +589,10 @@
target_import_string.append("\texports = [")
target_import_labels = []
+ artifact_exclusions = exclusions.get(simple_coord, [])
for dep in artifact.get("deps", []):
+ if _is_excluded_dependency(dep, artifact_exclusions):
+ continue
dep_target_label = escape(strip_packaging_and_classifier_and_version(dep))
# Coursier returns cyclic dependencies sometimes. Handle it here.
diff --git a/tests/unit/BUILD b/tests/unit/BUILD
index f3a6e1d..e6cf8f2 100644
--- a/tests/unit/BUILD
+++ b/tests/unit/BUILD
@@ -3,6 +3,7 @@
load(":coordinates_test.bzl", "coordinates_test_suite")
load(":coursier_test.bzl", "coursier_test_suite")
load(":coursier_utilities_test.bzl", "coursier_utilities_test_suite")
+load(":dependency_tree_parser_test.bzl", "dependency_tree_parser_test_suite")
load(":java_utilities_test.bzl", "java_utilities_test_suite")
load(":maven_version_test.bzl", "maven_version_test_suite")
load(":proxy_test.bzl", "proxy_test_suite")
@@ -21,6 +22,8 @@
coursier_utilities_test_suite()
+dependency_tree_parser_test_suite()
+
java_utilities_test_suite()
maven_version_test_suite()
diff --git a/tests/unit/dependency_tree_parser_test.bzl b/tests/unit/dependency_tree_parser_test.bzl
new file mode 100644
index 0000000..fa43641
--- /dev/null
+++ b/tests/unit/dependency_tree_parser_test.bzl
@@ -0,0 +1,153 @@
+"""Tests for generated dependency tree BUILD target declarations."""
+
+load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
+load("//private:dependency_tree_parser.bzl", "parser")
+
+def _repo_ctx():
+ return struct(
+ attr = struct(
+ fetch_javadoc = False,
+ fetch_sources = False,
+ generate_compat_repositories = False,
+ maven_install_json = False,
+ repositories = ["{ \"repo_url\": \"https://repo1.maven.org/maven2/\" }"],
+ strict_visibility = False,
+ strict_visibility_value = ["//visibility:public"],
+ ),
+ )
+
+def _generate_imports(dependencies, exclusions):
+ result = parser.generate_imports(
+ repository_ctx = _repo_ctx(),
+ dependencies = dependencies,
+ explicit_artifacts = {},
+ neverlink_artifacts = {},
+ testonly_artifacts = {},
+ exclusions = exclusions,
+ override_targets = {},
+ override_target_visibilities = {},
+ skip_maven_local_dependencies = False,
+ )
+ return result[0]
+
+def _artifact(group_artifact, version, deps = []):
+ group, artifact = group_artifact.split(":")
+ return {
+ "coordinates": "%s:%s" % (group_artifact, version),
+ "deps": deps,
+ "file": "v1/https/repo1.maven.org/maven2/%s/%s/%s/%s-%s.jar" % (
+ group.replace(".", "/"),
+ artifact,
+ version,
+ artifact,
+ version,
+ ),
+ "urls": [
+ "https://repo1.maven.org/maven2/%s/%s/%s/%s-%s.jar" % (
+ group.replace(".", "/"),
+ artifact,
+ version,
+ artifact,
+ version,
+ ),
+ ],
+ }
+
+def _exclusion_removes_generated_dep_impl(ctx):
+ env = unittest.begin(ctx)
+
+ generated_imports = _generate_imports(
+ dependencies = [
+ _artifact(
+ "com.example:parent",
+ "1.0",
+ deps = [
+ "com.example:excluded:1.0",
+ "com.example:kept:1.0",
+ ],
+ ),
+ _artifact("com.example:excluded", "1.0"),
+ _artifact("com.example:kept", "1.0"),
+ ],
+ exclusions = {
+ "com.example:parent": [
+ "com.example:not-it",
+ "com.example:excluded",
+ ],
+ },
+ )
+
+ asserts.true(env, "\"maven_exclusion=com.example:not-it\"," in generated_imports)
+ asserts.true(env, "\"maven_exclusion=com.example:excluded\"," in generated_imports)
+ asserts.false(env, "\t\t\":com_example_excluded\",\n" in generated_imports)
+ asserts.true(env, "\t\t\":com_example_kept\",\n" in generated_imports)
+
+ return unittest.end(env)
+
+exclusion_removes_generated_dep_test = unittest.make(_exclusion_removes_generated_dep_impl)
+
+def _wildcard_exclusion_removes_all_generated_deps_impl(ctx):
+ env = unittest.begin(ctx)
+
+ generated_imports = _generate_imports(
+ dependencies = [
+ _artifact(
+ "com.example:parent",
+ "1.0",
+ deps = [
+ "com.example:first:1.0",
+ "com.example:second:1.0",
+ ],
+ ),
+ _artifact("com.example:first", "1.0"),
+ _artifact("com.example:second", "1.0"),
+ ],
+ exclusions = {
+ "com.example:parent": ["*:*"],
+ },
+ )
+
+ asserts.true(env, "\"maven_exclusion=*:*\"," in generated_imports)
+ asserts.false(env, "\t\t\":com_example_first\",\n" in generated_imports)
+ asserts.false(env, "\t\t\":com_example_second\",\n" in generated_imports)
+
+ return unittest.end(env)
+
+wildcard_exclusion_removes_all_generated_deps_test = unittest.make(_wildcard_exclusion_removes_all_generated_deps_impl)
+
+def _pom_only_exclusion_removes_generated_export_impl(ctx):
+ env = unittest.begin(ctx)
+
+ generated_imports = _generate_imports(
+ dependencies = [
+ {
+ "coordinates": "com.example:parent-pom:1.0@pom",
+ "deps": [
+ "com.example:excluded:1.0",
+ "com.example:kept:1.0",
+ ],
+ "file": None,
+ "urls": [],
+ },
+ _artifact("com.example:excluded", "1.0"),
+ _artifact("com.example:kept", "1.0"),
+ ],
+ exclusions = {
+ "com.example:parent-pom": ["com.example:excluded"],
+ },
+ )
+
+ asserts.false(env, "\t\t\":com_example_excluded\",\n" in generated_imports)
+ asserts.true(env, "\t\t\":com_example_kept\",\n" in generated_imports)
+
+ return unittest.end(env)
+
+pom_only_exclusion_removes_generated_export_test = unittest.make(_pom_only_exclusion_removes_generated_export_impl)
+
+def dependency_tree_parser_test_suite():
+ unittest.suite(
+ "dependency_tree_parser_tests",
+ exclusion_removes_generated_dep_test,
+ wildcard_exclusion_removes_all_generated_deps_test,
+ pom_only_exclusion_removes_generated_export_test,
+ )