diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequest.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequest.java index 3c51bd105..bb75a7e62 100644 --- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequest.java +++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequest.java @@ -25,6 +25,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -33,7 +34,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class ResolutionRequest { +public class ResolutionRequest implements AutoCloseable { private final List repos = new ArrayList<>(); private final List dependencies = new ArrayList<>(); @@ -41,6 +42,7 @@ public class ResolutionRequest { private final Set globalExclusions = new HashSet<>(); private boolean useUnsafeSharedCache; private Path userHome; + private boolean usingTemporaryUserHome; private boolean isUsingM2Local; public ResolutionRequest addRepository(String uri) { @@ -132,6 +134,7 @@ public ResolutionRequest replaceDependencies(Collection amended) { getGlobalExclusions().forEach(toReturn::exclude); toReturn.useUnsafeSharedCache = isUseUnsafeSharedCache(); toReturn.userHome = userHome; + toReturn.usingTemporaryUserHome = usingTemporaryUserHome; toReturn.isUsingM2Local = isUsingM2Local(); return toReturn; @@ -168,9 +171,11 @@ public Path getUserHome() { if (isUseUnsafeSharedCache()) { userHome = Paths.get(USER_HOME.value()); + usingTemporaryUserHome = false; } else { try { userHome = Files.createTempDirectory("resolver-home"); + usingTemporaryUserHome = true; } catch (IOException e) { throw new RuntimeException(e); } @@ -207,6 +212,21 @@ public Path getLocalCache(String resolver) { return localRepo; } + @Override + public void close() { + if (!usingTemporaryUserHome || userHome == null || !Files.exists(userHome)) { + return; + } + + try (Stream files = Files.walk(userHome)) { + files.sorted(Comparator.reverseOrder()).forEach(this::deleteIfExists); + userHome = null; + usingTemporaryUserHome = false; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private void createDirectories(Path path) { try { Files.createDirectories(path); @@ -214,4 +234,12 @@ private void createDirectories(Path path) { throw new UncheckedIOException(e); } } + + private void deleteIfExists(Path path) { + try { + Files.deleteIfExists(path); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } } diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/AbstractMain.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/AbstractMain.java index d33cacd7b..9f626ce2f 100644 --- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/AbstractMain.java +++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver/cmd/AbstractMain.java @@ -64,18 +64,16 @@ public void doMain(String[] args) { Set infos; try (EventListener listener = HttpDownloader.defaultEventListener()) { ResolverConfig config = new ResolverConfig(listener, args); + try (ResolutionRequest request = config.getResolutionRequest()) { + Resolver resolver = getResolver(config.getNetrc(), config.getMaxThreads(), listener); - ResolutionRequest request = config.getResolutionRequest(); + ResolutionResult resolutionResult = resolver.resolve(request); - Resolver resolver = getResolver(config.getNetrc(), config.getMaxThreads(), listener); - - ResolutionResult resolutionResult = resolver.resolve(request); - - infos = fulfillDependencyInfos(resolver, listener, config, resolutionResult); - - writeLockFile(listener, config, request, infos, resolutionResult.getConflicts()); - writeDependencyIndex(config, infos); + infos = fulfillDependencyInfos(resolver, listener, config, resolutionResult); + writeLockFile(listener, config, request, infos, resolutionResult.getConflicts()); + writeDependencyIndex(config, infos); + } System.exit(0); } catch (Exception e) { e.printStackTrace(); diff --git a/private/tools/prebuilt/lock_file_converter_deploy.jar b/private/tools/prebuilt/lock_file_converter_deploy.jar index 17c101ac1..1c05b00ad 100755 Binary files a/private/tools/prebuilt/lock_file_converter_deploy.jar and b/private/tools/prebuilt/lock_file_converter_deploy.jar differ diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/BUILD b/tests/com/github/bazelbuild/rules_jvm_external/resolver/BUILD index f399e5311..564561aee 100644 --- a/tests/com/github/bazelbuild/rules_jvm_external/resolver/BUILD +++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/BUILD @@ -1,4 +1,5 @@ load("@rules_java//java:java_library.bzl", "java_library") +load("@rules_java//java:java_test.bzl", "java_test") load("//:defs.bzl", "artifact") java_library( @@ -38,3 +39,18 @@ java_library( ), ], ) + +java_test( + name = "ResolutionRequestTest", + size = "small", + srcs = ["ResolutionRequestTest.java"], + test_class = "com.github.bazelbuild.rules_jvm_external.resolver.ResolutionRequestTest", + deps = [ + "//private/tools/java/com/github/bazelbuild/rules_jvm_external/resolver", + artifact( + "junit:junit", + repository_name = "regression_testing_coursier", + ), + artifact("org.hamcrest:hamcrest"), + ], +) diff --git a/tests/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequestTest.java b/tests/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequestTest.java new file mode 100644 index 000000000..b298b7b10 --- /dev/null +++ b/tests/com/github/bazelbuild/rules_jvm_external/resolver/ResolutionRequestTest.java @@ -0,0 +1,56 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.github.bazelbuild.rules_jvm_external.resolver; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; + +public class ResolutionRequestTest { + + @Test + public void shouldDeleteTemporaryUserHomeOnCleanup() throws IOException { + ResolutionRequest request = new ResolutionRequest(); + + Path userHome = request.getUserHome(); + Path marker = request.getLocalCache("maven").resolve("cleanup-marker"); + Files.writeString(marker, "cleanup-me"); + + assertTrue(Files.exists(userHome)); + assertTrue(Files.exists(marker)); + + request.close(); + + assertFalse(Files.exists(userHome)); + } + + @Test + public void shouldNotDeleteSharedUserHomeWhenUsingUnsafeCache() { + ResolutionRequest request = new ResolutionRequest(); + request.useUnsafeSharedCache(true); + + Path userHome = request.getUserHome(); + request.close(); + + assertEquals(Paths.get(System.getProperty("user.home")), userHome); + assertTrue(Files.exists(userHome)); + } +}