diff --git a/src/main/java/com/crowdin/cli/commands/actions/DownloadBundleAction.java b/src/main/java/com/crowdin/cli/commands/actions/DownloadBundleAction.java index dcd218c5b..9b55ffcf7 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DownloadBundleAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DownloadBundleAction.java @@ -16,6 +16,7 @@ import java.io.InputStream; import java.net.URL; import java.util.List; +import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; import static com.crowdin.cli.utils.console.ExecutionStatus.ERROR; @@ -28,16 +29,18 @@ public class DownloadBundleAction implements NewAction extractedPaths; String baseTemp = StringUtils.removeEnd(pb.getBasePath(), Utils.PATH_SEPARATOR) + Utils.PATH_SEPARATOR; - java.io.File baseTempDir = new java.io.File(baseTemp + Utils.PATH_SEPARATOR); - List downloadedFiles = extractArchive(to, baseTempDir); + File baseTempDir = new File(baseTemp + Utils.PATH_SEPARATOR); + if (dryrun) { + extractedPaths = files.zipArchiveContent(to); + } else { + List downloadedFiles = extractArchive(to, baseTempDir); + extractedPaths = downloadedFiles.stream().map(File::getAbsolutePath).collect(Collectors.toList()); + } - for (File file: downloadedFiles) { - String filePath = Utils.noSepAtStart(StringUtils.removeStart(file.getAbsolutePath(), baseTempDir.getAbsolutePath())); + for (String file: extractedPaths) { + String filePath = Utils.noSepAtStart(StringUtils.removeStart(file, baseTempDir.getAbsolutePath())); out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.extracted_file"), filePath))); } diff --git a/src/main/java/com/crowdin/cli/commands/functionality/FilesInterface.java b/src/main/java/com/crowdin/cli/commands/functionality/FilesInterface.java index 16e1221e4..d4ddd7a3d 100644 --- a/src/main/java/com/crowdin/cli/commands/functionality/FilesInterface.java +++ b/src/main/java/com/crowdin/cli/commands/functionality/FilesInterface.java @@ -13,6 +13,8 @@ public interface FilesInterface { List extractZipArchive(File zipArchive, File dir); + List zipArchiveContent(File zipArchive); + void deleteFile(File file) throws IOException; void deleteDirectory(File dir) throws IOException; diff --git a/src/main/java/com/crowdin/cli/commands/functionality/FsFiles.java b/src/main/java/com/crowdin/cli/commands/functionality/FsFiles.java index 3af0f5c5a..b8554e42b 100644 --- a/src/main/java/com/crowdin/cli/commands/functionality/FsFiles.java +++ b/src/main/java/com/crowdin/cli/commands/functionality/FsFiles.java @@ -73,6 +73,26 @@ public List extractZipArchive(File zipArchive, File dir) { return extractedFiles; } + @Override + public List zipArchiveContent(File zipArchive) { + List archiveFiles = new ArrayList<>(); + ZipFile zipFile; + try { + zipFile = new ZipFile(zipArchive); + } catch (IllegalArgumentException e) { + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.archive_not_exist"), zipArchive.getAbsolutePath())); + } + try { + List fileHeaders = zipFile.getFileHeaders(); + for (FileHeader fileHeader : fileHeaders) { + archiveFiles.add(fileHeader.getFileName()); + } + } catch (net.lingala.zip4j.exception.ZipException e) { + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.extract_archive"), zipArchive.getAbsolutePath())); + } + return archiveFiles; + } + @Override public void deleteFile(File file) throws IOException { java.nio.file.Files.delete(file.toPath()); diff --git a/src/main/java/com/crowdin/cli/commands/picocli/DownloadBundleSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/DownloadBundleSubcommand.java index aee47c8d1..b64c2d11d 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/DownloadBundleSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/DownloadBundleSubcommand.java @@ -23,8 +23,11 @@ public class DownloadBundleSubcommand extends ActCommandBundle { @CommandLine.Option(names = {"--keep-archive"}, descriptionKey = "params.keepArchive") protected boolean keepArchive; + @CommandLine.Option(names = {"--dryrun"}) + protected boolean dryrun; + @Override protected NewAction getAction(Actions actions) { - return new DownloadBundleAction(id, new FsFiles(), plainView, keepArchive, noProgress); + return new DownloadBundleAction(id, new FsFiles(), plainView, keepArchive, noProgress, dryrun); } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/DownloadBundleActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/DownloadBundleActionTest.java index 4ca630c24..71d0cfee9 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/DownloadBundleActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/DownloadBundleActionTest.java @@ -44,7 +44,7 @@ public void testDownloadBundle() { .build(); Bundle bundle = new Bundle(); - bundle.setId(1l); + bundle.setId(1L); BundleExport export = new BundleExport(); export.setStatus("finished"); @@ -63,7 +63,7 @@ public void testDownloadBundle() { FilesInterface files = mock(FilesInterface.class); NewAction action = - new DownloadBundleAction(bundle.getId(), files, false, false, false); + new DownloadBundleAction(bundle.getId(), files, false, false, false, false); action.act(Outputter.getDefault(), pb, client); verify(client).getBundle(bundle.getId()); @@ -71,4 +71,43 @@ public void testDownloadBundle() { verify(client).downloadBundle(bundle.getId(), null); verifyNoMoreInteractions(client); } + + @Test + public void testDryRun() { + PropertiesWithFiles pb = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean( + "/values/strings.xml", "/values-%two_letters_code%/%original_file_name%", + null, "/common/%original_file_name%") + .setBasePath(project.getBasePath()) + .build(); + + Bundle bundle = new Bundle(); + bundle.setId(1L); + + BundleExport export = new BundleExport(); + export.setStatus("finished"); + ClientBundle client = mock(ClientBundle.class); + + URL urlMock = MockitoUtils.getMockUrl(getClass()); + + when(client.downloadBundle(bundle.getId(), null)) + .thenReturn(urlMock); + when(client.getBundle(bundle.getId())) + .thenReturn(Optional.of(bundle)); + + when(client.startExportingBundle(bundle.getId())) + .thenReturn(export); + + FilesInterface files = mock(FilesInterface.class); + + NewAction action = + new DownloadBundleAction(bundle.getId(), files, false, false, false, true); + action.act(Outputter.getDefault(), pb, client); + + verify(client).getBundle(bundle.getId()); + verify(client).startExportingBundle(bundle.getId()); + verify(client).downloadBundle(bundle.getId(), null); + + verifyNoMoreInteractions(client); + } }