This is an automated email from the ASF dual-hosted git repository. cstamas pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push: new ebe4ae437 Go back to atomic (#1594) ebe4ae437 is described below commit ebe4ae437fad3d4c531f09f4c0636771a99581d9 Author: Tamas Cservenak <ta...@cservenak.net> AuthorDate: Fri Sep 19 11:41:34 2025 +0200 Go back to atomic (#1594) This change was done due Windows, but later the execution path was split for Windows to use oldie pre-NIO2 code to copy as for some reason that works on Windows. On other platforms, insist on ATOMIC, still make use able to override it, in case atomic is not a viable option. --- .../java/org/eclipse/aether/util/FileUtils.java | 18 +++++++-- .../org/eclipse/aether/util/FileUtilsTest.java | 44 ++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/FileUtils.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/FileUtils.java index 2c0d553bf..52e2348f5 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/FileUtils.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/FileUtils.java @@ -37,14 +37,24 @@ import static java.util.Objects.requireNonNull; * @since 1.9.0 */ public final class FileUtils { - // Logic borrowed from Commons-Lang3: we really need only this, to decide do we "atomic move" or not + /** + * Logic borrowed from Commons-Lang3: we really need only this, to decide do we NIO2 file ops or not. + * For some reason non-NIO2 works better on Windows. + */ private static final boolean IS_WINDOWS = System.getProperty("os.name", "unknown").startsWith("Windows"); + /** + * Escape hatch if atomic move is not desired on system we run on. + * + * @since 2.0.12 + */ + private static final boolean ATOMIC_MOVE = + Boolean.parseBoolean(System.getProperty(FileUtils.class.getName() + "ATOMIC_MOVE", "true")); + private FileUtils() { // hide constructor } - /** * A temporary file, that is removed when closed. */ @@ -115,6 +125,8 @@ public final class FileUtils { + Long.toUnsignedString(ThreadLocalRandom.current().nextLong()) + ".tmp"); return new CollocatedTempFile() { private final AtomicBoolean wantsMove = new AtomicBoolean(false); + private final StandardCopyOption copyOption = + FileUtils.ATOMIC_MOVE ? StandardCopyOption.ATOMIC_MOVE : StandardCopyOption.REPLACE_EXISTING; @Override public Path getPath() { @@ -132,7 +144,7 @@ public final class FileUtils { if (IS_WINDOWS) { copy(tempFile, file); } else { - Files.move(tempFile, file, StandardCopyOption.REPLACE_EXISTING); + Files.move(tempFile, file, copyOption); } } Files.deleteIfExists(tempFile); diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/FileUtilsTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/FileUtilsTest.java new file mode 100644 index 000000000..e4ad14c31 --- /dev/null +++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/FileUtilsTest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.eclipse.aether.util; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class FileUtilsTest { + @Test + void smoke(@TempDir Path tmp) throws IOException { + Path target = tmp.resolve("target.txt"); + Files.write(target, "Hello world".getBytes(StandardCharsets.UTF_8)); + assertEquals("Hello world", new String(Files.readAllBytes(target), StandardCharsets.UTF_8)); + + try (FileUtils.CollocatedTempFile tempFile = FileUtils.newTempFile(target)) { + Files.write(tempFile.getPath(), "Hello other world".getBytes(StandardCharsets.UTF_8)); + tempFile.move(); + } + assertEquals("Hello other world", new String(Files.readAllBytes(target), StandardCharsets.UTF_8)); + } +}