From 2ff8bc3f3e4b97a559251d7f3d3462311439e3ac Mon Sep 17 00:00:00 2001 From: Marco Vomiero <102261609+mvomiero@users.noreply.github.com> Date: Fri, 19 Apr 2024 17:32:20 +0200 Subject: [PATCH] #264: prevent Windows file lock errors (#288) --- .../devonfw/tools/ide/io/FileAccessImpl.java | 116 +++++++----------- 1 file changed, 47 insertions(+), 69 deletions(-) diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java index 85f30ad65..15dbbc3e2 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java @@ -1,5 +1,19 @@ package com.devonfw.tools.ide.io; +import com.devonfw.tools.ide.cli.CliException; +import com.devonfw.tools.ide.context.IdeContext; +import com.devonfw.tools.ide.os.SystemInfoImpl; +import com.devonfw.tools.ide.process.ProcessContext; +import com.devonfw.tools.ide.url.model.file.UrlChecksum; +import com.devonfw.tools.ide.util.DateTimeUtil; +import com.devonfw.tools.ide.util.FilenameUtil; +import com.devonfw.tools.ide.util.HexUtil; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; + import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -32,21 +46,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import org.apache.commons.compress.archivers.ArchiveEntry; -import org.apache.commons.compress.archivers.ArchiveInputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; - -import com.devonfw.tools.ide.cli.CliException; -import com.devonfw.tools.ide.context.IdeContext; -import com.devonfw.tools.ide.os.SystemInfoImpl; -import com.devonfw.tools.ide.process.ProcessContext; -import com.devonfw.tools.ide.url.model.file.UrlChecksum; -import com.devonfw.tools.ide.util.DateTimeUtil; -import com.devonfw.tools.ide.util.FilenameUtil; -import com.devonfw.tools.ide.util.HexUtil; - /** * Implementation of {@link FileAccess}. */ @@ -106,14 +105,11 @@ public void download(String url, Path target) { * @param target Path of the target directory. * @param response the {@link HttpResponse} to use. */ - private void downloadFileWithProgressBar(String url, Path target, HttpResponse response) - throws IOException { + private void downloadFileWithProgressBar(String url, Path target, HttpResponse response) throws IOException { long contentLength = response.headers().firstValueAsLong("content-length").orElse(0); if (contentLength == 0) { - this.context.warning( - "Content-Length was not provided by download source : {} using fallback for the progress bar which will be inaccurate.", - url); + this.context.warning("Content-Length was not provided by download source : {} using fallback for the progress bar which will be inaccurate.", url); contentLength = 10000000; } @@ -147,8 +143,7 @@ private void downloadFileWithProgressBar(String url, Path target, HttpResponse postExtract return; } Path tmpDir = createTempDir("extract-" + archiveFile.getFileName()); - this.context.trace("Trying to extract the downloaded file {} to {} and move it to {}.", archiveFile, tmpDir, - targetDir); + this.context.trace("Trying to extract the downloaded file {} to {} and move it to {}.", archiveFile, tmpDir, targetDir); String filename = archiveFile.getFileName().toString(); TarCompression tarCompression = TarCompression.of(filename); if (tarCompression != null) { @@ -567,21 +548,19 @@ private void postExtractHook(Consumer postExtractHook, Path properInstallD /** * @param path the {@link Path} to start the recursive search from. - * @return the deepest subdir {@code s} of the passed path such that all directories between {@code s} and the passed - * path (including {@code s}) are the sole item in their respective directory and {@code s} is not named - * "bin". + * @return the deepest subdir {@code s} of the passed path such that all directories between {@code s} and the passed path (including {@code s}) are the sole + * item in their respective directory and {@code s} is not named "bin". */ private Path getProperInstallationSubDirOf(Path path, Path archiveFile) { try (Stream stream = Files.list(path)) { Path[] subFiles = stream.toArray(Path[]::new); if (subFiles.length == 0) { - throw new CliException("The downloaded package " + archiveFile - + " seems to be empty as you can check in the extracted folder " + path); + throw new CliException("The downloaded package " + archiveFile + " seems to be empty as you can check in the extracted folder " + path); } else if (subFiles.length == 1) { String filename = subFiles[0].getFileName().toString(); - if (!filename.equals(IdeContext.FOLDER_BIN) && !filename.equals(IdeContext.FOLDER_CONTENTS) - && !filename.endsWith(".app") && Files.isDirectory(subFiles[0])) { + if (!filename.equals(IdeContext.FOLDER_BIN) && !filename.equals(IdeContext.FOLDER_CONTENTS) && !filename.endsWith(".app") && Files.isDirectory( + subFiles[0])) { return getProperInstallationSubDirOf(subFiles[0], archiveFile); } } @@ -604,8 +583,7 @@ public void extractTar(Path file, Path targetDir, TarCompression compression) { } /** - * @param permissions The integer as returned by {@link TarArchiveEntry#getMode()} that represents the file - * permissions of a file on a Unix file system. + * @param permissions The integer as returned by {@link TarArchiveEntry#getMode()} that represents the file permissions of a file on a Unix file system. * @return A String representing the file permissions. E.g. "rwxrwxr-x" or "rw-rw-r--" */ public static String generatePermissionString(int permissions) { @@ -707,7 +685,7 @@ public void delete(Path path) { } this.context.debug("Deleting {} ...", path); try { - if (Files.isSymbolicLink(path)) { + if (Files.isSymbolicLink(path) || isJunction(path)) { Files.delete(path); } else { deleteRecursive(path); @@ -810,7 +788,7 @@ public Path findExistingFile(String fileName, List searchDirs) { return filePath; } } catch (Exception e) { - throw new IllegalStateException("Unexpected error while checking existence of file "+filePath+" .", e); + throw new IllegalStateException("Unexpected error while checking existence of file " + filePath + " .", e); } } return null;