Add support for publishing maven-metadata.xml (#1260)
Maven repositories normally have a maven-metadata.xml file that indicate to the Maven system what versions are available and which is to be considered the latest version.
```xml
<metadata modelVersion="1.1.0">
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<versioning>
<latest>1.0</latest>
<release>1.0</release>
<versions>
<version>1.0</version>
</versions>
<lastUpdated>20200731090423</lastUpdated>
</versioning>
</metadata>
```
At Confluent, we use AWS Code Artifactory which does not mark a Maven package as "published" unless a new maven-metadata.xml is uploaded indicating so.
Add support for reading existing maven-metadata.xml
Add support for adding the new version to the metadata object
Add support to upload the file for http, file, s3 protocols
Co-authored-by: Vince Rose <vrose@confluent.io>
Co-authored-by: Na Lou <nlou@confluent.io>
diff --git a/MODULE.bazel b/MODULE.bazel
index c7b09f1..79a0038 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -81,6 +81,7 @@
"org.apache.maven:maven-core:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-model:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-model-builder:%s" % _MAVEN_VERSION,
+ "org.apache.maven:maven-repository-metadata:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-settings:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-settings-builder:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-resolver-provider:%s" % _MAVEN_VERSION,
@@ -99,6 +100,7 @@
"org.slf4j:log4j-over-slf4j:2.0.12",
"org.slf4j:slf4j-simple:2.0.12",
"software.amazon.awssdk:s3:2.26.12",
+ "software.amazon.awssdk:sdk-core:2.26.12",
"org.bouncycastle:bcprov-jdk15on:1.68",
"org.bouncycastle:bcpg-jdk15on:1.68",
"org.gradle:gradle-tooling-api:%s" % _GRADLE_VERSION,
diff --git a/docs/api.md b/docs/api.md
index 4ea73d7..de01aef 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -50,7 +50,7 @@
java_export(<a href="#java_export-name">name</a>, <a href="#java_export-maven_coordinates">maven_coordinates</a>, <a href="#java_export-manifest_entries">manifest_entries</a>, <a href="#java_export-deploy_env">deploy_env</a>, <a href="#java_export-excluded_workspaces">excluded_workspaces</a>, <a href="#java_export-exclusions">exclusions</a>,
<a href="#java_export-pom_template">pom_template</a>, <a href="#java_export-allowed_duplicate_names">allowed_duplicate_names</a>, <a href="#java_export-visibility">visibility</a>, <a href="#java_export-tags">tags</a>, <a href="#java_export-testonly">testonly</a>, <a href="#java_export-classifier_artifacts">classifier_artifacts</a>,
- <a href="#java_export-kwargs">kwargs</a>)
+ <a href="#java_export-publish_maven_metadata">publish_maven_metadata</a>, <a href="#java_export-kwargs">kwargs</a>)
</pre>
Extends `java_library` to allow maven artifacts to be uploaded.
@@ -113,6 +113,7 @@
| <a id="java_export-tags"></a>tags | <p align="center"> - </p> | `[]` |
| <a id="java_export-testonly"></a>testonly | <p align="center"> - </p> | `None` |
| <a id="java_export-classifier_artifacts"></a>classifier_artifacts | A dict of classifier -> artifact of additional artifacts to publish to Maven. | `{}` |
+| <a id="java_export-publish_maven_metadata"></a>publish_maven_metadata | Whether to publish a maven-metadata.xml to remote repository. Some repositories (like AWS CodeArtifact) require the client to publish this file. It is disabled by default. | `False` |
| <a id="java_export-kwargs"></a>kwargs | <p align="center"> - </p> | none |
diff --git a/private/dependency_tree_parser.bzl b/private/dependency_tree_parser.bzl
index bfb9433..7d93543 100644
--- a/private/dependency_tree_parser.bzl
+++ b/private/dependency_tree_parser.bzl
@@ -29,7 +29,7 @@
"strip_packaging_and_classifier_and_version",
"to_repository_name",
)
-load("//private/lib:coordinates.bzl", "unpack_coordinates", "to_purl")
+load("//private/lib:coordinates.bzl", "to_purl", "unpack_coordinates")
load("//private/lib:urls.bzl", "scheme_and_host")
def _genrule_copy_artifact_from_http_file(artifact, visibilities):
diff --git a/private/rules/java_export.bzl b/private/rules/java_export.bzl
index 4fc8b37..055b33f 100644
--- a/private/rules/java_export.bzl
+++ b/private/rules/java_export.bzl
@@ -19,6 +19,7 @@
tags = [],
testonly = None,
classifier_artifacts = {},
+ publish_maven_metadata = False,
**kwargs):
"""Extends `java_library` to allow maven artifacts to be uploaded.
@@ -92,6 +93,8 @@
end of the package name. For example, `com.example.*` will include all the subpackages of `com.example`, while
`com.example` will include only the files directly in `com.example`
visibility: The visibility of the target
+ publish_maven_metadata: Whether to publish a maven-metadata.xml to remote repository. Some repositories
+ (like AWS CodeArtifact) require the client to publish this file. It is disabled by default.
kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library),
and so may contain any valid parameter for that rule.
"""
@@ -137,6 +140,7 @@
testonly = testonly,
javadocopts = javadocopts,
classifier_artifacts = classifier_artifacts,
+ publish_maven_metadata = publish_maven_metadata,
doc_deps = doc_deps,
doc_url = doc_url,
doc_resources = doc_resources,
@@ -167,6 +171,7 @@
doc_resources = [],
doc_excluded_packages = [],
doc_included_packages = [],
+ publish_maven_metadata = False,
toolchains = None):
"""
All arguments are the same as java_export with the addition of:
@@ -237,6 +242,8 @@
end of the package name. For example, `com.example.*` will include all the subpackages of `com.example`, while
`com.example` will include only the files directly in `com.example`
visibility: The visibility of the target
+ publish_maven_metadata: Whether to publish a maven-metadata.xml to remote repository. Some repositories
+ (like AWS CodeArtifact) require the client to publish this file. It is disabled by default.
kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library),
and so may contain any valid parameter for that rule.
"""
@@ -350,6 +357,7 @@
tags = tags,
testonly = testonly,
toolchains = toolchains,
+ publish_maven_metadata = publish_maven_metadata,
)
# We may want to aggregate several `java_export` targets into a single Maven BOM POM
diff --git a/private/rules/maven_publish.bzl b/private/rules/maven_publish.bzl
index bb68795..28f045a 100644
--- a/private/rules/maven_publish.bzl
+++ b/private/rules/maven_publish.bzl
@@ -18,7 +18,7 @@
export PGP_SIGNING_KEY="${{PGP_SIGNING_KEY:-{pgp_signing_key}}}"
export PGP_SIGNING_PWD="${{PGP_SIGNING_PWD:-{pgp_signing_pwd}}}"
echo Uploading "{coordinates}" to "${{MAVEN_REPO}}"
-{uploader} "{coordinates}" '{pom}' '{artifact}' '{classifier_artifacts}' $@
+{uploader} "{coordinates}" '{pom}' '{artifact}' '{publish_maven_metadata}' '{classifier_artifacts}' $@
"""
def _escape_arg(str):
@@ -68,6 +68,7 @@
pom = ctx.file.pom.short_path,
artifact = artifacts_short_path,
classifier_artifacts = ",".join(["{}={}".format(classifier, file.short_path) for (classifier, file) in classifier_artifacts_dict.items()]),
+ publish_maven_metadata = ctx.attr.publish_maven_metadata,
),
)
@@ -125,6 +126,10 @@
allow_single_file = True,
),
"classifier_artifacts": attr.label_keyed_string_dict(allow_files = True),
+ "publish_maven_metadata": attr.bool(
+ default = False,
+ doc = "Whether to publish a maven-metadata.xml to the Maven repository",
+ ),
"_uploader": attr.label(
executable = True,
cfg = "exec",
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD
index 972b662..54c482f 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD
@@ -11,6 +11,13 @@
visibility = ["//visibility:public"],
deps = [
"//private/tools/java/com/github/bazelbuild/rules_jvm_external",
+ "//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",
+ artifact(
+ "software.amazon.awssdk:sdk-core",
+ repository_name = "rules_jvm_external_deps",
+ ),
artifact(
"com.google.auth:google-auth-library-oauth2-http",
repository_name = "rules_jvm_external_deps",
@@ -43,6 +50,10 @@
"org.bouncycastle:bcpg-jdk15on",
repository_name = "rules_jvm_external_deps",
),
+ artifact(
+ "org.apache.maven:maven-repository-metadata",
+ repository_name = "rules_jvm_external_deps",
+ ),
],
)
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
index 55125d4..2ec0f8c 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
@@ -24,6 +24,8 @@
import static java.util.concurrent.TimeUnit.MINUTES;
import com.github.bazelbuild.rules_jvm_external.ByteStreams;
+import com.github.bazelbuild.rules_jvm_external.resolver.netrc.Netrc;
+import com.github.bazelbuild.rules_jvm_external.resolver.remote.HttpDownloader;
import com.google.auth.Credentials;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.WriteChannel;
@@ -31,26 +33,34 @@
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.common.base.Splitter;
+import com.google.common.io.CharStreams;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.UncheckedIOException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.time.Instant;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -58,8 +68,17 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import org.apache.maven.artifact.repository.metadata.Metadata;
+import org.apache.maven.artifact.repository.metadata.Versioning;
+import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
+import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.GetObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
+import software.amazon.awssdk.services.s3.model.S3Exception;
public class MavenPublisher {
@@ -68,16 +87,25 @@
private static final String[] SUPPORTED_SCHEMES = {
"file:/", "https://", "gs://", "s3://", "artifactregistry://"
};
+ private static final String[] SUPPORTED_UPLOAD_SCHEMES = {"file:/", "https://", "s3://"};
public static void main(String[] args)
throws IOException, InterruptedException, ExecutionException, TimeoutException {
String repo = System.getenv("MAVEN_REPO");
+ boolean publishMavenMetadata = Boolean.parseBoolean(args[3]);
+
if (!isSchemeSupported(repo)) {
throw new IllegalArgumentException(
"Repository must be accessed via the supported schemes: "
+ Arrays.toString(SUPPORTED_SCHEMES));
}
+ if (!isUploadSchemeSupported(repo)) {
+ throw new IllegalArgumentException(
+ "Repository must be uploaded to via the supported schemes: "
+ + Arrays.toString(SUPPORTED_UPLOAD_SCHEMES));
+ }
+
boolean gpgSign = Boolean.parseBoolean(System.getenv("GPG_SIGN"));
Credentials credentials =
new BasicAuthCredentials(System.getenv("MAVEN_USER"), System.getenv("MAVEN_PASSWORD"));
@@ -99,9 +127,6 @@
Path pom = Paths.get(args[1]);
Path mainArtifact = getPathIfSet(args[2]);
- Path maven_metadata_dir = null;
- Path maven_metadata_xml = null;
-
try {
List<CompletableFuture<Void>> futures = new ArrayList<>();
futures.add(upload(repo, credentials, coords, ".pom", pom, signingMetadata));
@@ -112,41 +137,8 @@
futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, signingMetadata));
}
- // Update maven-metadata for local maven repositories.
- // This makes it so the target maven repository can be directly used without further steps.
- if (repo.startsWith("file:/")) {
- maven_metadata_dir = Files.createTempDirectory("maven-metadata");
- maven_metadata_xml = maven_metadata_dir.resolve("maven-metadata.xml");
- String template =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- + "<metadata>\n"
- + " <groupId>{groupId}</groupId>\n"
- + " <artifactId>{artifactId}</artifactId>\n"
- + " <versioning>\n"
- + " <latest>{version}</latest>\n"
- + " <release>{version}</release>\n"
- + " <versions>\n"
- + " <version>{version}</version>\n"
- + " </versions>\n"
- + " <lastUpdated>{lastUpdated}</lastUpdated>\n"
- + " </versioning>\n"
- + "</metadata>\n";
- template = template.replace("{groupId}", coords.groupId);
- template = template.replace("{artifactId}", coords.artifactId);
- template = template.replace("{version}", coords.version);
- template =
- template.replace("{lastUpdated}", String.valueOf(Instant.now().getEpochSecond()));
- Files.writeString(maven_metadata_xml, template);
-
- String metadata_url =
- String.format(
- "%s/%s/%s/maven-metadata.xml",
- repo.replaceAll("/$", ""), coords.groupId.replace('.', '/'), coords.artifactId);
- futures.add(upload(metadata_url, credentials, maven_metadata_xml));
- }
-
- if (args.length > 3 && !args[3].isEmpty()) {
- List<String> extraArtifactTuples = Splitter.onPattern(",").splitToList(args[3]);
+ if (args.length > 4 && !args[4].isEmpty()) {
+ List<String> extraArtifactTuples = Splitter.onPattern(",").splitToList(args[4]);
for (String artifactTuple : extraArtifactTuples) {
String[] splits = artifactTuple.split("=");
String classifier = splits[0];
@@ -165,16 +157,18 @@
CompletableFuture<Void> all =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
+
+ // uploading the maven-metadata.xml signals to cut over to the new version, so it must be at
+ // the end.
+ // publishing the file is opt-in for remote repositories, but always done for local file
+ // repositories.
+ if (publishMavenMetadata || repo.startsWith("file:/")) {
+ all = all.thenCompose(Void -> uploadMavenMetadata(repo, credentials, coords));
+ }
+
all.get(30, MINUTES);
} finally {
EXECUTOR.shutdown();
-
- if (maven_metadata_xml != null) {
- Files.delete(maven_metadata_xml);
- }
- if (maven_metadata_dir != null) {
- Files.delete(maven_metadata_dir);
- }
}
}
@@ -194,6 +188,90 @@
return false;
}
+ private static boolean isUploadSchemeSupported(String repo) {
+ for (String scheme : SUPPORTED_UPLOAD_SCHEMES) {
+ if (repo.startsWith(scheme)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Download the pre-existing maven-metadata.xml file if it exists. If no such file exists, create
+ * a default Metadata with the Coordinates provided.
+ */
+ private static CompletableFuture<Metadata> downloadExistingMavenMetadata(
+ String repo, Coordinates coords) {
+ String mavenMetadataUrl =
+ String.format(
+ "%s/%s/%s/maven-metadata.xml",
+ repo.replaceAll("/$", ""), coords.groupId.replace('.', '/'), coords.artifactId);
+
+ return download(mavenMetadataUrl)
+ .thenApply(
+ optionalFileContents -> {
+ try {
+ if (optionalFileContents.isEmpty()) {
+ // no file so just upload a new one
+ // we must bootstrap
+ Metadata metadata = new Metadata();
+ metadata.setGroupId(coords.groupId);
+ metadata.setArtifactId(coords.artifactId);
+ metadata.setVersioning(new Versioning());
+ return metadata;
+ }
+ return new MetadataXpp3Reader()
+ .read(new StringReader(optionalFileContents.get()), false);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ /**
+ * Upload the new maven-metadata.xml with the new version included in the version list & set the
+ * latest and release tags in the Metadata XML object. This function will first download the
+ * pre-existing metadata-xml and augment. If no maven-metadata.xml exists, a new one will be
+ * hydrated.
+ */
+ private static CompletableFuture<Void> uploadMavenMetadata(
+ String repo, Credentials credentials, Coordinates coords) {
+
+ String mavenMetadataUrl =
+ String.format(
+ "%s/%s/%s/maven-metadata.xml",
+ repo.replaceAll("/$", ""), coords.groupId.replace('.', '/'), coords.artifactId);
+ return downloadExistingMavenMetadata(repo, coords)
+ .thenCompose(
+ metadata -> {
+ try {
+
+ // There is a chance versioning is null; handle it by creating the empty object.
+ Versioning versioning =
+ Optional.ofNullable(metadata.getVersioning()).orElse(new Versioning());
+ versioning.setLatest(coords.version);
+ versioning.setRelease(coords.version);
+ // This may be needed for SNAPSHOT support
+ String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+ versioning.setLastUpdated("20200731090423");
+ versioning.getVersions().add(coords.version);
+ // Let's handle adding multiple versions many times by turning it back to a set
+ versioning.setVersions(
+ versioning.getVersions().stream().distinct().collect(Collectors.toList()));
+ metadata.setVersioning(versioning);
+
+ Path newMavenMetadataXml = Files.createTempFile("maven-metadata", ".xml");
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ new MetadataXpp3Writer().write(os, metadata);
+ Files.write(newMavenMetadataXml, os.toByteArray());
+ return upload(mavenMetadataUrl, credentials, newMavenMetadataXml);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
private static CompletableFuture<Void> upload(
String repo,
Credentials credentials,
@@ -274,6 +352,79 @@
}
}
+ /**
+ * Attempts to download the file at the given targetUrl. Valid protocols are: http(s), file, and
+ * s3 at the moment.
+ */
+ private static CompletableFuture<Optional<String>> download(String targetUrl) {
+ if (targetUrl.startsWith("http")) {
+ return httpDownload(targetUrl);
+ } else if (targetUrl.startsWith("file:/")) {
+ return fileDownload(targetUrl);
+ } else if (targetUrl.startsWith("s3://")) {
+ return s3Download(targetUrl);
+ } else {
+ throw new IllegalArgumentException("Unsupported protocol for download: " + targetUrl);
+ }
+ }
+
+ private static CompletableFuture<Optional<String>> s3Download(String targetUrl) {
+ return CompletableFuture.supplyAsync(
+ () -> {
+ S3Client s3Client = S3Client.create();
+ try {
+ URI s3Uri = URI.create(targetUrl);
+ String bucketName = s3Uri.getHost();
+ String key = s3Uri.getPath().substring(1);
+ GetObjectRequest request =
+ GetObjectRequest.builder().bucket(bucketName).key(key).build();
+ ResponseInputStream<GetObjectResponse> s3Object = s3Client.getObject(request);
+ return Optional.of(
+ CharStreams.toString(new InputStreamReader(s3Object, StandardCharsets.UTF_8)));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ } catch (S3Exception e) {
+ if (e.statusCode() == 404) {
+ return Optional.empty();
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ private static CompletableFuture<Optional<String>> fileDownload(String targetUrl) {
+ return CompletableFuture.supplyAsync(
+ () -> {
+ try {
+ Path path = Paths.get(URI.create(targetUrl));
+ if (!Files.exists(path)) {
+ return Optional.empty();
+ }
+ return Optional.of(Files.readString(path, StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+ }
+
+ private static CompletableFuture<Optional<String>> httpDownload(String targetUrl) {
+ return CompletableFuture.supplyAsync(
+ () -> {
+ HttpDownloader downloader = new HttpDownloader(Netrc.fromUserHome());
+
+ Path path = downloader.get(URI.create(targetUrl));
+ if (path == null || !Files.exists(path)) {
+ return Optional.empty();
+ }
+ try {
+ return Optional.of(Files.readString(path, StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+ }
+
private static CompletableFuture<Void> upload(
String targetUrl, Credentials credentials, Path toUpload) {
Callable<Void> callable;
@@ -359,7 +510,7 @@
private static Callable<Void> writeFile(String targetUrl, Path toUpload) {
return () -> {
LOG.info(String.format("Copying %s to %s", toUpload, targetUrl));
- Path path = Paths.get(new URL(targetUrl).toURI());
+ Path path = Paths.get(URI.create(targetUrl));
Files.createDirectories(path.getParent());
Files.deleteIfExists(path);
Files.copy(toUpload, path);
@@ -371,7 +522,7 @@
private static Callable<Void> gcsUpload(String targetUrl, Path toUpload) {
return () -> {
Storage storage = StorageOptions.getDefaultInstance().getService();
- URI gsUri = new URI(targetUrl);
+ URI gsUri = URI.create(targetUrl);
String bucketName = gsUri.getHost();
String path = gsUri.getPath().substring(1);
@@ -389,7 +540,7 @@
private static Callable<Void> s3upload(String targetUrl, Path toUpload) {
return () -> {
S3Client s3Client = S3Client.create();
- URI s3Uri = new URI(targetUrl);
+ URI s3Uri = URI.create(targetUrl);
String bucketName = s3Uri.getHost();
String path = s3Uri.getPath().substring(1);
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/Main.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/Main.java
index 72fb87e..3f7a653 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/Main.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/Main.java
@@ -30,10 +30,8 @@
import com.github.bazelbuild.rules_jvm_external.resolver.lockfile.V2LockFile;
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.remote.HttpDownloader;
import com.github.bazelbuild.rules_jvm_external.resolver.remote.UriNotFoundException;
-import com.github.bazelbuild.rules_jvm_external.resolver.ui.AnsiConsoleListener;
-import com.github.bazelbuild.rules_jvm_external.resolver.ui.NullListener;
-import com.github.bazelbuild.rules_jvm_external.resolver.ui.PlainConsoleListener;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.graph.Graph;
@@ -49,7 +47,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -63,7 +60,7 @@
public static void main(String[] args) throws IOException {
Set<DependencyInfo> infos;
- try (EventListener listener = createEventListener()) {
+ try (EventListener listener = HttpDownloader.defaultEventListener()) {
ResolverConfig config = new ResolverConfig(listener, args);
ResolutionRequest request = config.getResolutionRequest();
@@ -83,17 +80,6 @@
}
}
- private static EventListener createEventListener() {
- boolean termAvailable = !Objects.equals(System.getenv().get("TERM"), "dumb");
- boolean consoleAvailable = System.console() != null;
- if (System.getenv("RJE_VERBOSE") != null) {
- return new PlainConsoleListener();
- } else if (termAvailable && consoleAvailable) {
- return new AnsiConsoleListener();
- }
- return new NullListener();
- }
-
private static Set<DependencyInfo> fulfillDependencyInfos(
EventListener listener, ResolverConfig config, Graph<Coordinates> resolved) {
listener.onEvent(new PhaseEvent("Downloading dependencies"));
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc/BUILD
index 0fd8382..28b86f0 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc/BUILD
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc/BUILD
@@ -5,6 +5,7 @@
name = "netrc",
srcs = glob(["*.java"]),
visibility = [
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/maven:__pkg__",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver:__subpackages__",
"//tests/com/github/bazelbuild/rules_jvm_external:__subpackages__",
],
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/BUILD
index 7ce876b..f8b6a86 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/BUILD
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/BUILD
@@ -5,6 +5,7 @@
name = "remote",
srcs = glob(["*.java"]),
visibility = [
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/maven:__pkg__",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver:__subpackages__",
"//tests/com/github/bazelbuild/rules_jvm_external/resolver:__subpackages__",
],
@@ -13,6 +14,7 @@
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/events",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/netrc",
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui",
artifact(
"com.google.guava:guava",
repository_name = "rules_jvm_external_deps",
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/HttpDownloader.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/HttpDownloader.java
index 882fc3a..7d65b45 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/HttpDownloader.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/remote/HttpDownloader.java
@@ -23,6 +23,9 @@
import com.github.bazelbuild.rules_jvm_external.resolver.events.EventListener;
import com.github.bazelbuild.rules_jvm_external.resolver.events.LogEvent;
import com.github.bazelbuild.rules_jvm_external.resolver.netrc.Netrc;
+import com.github.bazelbuild.rules_jvm_external.resolver.ui.AnsiConsoleListener;
+import com.github.bazelbuild.rules_jvm_external.resolver.ui.NullListener;
+import com.github.bazelbuild.rules_jvm_external.resolver.ui.PlainConsoleListener;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.Authenticator;
@@ -39,6 +42,7 @@
import java.time.Duration;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Set;
import java.util.logging.Logger;
@@ -86,6 +90,21 @@
this.client = builder.build();
}
+ public HttpDownloader(Netrc netrc) {
+ this(netrc, defaultEventListener());
+ }
+
+ public static EventListener defaultEventListener() {
+ boolean termAvailable = !Objects.equals(System.getenv().get("TERM"), "dumb");
+ boolean consoleAvailable = System.console() != null;
+ if (System.getenv("RJE_VERBOSE") != null) {
+ return new PlainConsoleListener();
+ } else if (termAvailable && consoleAvailable) {
+ return new AnsiConsoleListener();
+ }
+ return new NullListener();
+ }
+
public Path get(URI uriToGet) {
if ("file".equals(uriToGet.getScheme())) {
Path path = Paths.get(uriToGet);
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui/BUILD
index c821198..f686ad6 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui/BUILD
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ui/BUILD
@@ -5,6 +5,7 @@
name = "ui",
srcs = glob(["*.java"]),
visibility = [
+ "//private/tools/java/com/github/bazelbuild/rules_jvm_external/maven:__pkg__",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver:__subpackages__",
"//tests/com/github/bazelbuild/rules_jvm_external:__subpackages__",
],
diff --git a/repositories.bzl b/repositories.bzl
index 0e72eed..652a609 100644
--- a/repositories.bzl
+++ b/repositories.bzl
@@ -136,6 +136,7 @@
"org.apache.maven:maven-core:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-model:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-model-builder:%s" % _MAVEN_VERSION,
+ "org.apache.maven:maven-repository-metadata:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-settings:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-settings-builder:%s" % _MAVEN_VERSION,
"org.apache.maven:maven-resolver-provider:%s" % _MAVEN_VERSION,
@@ -154,6 +155,7 @@
"org.slf4j:log4j-over-slf4j:2.0.12",
"org.slf4j:slf4j-simple:2.0.12",
"software.amazon.awssdk:s3:2.26.12",
+ "software.amazon.awssdk:sdk-core:2.26.12",
"org.bouncycastle:bcprov-jdk15on:1.68",
"org.bouncycastle:bcpg-jdk15on:1.68",
"org.gradle:gradle-tooling-api:%s" % _GRADLE_VERSION,
diff --git a/rules_jvm_external_deps_install.json b/rules_jvm_external_deps_install.json
index e3fc024..94e5183 100644
--- a/rules_jvm_external_deps_install.json
+++ b/rules_jvm_external_deps_install.json
@@ -1,7 +1,7 @@
{
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
- "__INPUT_ARTIFACTS_HASH": 1321988192,
- "__RESOLVED_ARTIFACTS_HASH": -1298063869,
+ "__INPUT_ARTIFACTS_HASH": -731442651,
+ "__RESOLVED_ARTIFACTS_HASH": 968256901,
"conflict_resolution": {
"com.google.guava:guava:33.2.1-jre": "com.google.guava:guava:33.4.8-jre",
"org.codehaus.plexus:plexus-utils:3.5.1": "org.codehaus.plexus:plexus-utils:3.6.0"
@@ -205,8 +205,7 @@
},
"com.google.guava:listenablefuture": {
"shasums": {
- "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99",
- "sources": null
+ "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99"
},
"version": "9999.0-empty-to-avoid-conflict-with-guava"
},
@@ -3242,7 +3241,7 @@
]
},
"repositories": {
- "https://repo1.maven.org/maven2/": [
+ "https://repo.gradle.org/gradle/libs-releases/": [
"aopalliance:aopalliance",
"aopalliance:aopalliance:jar:sources",
"com.fasterxml.jackson.core:jackson-core",
@@ -3539,7 +3538,7 @@
"software.amazon.eventstream:eventstream",
"software.amazon.eventstream:eventstream:jar:sources"
],
- "https://repo.gradle.org/gradle/libs-releases/": [
+ "https://repo1.maven.org/maven2/": [
"aopalliance:aopalliance",
"aopalliance:aopalliance:jar:sources",
"com.fasterxml.jackson.core:jackson-core",
diff --git a/tests/integration/java_export/PublishShapeTest.java b/tests/integration/java_export/PublishShapeTest.java
index ff6f56e..0e9062e 100644
--- a/tests/integration/java_export/PublishShapeTest.java
+++ b/tests/integration/java_export/PublishShapeTest.java
@@ -97,6 +97,7 @@
coordinates,
pomXml.getAbsolutePath(),
stubJar.getAbsolutePath(),
+ "false",
String.format(
"javadoc=%s,sources=%s", stubJar.getAbsolutePath(), stubJar.getAbsolutePath()))
.redirectErrorStream(true);
diff --git a/tests/integration/pom_file/OtherLibrary.java b/tests/integration/pom_file/OtherLibrary.java
index 7532f95..b909799 100644
--- a/tests/integration/pom_file/OtherLibrary.java
+++ b/tests/integration/pom_file/OtherLibrary.java
@@ -1,4 +1,3 @@
package tests.integration.pom_file;
-public class OtherLibrary {
-}
+public class OtherLibrary {}
diff --git a/tests/unit/jvm_import/jvm_import_test.bzl b/tests/unit/jvm_import/jvm_import_test.bzl
index 75a6293..fa6278d 100644
--- a/tests/unit/jvm_import/jvm_import_test.bzl
+++ b/tests/unit/jvm_import/jvm_import_test.bzl
@@ -55,13 +55,13 @@
for t in direct:
if PackageMetadataInfo not in t:
continue
-
+
return [
PackageMetadataInfoCollectionInfo(
info = t[PackageMetadataInfo],
),
]
-
+
return []
package_metadata_info_propagator = aspect(
@@ -100,7 +100,7 @@
asserts.true(env, PackageMetadataInfoCollectionInfo in ctx.attr.src)
info = ctx.attr.src[PackageMetadataInfoCollectionInfo]
asserts.true(env, info.info)
-
+
return analysistest.end(env)
does_jvm_import_have_applicable_licenses_test = analysistest.make(