Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This file documents all notable changes to https://github.com/devonfw/IDEasy[IDE

Release with new features and bugfixes:

* https://github.com/devonfw/IDEasy/issues/871[#871]: Add a progress bar when copying applications from DMG files
* https://github.com/devonfw/IDEasy/issues/2178[#2178]: Make ReleaseCommandlet independent of specific build commandlet and fix `ide build` using npm instead of yarn
* https://github.com/devonfw/IDEasy/issues/2142[#2142]: Move IDE-specific metadata (.idea, .vscode) out of workspace
* https://github.com/devonfw/IDEasy/issues/989[#989]: Allow expressions in template variable definitions
Expand Down
26 changes: 25 additions & 1 deletion cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,18 @@ private void copyFileWithProgressBar(Path source, Path target) {
}
}

private void copyTreeWithProgressBar(Path source, Path target, FileCopyMode mode) {

long size = getPathSize(source);
try (IdeProgressBar progressBar = this.context.newProgressbarForCopying(size)) {
copy(source, target, mode, (copiedSource, copiedTarget, directory) -> {
if (!directory) {
progressBar.stepBy(getFileSize(copiedSource));
}
});
}
}

@Override
public String download(String url) {

Expand Down Expand Up @@ -1009,7 +1021,7 @@ public void extractDmg(Path file, Path targetDir) {
throw new IllegalStateException("Failed to unpack DMG as no MacOS *.app was found in file " + file);
}

copy(appPath, targetDir, FileCopyMode.COPY_TREE_OVERRIDE_TREE);
copyTreeWithProgressBar(appPath, targetDir, FileCopyMode.COPY_TREE_OVERRIDE_TREE);
pc.addArgs("detach", "-force", mountPath);
pc.run();
}
Expand Down Expand Up @@ -1425,6 +1437,18 @@ private long getFileSize(Path file) {
}
}

private long getPathSize(Path path) {

if (!Files.isDirectory(path)) {
return getFileSize(path);
}
long size = 0;
for (Path child : listChildren(path, file -> true)) {
size += getPathSize(child);
}
return size;
}


@Override
public Path findExistingFile(String fileName, List<Path> searchDirs) {
Expand Down
33 changes: 33 additions & 0 deletions cli/src/test/java/com/devonfw/tools/ide/io/FileAccessImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.CleanupMode;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mockito;

import com.devonfw.tools.ide.context.AbstractIdeContextTest;
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.context.IdeTestContext;
import com.devonfw.tools.ide.os.SystemInfoMock;
import com.devonfw.tools.ide.process.ProcessContext;

/**
* Test of {@link FileAccessImpl}.
Expand Down Expand Up @@ -799,6 +802,36 @@ void testUnzipFilePermissionsSkippedOnSimulatedWindows(@TempDir Path tempDir) {
}
}

/**
* Test of {@link FileAccessImpl#extractDmg(Path, Path)} with a progress bar for copying the mounted app.
*/
@Test
void testExtractDmgWithProgressBar(@TempDir Path tempDir) throws IOException {

// arrange
IdeTestContext context = newContext(tempDir);
context.setIdeHome(tempDir);
context.setSystemInfo(SystemInfoMock.MAC_X64);
ProcessContext processContext = Mockito.mock(ProcessContext.class);
context.setProcessContext(processContext);
Path appPath = context.getIdeHome().resolve(IdeContext.FOLDER_UPDATES).resolve(IdeContext.FOLDER_VOLUME).resolve("MyApp.app");
Path sourceFile = appPath.resolve("Contents/Resources/resource.txt");
Files.createDirectories(sourceFile.getParent());
Files.writeString(sourceFile, "x".repeat(1024));
long appSize = Files.size(sourceFile);
Path target = tempDir.resolve("target");

// act
context.getFileAccess().extractDmg(tempDir.resolve("MyApp.dmg"), target);

// assert
assertThat(target.resolve(appPath.getFileName()).resolve(appPath.relativize(sourceFile))).hasSameTextualContentAs(sourceFile);
IdeProgressBarTestImpl progressBar = context.getProgressBarMap().get(IdeProgressBar.TITLE_COPYING);
assertThat(progressBar).isNotNull();
assertThat(progressBar.getMaxSize()).isEqualTo(appSize);
assertThat(progressBar.getEventList()).extracting(IdeProgressBarTestImpl.ProgressEvent::getStepSize).containsExactly(appSize);
}

/**
* Test of {@link FileAccessImpl#generatePermissionString(int)}.
*/
Expand Down