Fix resolver NPE for no-binary artifacts (#1595)
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/BUILD
index 53dc9ba..cd78c91 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/BUILD
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/BUILD
@@ -6,6 +6,7 @@
srcs = glob(["*.java"]),
visibility = [
"//private/tools/java/com/github/bazelbuild/rules_jvm_external:__subpackages__",
+ "//tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle:__pkg__",
"//tests/com/github/bazelbuild/rules_jvm_external/resolver/lockfile:__pkg__",
],
deps = [
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/V3LockFile.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/V3LockFile.java
index 8a4cc93..d200069 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/V3LockFile.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile/V3LockFile.java
@@ -231,7 +231,11 @@
@SuppressWarnings("unchecked")
Map<String, String> shasums =
(Map<String, String>) artifactValue.computeIfAbsent("shasums", k -> new TreeMap<>());
- info.getSha256().ifPresent(sha -> shasums.put(classifier, sha));
+ if (info.getSha256().isPresent()) {
+ shasums.put(classifier, info.getSha256().get());
+ } else {
+ shasums.putIfAbsent(classifier, null);
+ }
info.getRepositories()
.forEach(
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/Downloader.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/Downloader.java
index c5aa48e..5e707a2 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/Downloader.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/Downloader.java
@@ -126,6 +126,9 @@
Path knownPath = knownPaths.get(coordsToUse);
if (knownPath != null && Files.exists(knownPath)) {
+ if (isPomPathForNonPomCoordinates(coordsToUse, knownPath)) {
+ return new DownloadResult(coordsToUse, Set.of(), null, null);
+ }
pathInRepo = knownPath;
} else {
// Check the local cache for the path first
@@ -221,6 +224,10 @@
return !JAR_PACKAGINGS.contains(extension);
}
+ private boolean isPomPathForNonPomCoordinates(Coordinates coords, Path path) {
+ return path.getFileName().toString().endsWith(".pom") && !"pom".equals(coords.getExtension());
+ }
+
private String calculateSha256(Path path) {
try {
byte[] bytes = Files.readAllBytes(path);
diff --git a/private/tools/prebuilt/lock_file_converter_deploy.jar b/private/tools/prebuilt/lock_file_converter_deploy.jar
index 0697a45..ef44459 100755
--- a/private/tools/prebuilt/lock_file_converter_deploy.jar
+++ b/private/tools/prebuilt/lock_file_converter_deploy.jar
Binary files differ
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
index ba998bf..9ce5360 100644
--- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/BUILD
@@ -37,7 +37,10 @@
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/events",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/gradle/models",
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/lockfile",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc",
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote",
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui",
"//tests/com/github/bazelbuild/rules_jvm_external/resolver",
artifact(
"junit:junit",
diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
index a5cef57..b8a2c6b 100644
--- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
+++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/gradle/GradleResolverTest.java
@@ -16,27 +16,37 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.github.bazelbuild.rules_jvm_external.Coordinates;
+import com.github.bazelbuild.rules_jvm_external.resolver.DependencyInfo;
import com.github.bazelbuild.rules_jvm_external.resolver.MavenRepo;
import com.github.bazelbuild.rules_jvm_external.resolver.ResolutionResult;
import com.github.bazelbuild.rules_jvm_external.resolver.ResolvedArtifact;
import com.github.bazelbuild.rules_jvm_external.resolver.Resolver;
import com.github.bazelbuild.rules_jvm_external.resolver.ResolverTestBase;
+import com.github.bazelbuild.rules_jvm_external.resolver.cmd.AbstractMain;
import com.github.bazelbuild.rules_jvm_external.resolver.cmd.ResolverConfig;
import com.github.bazelbuild.rules_jvm_external.resolver.events.EventListener;
+import com.github.bazelbuild.rules_jvm_external.resolver.lockfile.V3LockFile;
import com.github.bazelbuild.rules_jvm_external.resolver.netrc.Netrc;
+import com.github.bazelbuild.rules_jvm_external.resolver.remote.DownloadResult;
+import com.github.bazelbuild.rules_jvm_external.resolver.remote.Downloader;
+import com.github.bazelbuild.rules_jvm_external.resolver.ui.NullListener;
import com.google.common.graph.Graph;
import com.google.devtools.build.runfiles.AutoBazelRepository;
import com.google.devtools.build.runfiles.Runfiles;
import java.io.IOException;
+import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.TreeMap;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import org.junit.Test;
@@ -254,6 +264,82 @@
}
@Test
+ public void lockFileHashIncludesNoBinaryBaseArtifactWithClassifiedArtifact() throws IOException {
+ Coordinates baseCoordinates = new Coordinates("com.example:native-lib:1.0");
+ Coordinates classifiedCoordinates =
+ new Coordinates("com.example:native-lib:jar:osx-aarch_64:1.0");
+ URI repo = URI.create("https://example.com/repo/");
+ Path classifiedArtifact = Files.createTempFile("native-lib", ".jar");
+ String classifiedSha = "sha-for-classified-artifact";
+
+ Map<String, Object> rendered =
+ new V3LockFile(
+ Set.of(repo),
+ Set.of(
+ new DependencyInfo(
+ baseCoordinates,
+ Set.of(),
+ Optional.empty(),
+ Optional.empty(),
+ Set.of(classifiedCoordinates),
+ Set.of(),
+ Set.of(),
+ new TreeMap<>()),
+ new DependencyInfo(
+ classifiedCoordinates,
+ Set.of(repo),
+ Optional.of(classifiedArtifact),
+ Optional.of(classifiedSha),
+ Set.of(),
+ Set.of(),
+ Set.of(),
+ new TreeMap<>())),
+ Set.of(),
+ false)
+ .render();
+
+ Map<String, Integer> hashes = AbstractMain.calculateArtifactHash(rendered);
+ assertTrue(hashes.containsKey(baseCoordinates.asKey()));
+ assertTrue(hashes.containsKey(classifiedCoordinates.asKey()));
+
+ @SuppressWarnings("unchecked")
+ Map<String, Map<String, Object>> artifacts =
+ (Map<String, Map<String, Object>>) rendered.get("artifacts");
+ @SuppressWarnings("unchecked")
+ Map<String, String> shasums =
+ (Map<String, String>) artifacts.get("com.example:native-lib").get("shasums");
+ assertTrue(shasums.containsKey("jar"));
+ assertNull(shasums.get("jar"));
+ assertEquals(classifiedSha, shasums.get("osx-aarch_64"));
+ }
+
+ @Test
+ public void downloaderDoesNotUsePomKnownPathAsBinaryForNonPomCoordinate() throws IOException {
+ Coordinates coordinates = new Coordinates("com.example:pom-backed:1.0");
+ MavenRepo mavenRepo = MavenRepo.create().add(coordinates);
+ Path pomPath =
+ mavenRepo
+ .getPath()
+ .resolve(coordinates.toRepoPath())
+ .getParent()
+ .resolve("pom-backed-1.0.pom");
+ Files.delete(mavenRepo.getPath().resolve(coordinates.toRepoPath()));
+
+ DownloadResult download =
+ new Downloader(
+ Netrc.fromUserHome(),
+ Files.createTempDirectory("local-repo"),
+ Set.of(mavenRepo.getPath().toUri()),
+ new NullListener(),
+ false,
+ Map.of(coordinates, pomPath))
+ .download(coordinates);
+
+ assertTrue(download.getPath().isEmpty());
+ assertTrue(download.getSha256().isEmpty());
+ }
+
+ @Test
public void shouldRecordCorrectShaForResolvedVersionNotConflictingVersion() {
// When there's a version conflict, the paths map should contain only the resolved version,
// not the conflicting lower version. This ensures we record the correct SHA for the artifact.