Skip to content

Commit

Permalink
#461: Add Progressbar for Unpacking Archives (#567)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfeilex authored Sep 13, 2024
1 parent d3d3550 commit fd5a92b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
52 changes: 46 additions & 6 deletions cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

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;
Expand Down Expand Up @@ -619,7 +620,7 @@ private Path getProperInstallationSubDirOf(Path path, Path archiveFile) {
@Override
public void extractZip(Path file, Path targetDir) {

extractArchive(file, targetDir, in -> new ZipArchiveInputStream(in));
extractZipArchive(file, targetDir);
}

@Override
Expand All @@ -632,7 +633,8 @@ public void extractTar(Path file, Path targetDir, TarCompression compression) {
public void extractJar(Path file, Path targetDir) {

this.context.trace("Unpacking JAR {} to {}", file, targetDir);
try (JarInputStream jis = new JarInputStream(Files.newInputStream(file))) {
try (JarInputStream jis = new JarInputStream(Files.newInputStream(file)); IdeProgressBar pb = getProgressbarForUnpacking(
getFileSize(file))) {
JarEntry entry;
while ((entry = jis.getNextJarEntry()) != null) {
Path entryPath = targetDir.resolve(entry.getName()).toAbsolutePath();
Expand All @@ -647,7 +649,7 @@ public void extractJar(Path file, Path targetDir) {
Files.createDirectories(entryPath.getParent());
Files.copy(jis, entryPath);
}

pb.stepBy(entry.getCompressedSize());
jis.closeEntry();
}
} catch (IOException e) {
Expand Down Expand Up @@ -678,7 +680,8 @@ public static String generatePermissionString(int permissions) {
private void extractArchive(Path file, Path targetDir, Function<InputStream, ArchiveInputStream> unpacker) {

this.context.trace("Unpacking archive {} to {}", file, targetDir);
try (InputStream is = Files.newInputStream(file); ArchiveInputStream ais = unpacker.apply(is)) {
try (InputStream is = Files.newInputStream(file); ArchiveInputStream ais = unpacker.apply(is); IdeProgressBar pb = getProgressbarForUnpacking(
getFileSize(file))) {
ArchiveEntry entry = ais.getNextEntry();
boolean isTar = ais instanceof TarArchiveInputStream;
while (entry != null) {
Expand All @@ -687,7 +690,6 @@ private void extractArchive(Path file, Path targetDir, Function<InputStream, Arc
int tarMode = ((TarArchiveEntry) entry).getMode();
permissionStr = generatePermissionString(tarMode);
}

Path entryName = Path.of(entry.getName());
Path entryPath = targetDir.resolve(entryName).toAbsolutePath();
if (!entryPath.startsWith(targetDir)) {
Expand All @@ -704,13 +706,42 @@ private void extractArchive(Path file, Path targetDir, Function<InputStream, Arc
Set<PosixFilePermission> permissions = PosixFilePermissions.fromString(permissionStr);
Files.setPosixFilePermissions(entryPath, permissions);
}
pb.stepBy(entry.getSize());
entry = ais.getNextEntry();
}
} catch (IOException e) {
throw new IllegalStateException("Failed to extract " + file + " to " + targetDir, e);
}
}

private void extractZipArchive(Path file, Path targetDir) {

this.context.trace("Unpacking archive {} to {}", file, targetDir);
try (FileInputStream fis = new FileInputStream(file.toFile()); ZipInputStream zis = new ZipInputStream(fis); IdeProgressBar pb = getProgressbarForUnpacking(
getFileSize(file))) {
ZipEntry entry = zis.getNextEntry();
while (entry != null) {
Path entryName = Path.of(entry.getName());
Path entryPath = targetDir.resolve(entryName).toAbsolutePath();
if (!entryPath.startsWith(targetDir)) {
throw new IOException("Preventing path traversal attack from " + entryName + " to " + entryPath);
}
if (entry.isDirectory()) {
mkdirs(entryPath);
} else {
// ensure the file can also be created if directory entry was missing or out of order...
mkdirs(entryPath.getParent());
Files.copy(zis, entryPath);
}
pb.stepBy(entry.getCompressedSize());
zis.closeEntry();
entry = zis.getNextEntry();
}
} catch (IOException e) {
throw new IllegalStateException("Failed to extract " + file + " to " + targetDir, e);
}
}

@Override
public void extractDmg(Path file, Path targetDir) {

Expand Down Expand Up @@ -828,6 +859,15 @@ private Path findFirstRecursive(Path dir, Predicate<Path> filter, boolean recurs
return null;
}

/**
* @param sizeFile the size of archive
* @return prepared progressbar for unpacking
*/
private IdeProgressBar getProgressbarForUnpacking(long sizeFile) {

return this.context.prepareProgressBar("Unpacking", sizeFile);
}

@Override
public List<Path> listChildren(Path dir, Predicate<Path> filter) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ public IdeProgressBar prepareProgressBar(String taskName, long size) {

IdeProgressBarTestImpl progressBar = new IdeProgressBarTestImpl(taskName, size);
IdeProgressBarTestImpl duplicate = this.progressBarMap.put(taskName, progressBar);
// If we have multiple downloads, we may have an existing "Downloading" key
if (!taskName.equals("Downloading")) {
// If we have multiple downloads or unpacking, we may have an existing "Downloading" or "Unpacking" key
if ((!taskName.equals("Downloading")) && (!taskName.equals("Unpacking"))) {
assert duplicate == null;
}
return progressBar;
Expand Down

0 comments on commit fd5a92b

Please sign in to comment.