From f00730e15936662591657480cc097e314344b0d1 Mon Sep 17 00:00:00 2001 From: Daniil Barabash Date: Fri, 6 Aug 2021 13:37:08 +0300 Subject: [PATCH 1/5] Small fixes: - Fix exception handling at uploading file to storage in 'upload source' action - Fix showing New version banner with '--plain' param - Fix message in authorizing via browser --- .../com/crowdin/cli/commands/actions/GenerateAction.java | 2 +- .../crowdin/cli/commands/actions/UploadSourcesAction.java | 2 +- .../com/crowdin/cli/commands/picocli/PicocliRunner.java | 8 ++++---- src/main/java/com/crowdin/cli/utils/http/OAuthUtil.java | 5 +++-- src/main/resources/messages/messages.properties | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/crowdin/cli/commands/actions/GenerateAction.java b/src/main/java/com/crowdin/cli/commands/actions/GenerateAction.java index 1a18853a5..f4c194fdb 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/GenerateAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/GenerateAction.java @@ -94,7 +94,7 @@ private void updateWithUserInputs(Outputter out, Asking asking, List fil String token; try { ConsoleSpinner.start(out, "Waiting for authorization to complete (Press +C to exit)", false); - token = OAuthUtil.getToken(OAUTH_CLIENT_ID); + token = OAuthUtil.getToken(out, OAUTH_CLIENT_ID); ConsoleSpinner.stop(OK, "Authorization finished successfully"); } catch (Exception e) { ConsoleSpinner.stop(ERROR, e.getMessage()); diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java index 4c4156c13..6577a4f1b 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java @@ -188,7 +188,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { return (Runnable) () -> { try (InputStream fileStream = new FileInputStream(sourceFile)) { request.setStorageId(client.uploadStorage(source.substring(source.lastIndexOf(Utils.PATH_SEPARATOR) + 1), fileStream)); - } catch (IOException e) { + } catch (Exception e) { errorsPresented.set(true); throw new RuntimeException( String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath())); diff --git a/src/main/java/com/crowdin/cli/commands/picocli/PicocliRunner.java b/src/main/java/com/crowdin/cli/commands/picocli/PicocliRunner.java index 88280b545..233162cbb 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/PicocliRunner.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/PicocliRunner.java @@ -39,10 +39,10 @@ public int execute(Actions actions, PropertiesBuilders propertiesBuilders, Strin public boolean hasMatchedArg(String name) { CommandLine.ParseResult parseResult = commandLine.getParseResult(); - return parseResult != null - && ((parseResult.hasSubcommand()) - ? parseResult.subcommand().hasMatchedOption(name) - : parseResult.hasMatchedOption(name)); + while (parseResult.hasSubcommand()) { + parseResult = parseResult.subcommand(); + } + return parseResult.hasMatchedOption(name); } private void init() { diff --git a/src/main/java/com/crowdin/cli/utils/http/OAuthUtil.java b/src/main/java/com/crowdin/cli/utils/http/OAuthUtil.java index 09a2d5b7c..f4372edd5 100644 --- a/src/main/java/com/crowdin/cli/utils/http/OAuthUtil.java +++ b/src/main/java/com/crowdin/cli/utils/http/OAuthUtil.java @@ -1,5 +1,6 @@ package com.crowdin.cli.utils.http; +import com.crowdin.cli.commands.Outputter; import lombok.Data; import org.apache.commons.codec.binary.Base64; import org.json.JSONException; @@ -17,7 +18,7 @@ public class OAuthUtil { - public static String getToken(String clientId) { + public static String getToken(Outputter out, String clientId) { try { int port = 46221; String redirectUri = String.format("http://localhost:%d/callback", port); @@ -57,7 +58,7 @@ public static String getToken(String clientId) { if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { Desktop.getDesktop().browse(new URI(builtUrl)); } else { - System.out.println(WARNING.withIcon(String.format(RESOURCE_BUNDLE.getString("message.warning.browser_not_found"), builtUrl))); + out.println(WARNING.withIcon(String.format(RESOURCE_BUNDLE.getString("message.warning.browser_not_found"), builtUrl))); } Result result = queue.take(); diff --git a/src/main/resources/messages/messages.properties b/src/main/resources/messages/messages.properties index 5971a10b3..d19480416 100755 --- a/src/main/resources/messages/messages.properties +++ b/src/main/resources/messages/messages.properties @@ -469,7 +469,7 @@ message.no_manager_access_in_upload_sources=You need to have @|yellow manager ac message.no_manager_access_in_upload_sources_dryrun=You need to have @|yellow manager access|@ in the project to apply 'delete-obsolete' options message.warning.not_yml=File @|bold '%s'|@ is not a YAML or YML file -message.warning.browser_not_found=Error opening web browser. Please open the following link manually:\n@|bold %s|@ +message.warning.browser_not_found=\nError opening web browser. Please open the following link manually:\n@|bold %s|@ message.warning.file_not_uploaded_cause_of_language=Translation file @|yellow,bold '%s'|@ @|yellow hasn't been uploaded|@ since @|bold %s|@ is not enabled as a target language for the source file in your Crowdin project message.warning.auto_approve_option_with_mt='--auto-approve-option' is used only for the TM Pre-Translation method From b31ae382efb97ccb840701b797989d2bea50f2e0 Mon Sep 17 00:00:00 2001 From: Daniil Barabash Date: Wed, 18 Aug 2021 13:55:17 +0300 Subject: [PATCH 2/5] Add 'custom_segmentation' field --- build.gradle | 2 +- .../crowdin/cli/client/CrowdinClientCore.java | 4 +-- .../cli/client/CrowdinProjectClient.java | 2 +- .../commands/actions/UploadSourcesAction.java | 25 +++++++++++++++---- .../com/crowdin/cli/properties/FileBean.java | 17 ++++++++----- .../cli/properties/PropertiesBuilder.java | 2 ++ .../crowdin/cli/client/ProjectBuilder.java | 4 +-- 7 files changed, 39 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 5bda6d457..1c29d2a31 100755 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'info.picocli:picocli:4.6.1' - implementation 'com.github.crowdin:crowdin-api-client-java:1.3.10' + implementation 'com.github.crowdin:crowdin-api-client-java:1.3.12' testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2' testImplementation 'org.hamcrest:hamcrest:2.2' diff --git a/src/main/java/com/crowdin/cli/client/CrowdinClientCore.java b/src/main/java/com/crowdin/cli/client/CrowdinClientCore.java index 8b130f0bc..e552edf66 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinClientCore.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinClientCore.java @@ -119,8 +119,8 @@ protected static T executeRequest(Map"; - String message = (e.getError().message != null) ? e.getError().message : ""; + String code = (e.getError() != null && e.getError().code != null) ? e.getError().code : ""; + String message = (e.getError() != null && e.getError().message != null) ? e.getError().message : ""; searchErrorHandler(errorHandlers, code, message); throw new RuntimeException(String.format("Error from server: ", code, message)); } catch (Exception e) { diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index dab9610a4..a3307b102 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -83,7 +83,7 @@ private void populateProjectWithInfo(CrowdinProjectInfo project) { if (projectModel instanceof ProjectSettings) { project.setAccessLevel(CrowdinProjectInfo.Access.MANAGER); ProjectSettings projectSettings = (ProjectSettings) projectModel; - if (projectSettings.isInContext()) { + if (projectSettings.getInContext() != null && projectSettings.getInContext()) { project.setInContextLanguage(projectSettings.getInContextPseudoLanguage()); } project.setLanguageMapping(LanguageMapping.fromServerLanguageMapping(projectSettings.getLanguageMapping())); diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java index 6577a4f1b..1be7df051 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java @@ -151,6 +151,19 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { return; } } + Long customSegmentationFileId = null; + if (file.getCustomSegmentation() != null) { + File customSegmentation = new File(Utils.normalizePath(Utils.joinPaths(pb.getBasePath(), file.getCustomSegmentation()))); + try (InputStream customSegmentationFileStream = new FileInputStream(customSegmentation)) { + customSegmentationFileId = client.uploadStorage(customSegmentation.getName(), customSegmentationFileStream); + } catch (Exception e) { + errorsPresented.set(true); + throw new RuntimeException( + String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), customSegmentation.getAbsolutePath(), e)); + } + } + Long srxStorageId = customSegmentationFileId; + List taskss = sources.stream() .map(source -> { final File sourceFile = new File(source); @@ -175,7 +188,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { if (autoUpdate && projectFile != null) { final UpdateFileRequest request = new UpdateFileRequest(); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); - request.setImportOptions(buildImportOptions(sourceFile, file)); + request.setImportOptions(buildImportOptions(sourceFile, file, srxStorageId)); PropertiesBeanUtils.getUpdateOption(file.getUpdateOption()).ifPresent(request::setUpdateOption); if (file.getLabels() != null) { @@ -191,7 +204,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } catch (Exception e) { errorsPresented.set(true); throw new RuntimeException( - String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath())); + String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath()), e); } try { @@ -218,7 +231,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { final AddFileRequest request = new AddFileRequest(); request.setName(fileName); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); - request.setImportOptions(buildImportOptions(sourceFile, file)); + request.setImportOptions(buildImportOptions(sourceFile, file, srxStorageId)); if (file.getExcludedTargetLanguages() != null && !file.getExcludedTargetLanguages().isEmpty()) { request.setExcludedTargetLanguages(file.getExcludedTargetLanguages()); } @@ -250,7 +263,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } catch (IOException e) { errorsPresented.set(true); throw new RuntimeException( - String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath())); + String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath()), e); } try { client.addSource(request); @@ -290,7 +303,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } } - private ImportOptions buildImportOptions(java.io.File sourceFile, FileBean fileBean) { + private ImportOptions buildImportOptions(java.io.File sourceFile, FileBean fileBean, Long srxStorageId) { if (isSpreadsheet(sourceFile, fileBean)) { SpreadsheetFileImportOptions importOptions = new SpreadsheetFileImportOptions(); importOptions.setFirstLineContainsHeader(fileBean.getFirstLineContainsHeader()); @@ -302,10 +315,12 @@ private ImportOptions buildImportOptions(java.io.File sourceFile, FileBean fileB importOptions.setTranslateAttributes(fileBean.getTranslateAttributes()); importOptions.setContentSegmentation(fileBean.getContentSegmentation()); importOptions.setTranslatableElements(fileBean.getTranslatableElements()); + importOptions.setSrxStorageId(srxStorageId); return importOptions; } else { OtherFileImportOptions importOptions = new OtherFileImportOptions(); importOptions.setContentSegmentation(fileBean.getContentSegmentation()); + importOptions.setSrxStorageId(srxStorageId); return importOptions; } } diff --git a/src/main/java/com/crowdin/cli/properties/FileBean.java b/src/main/java/com/crowdin/cli/properties/FileBean.java index 54ed24935..dafefd2a6 100755 --- a/src/main/java/com/crowdin/cli/properties/FileBean.java +++ b/src/main/java/com/crowdin/cli/properties/FileBean.java @@ -12,6 +12,7 @@ import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; import static com.crowdin.cli.properties.PropertiesBuilder.CONTENT_SEGMENTATION; +import static com.crowdin.cli.properties.PropertiesBuilder.CUSTOM_SEGMENTATION; import static com.crowdin.cli.properties.PropertiesBuilder.DEST; import static com.crowdin.cli.properties.PropertiesBuilder.ESCAPE_QUOTES; import static com.crowdin.cli.properties.PropertiesBuilder.ESCAPE_SPECIAL_CHARACTERS; @@ -63,6 +64,7 @@ public class FileBean { private Boolean exportApprovedOnly; private List labels; private List excludedTargetLanguages; + private String customSegmentation; static class FileBeanConfigurator implements BeanConfigurator { @@ -95,6 +97,7 @@ public FileBean buildFromMap(Map map) { PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setExportApprovedOnly, map, EXPORT_APPROVED_ONLY); PropertiesBuilder.setPropertyIfExists(fileBean::setLabels, map, LABELS, List.class); PropertiesBuilder.setPropertyIfExists(fileBean::setExcludedTargetLanguages, map, EXCLUDED_TARGET_LANGUAGES, List.class); + PropertiesBuilder.setPropertyIfExists(fileBean::setCustomSegmentation, map, CUSTOM_SEGMENTATION, String.class); return fileBean; } @@ -102,16 +105,15 @@ public FileBean buildFromMap(Map map) { public void populateWithDefaultValues(FileBean bean) { //Source if (bean.getSource() != null) { - bean.setSource(bean.getSource().replaceAll("[/\\\\]+", Utils.PATH_SEPARATOR_REGEX)); + bean.setSource(Utils.normalizePath(bean.getSource())); } //Translation if (bean.getTranslation() != null) { - bean.setTranslation(bean.getTranslation().replaceAll("[/\\\\]+", Utils.PATH_SEPARATOR_REGEX)); - if (!bean.getTranslation().startsWith(Utils.PATH_SEPARATOR)) { - bean.setTranslation(Utils.PATH_SEPARATOR + bean.getTranslation()); - } + bean.setTranslation(Utils.normalizePath(bean.getTranslation())); if (!PlaceholderUtil.containsLangPlaceholders(bean.getTranslation()) && bean.getScheme() != null) { - bean.setTranslation(StringUtils.removeStart(bean.getTranslation(), Utils.PATH_SEPARATOR)); + bean.setTranslation(Utils.noSepAtStart(bean.getTranslation())); + } else { + bean.setTranslation(Utils.sepAtStart(bean.getTranslation())); } } @@ -144,6 +146,9 @@ public void populateWithDefaultValues(FileBean bean) { if (bean.getFirstLineContainsHeader() == null) { bean.setFirstLineContainsHeader(Boolean.FALSE); } + if (bean.getCustomSegmentation() != null) { + bean.setCustomSegmentation(Utils.normalizePath(bean.getCustomSegmentation())); + } } @Override diff --git a/src/main/java/com/crowdin/cli/properties/PropertiesBuilder.java b/src/main/java/com/crowdin/cli/properties/PropertiesBuilder.java index a9f27ed65..a50aa0ad4 100644 --- a/src/main/java/com/crowdin/cli/properties/PropertiesBuilder.java +++ b/src/main/java/com/crowdin/cli/properties/PropertiesBuilder.java @@ -114,6 +114,8 @@ public abstract class PropertiesBuilder public static final String EXCLUDED_TARGET_LANGUAGES = "excluded_target_languages"; + public static final String CUSTOM_SEGMENTATION = "custom_segmentation"; + public static final String SETTINGS = "settings"; public static final String IGNORE_HIDDEN_FILES = "ignore_hidden_files"; diff --git a/src/test/java/com/crowdin/cli/client/ProjectBuilder.java b/src/test/java/com/crowdin/cli/client/ProjectBuilder.java index 1d85c9946..b88cca425 100644 --- a/src/test/java/com/crowdin/cli/client/ProjectBuilder.java +++ b/src/test/java/com/crowdin/cli/client/ProjectBuilder.java @@ -123,12 +123,12 @@ private static ProjectSettings buildProjectSettings(Long projectId) { throw new RuntimeException(e); } ps.setTranslateDuplicates(3); - ps.setMtAllowed(true); + ps.setIsMtAllowed(true); ps.setAutoSubstitution(true); ps.setUseGlobalTm(false); ps.setInContext(true); ps.setInContextPseudoLanguageId("ach"); - ps.setSuspended(false); + ps.setIsSuspended(false); ps.setQaCheckIsActive(false); return ps; } From 148f3688bfa983073fc2673f32ee050b94c41029 Mon Sep 17 00:00:00 2001 From: Daniil Barabash Date: Mon, 6 Sep 2021 13:52:27 +0300 Subject: [PATCH 3/5] Add '--branch' param for 'string list' command --- build.gradle | 2 +- .../crowdin/cli/client/CrowdinProjectClient.java | 4 ++-- .../com/crowdin/cli/client/ProjectClient.java | 2 +- .../java/com/crowdin/cli/commands/Actions.java | 2 +- .../crowdin/cli/commands/actions/CliActions.java | 4 ++-- .../cli/commands/actions/StringDeleteAction.java | 2 +- .../cli/commands/actions/StringEditAction.java | 2 +- .../cli/commands/actions/StringListAction.java | 16 +++++++++++++--- .../commands/picocli/StringListSubcommand.java | 5 ++++- .../cli/client/CrowdinProjectClientTest.java | 2 +- .../cli/commands/actions/CliActionsTest.java | 2 +- .../commands/actions/StringDeleteActionTest.java | 8 ++++---- .../commands/actions/StringEditActionTest.java | 8 ++++---- .../commands/actions/StringListActionTest.java | 12 ++++++------ .../cli/commands/picocli/PicocliTestUtils.java | 2 +- .../picocli/StringListSubcommandTest.java | 4 ++-- 16 files changed, 45 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index 1c29d2a31..e04569887 100755 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'info.picocli:picocli:4.6.1' - implementation 'com.github.crowdin:crowdin-api-client-java:1.3.12' + implementation 'com.github.crowdin:crowdin-api-client-java:1.3.14' testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2' testImplementation 'org.hamcrest:hamcrest:2.2' diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index a3307b102..757b9788a 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -241,9 +241,9 @@ public SourceString addSourceString(AddSourceStringRequest request) { } @Override - public List listSourceString(Long fileId, String labelIds, String filter) { + public List listSourceString(Long fileId, Long branchId, String labelIds, String filter) { return executeRequestFullList((limit, offset) -> this.client.getSourceStringsApi() - .listSourceStrings(this.projectId, fileId, null, labelIds, null, filter, null, limit, offset)); + .listSourceStrings(this.projectId, fileId, null, branchId, labelIds, null, filter, null, limit, offset)); } @Override diff --git a/src/main/java/com/crowdin/cli/client/ProjectClient.java b/src/main/java/com/crowdin/cli/client/ProjectClient.java index 93c4e7dff..1c683ff93 100644 --- a/src/main/java/com/crowdin/cli/client/ProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/ProjectClient.java @@ -65,7 +65,7 @@ public interface ProjectClient extends Client { SourceString addSourceString(AddSourceStringRequest request); - List listSourceString(Long fileId, String labelIds, String filter); + List listSourceString(Long fileId, Long branchId, String labelIds, String filter); void deleteSourceString(Long id); diff --git a/src/main/java/com/crowdin/cli/commands/Actions.java b/src/main/java/com/crowdin/cli/commands/Actions.java index b6d493ae5..ad62a2e08 100644 --- a/src/main/java/com/crowdin/cli/commands/Actions.java +++ b/src/main/java/com/crowdin/cli/commands/Actions.java @@ -57,7 +57,7 @@ NewAction stringEdit( boolean noProgress, Long id, String identifier, String newText, String newContext, Integer newMaxLength, List labelNames, Boolean isHidden); NewAction stringList( - boolean noProgress, boolean isVerbose, String file, String filter); + boolean noProgress, boolean isVerbose, String file, String filter, String branchName); NewAction uploadSources( String branchName, boolean deleteObsolete, boolean noProgress, boolean autoUpdate, boolean debug, boolean plainView); diff --git a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java index 37bb117c7..402b62115 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java +++ b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java @@ -100,9 +100,9 @@ public NewAction stringEdit( @Override public NewAction stringList( - boolean noProgress, boolean isVerbose, String file, String filter + boolean noProgress, boolean isVerbose, String file, String filter, String branchName ) { - return new StringListAction(noProgress, isVerbose, file, filter); + return new StringListAction(noProgress, isVerbose, file, filter, branchName); } @Override diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringDeleteAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringDeleteAction.java index 41f6087a8..15d0f9580 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringDeleteAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringDeleteAction.java @@ -40,7 +40,7 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { .stream() .collect(Collectors.toMap((entry) -> entry.getValue().getId(), Map.Entry::getKey)); - List sourceStrings = client.listSourceString(null, null, null) + List sourceStrings = client.listSourceString(null, null, null, null) .stream() .filter(sourceString -> (ids != null && ids.contains(sourceString.getId())) || (texts != null && sourceString.getText() instanceof String && texts.contains(sourceString.getText())) diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringEditAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringEditAction.java index 8d03f2744..ab6827706 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringEditAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringEditAction.java @@ -45,7 +45,7 @@ public StringEditAction( @Override public void act(Outputter out, ProjectProperties pb, ProjectClient client) { - List sourceStrings = client.listSourceString(null, null, null); + List sourceStrings = client.listSourceString(null, null, null, null); List labelIds = (labelNames != null && !labelNames.isEmpty()) ? this.prepareLabelIds(client) : null; diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java index b1e32a160..f44cda1a6 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java @@ -8,6 +8,7 @@ import com.crowdin.cli.properties.ProjectProperties; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.labels.model.Label; +import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.FileInfo; import com.crowdin.client.sourcestrings.model.SourceString; import org.apache.commons.lang3.StringUtils; @@ -17,6 +18,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; @@ -28,12 +30,14 @@ class StringListAction implements NewAction { private final boolean isVerbose; private final String file; private final String filter; + private final String branchName; - public StringListAction(boolean noProgress, boolean isVerbose, String file, String filter) { + public StringListAction(boolean noProgress, boolean isVerbose, String file, String filter, String branchName) { this.noProgress = noProgress; this.isVerbose = isVerbose; this.file = file; this.filter = filter; + this.branchName = branchName; } @Override @@ -41,6 +45,12 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, false, client::downloadFullProject); + Long branchId = Optional.ofNullable(this.branchName) + .map(br -> project.findBranchByName(br) + .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.not_found_branch")))) + .map(Branch::getId) + .orElse(null); + Map labels = client.listLabels().stream() .collect(Collectors.toMap(Label::getId, Label::getTitle)); @@ -58,10 +68,10 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { List sourceStrings; if (StringUtils.isEmpty(file)) { - sourceStrings = client.listSourceString(null, null, encodedFilter); + sourceStrings = client.listSourceString(null, branchId, null, encodedFilter); } else { if (paths.containsKey(file)) { - sourceStrings = client.listSourceString(paths.get(file).getId(), null, encodedFilter); + sourceStrings = client.listSourceString(paths.get(file).getId(), branchId, null, encodedFilter); } else { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file)); } diff --git a/src/main/java/com/crowdin/cli/commands/picocli/StringListSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/StringListSubcommand.java index 7f1777977..ca5d257fc 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/StringListSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/StringListSubcommand.java @@ -22,6 +22,9 @@ class StringListSubcommand extends ActCommandProject { @CommandLine.Option(names = {"--filter"}, paramLabel = "...") protected String filter; + @CommandLine.Option(names = {"-b", "--branch"}, paramLabel = "...") + protected String branchName; + @Override protected List checkOptions() { if (file != null) { @@ -32,6 +35,6 @@ protected List checkOptions() { @Override protected NewAction getAction(Actions actions) { - return actions.stringList(noProgress, isVerbose, file, filter); + return actions.stringList(noProgress, isVerbose, file, filter, branchName); } } diff --git a/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java b/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java index faf185d65..af9aa2ce7 100644 --- a/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java +++ b/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java @@ -523,7 +523,7 @@ public void testListSourceString() { when(httpClientMock.get(eq(listSourceStringUrl), any(), eq(SourceStringResponseList.class))) .thenReturn(response); - client.listSourceString(fileId, null, "FiLtEr"); + client.listSourceString(fileId, null, null, "FiLtEr"); verify(httpClientMock).get(eq(listSourceStringUrl), any(), eq(SourceStringResponseList.class)); verifyNoMoreInteractions(httpClientMock); diff --git a/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java b/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java index 98fd2b10c..00d7a563a 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java @@ -64,7 +64,7 @@ public void testStringEdit() { @Test public void testStringList() { - assertNotNull(actions.stringList(false, false, null, null)); + assertNotNull(actions.stringList(false, false, null, null, null)); } @Test diff --git a/src/test/java/com/crowdin/cli/commands/actions/StringDeleteActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/StringDeleteActionTest.java index f13521dc3..78bd2969b 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/StringDeleteActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/StringDeleteActionTest.java @@ -45,7 +45,7 @@ public void testStringList(List strings, List ids, List strings, List ids, List action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject(); - verify(client).listSourceString(null, null, null); + verify(client).listSourceString(null, null, null, null); for (SourceString sourceString : strings) { verify(client).deleteSourceString(sourceString.getId()); } diff --git a/src/test/java/com/crowdin/cli/commands/actions/StringEditActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/StringEditActionTest.java index 5d1940b64..3c0bb4bdd 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/StringEditActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/StringEditActionTest.java @@ -54,7 +54,7 @@ public void testStringList( when(client.downloadFullProject()) .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) .addFile("first.csv", "csv", 101L, null, null).build()); - when(client.listSourceString(null, null, null)) + when(client.listSourceString(null, null, null, null)) .thenReturn(Arrays.asList(SourceStringBuilder.standard().setProjectId(42L).setIdentifiers(801L, "old", "old", "old", null).build())); if (newLabels != null) { @@ -89,7 +89,7 @@ public void testStringList( add(RequestBuilder.patch(labelIds, PatchOperation.REPLACE, "/labelIds")); } }}; - verify(client).listSourceString(null, null, null); + verify(client).listSourceString(null, null, null, null); verify(client).editSourceString(801L, patches); if (newLabels != null) { verify(client).listLabels(); @@ -121,13 +121,13 @@ public void testBothIdAndIdentifier_throws() throws ResponseException { when(client.downloadFullProject()) .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) .addFile("first.csv", "csv", 101L, null, null).build()); - when(client.listSourceString(null, null, null)) + when(client.listSourceString(null, null, null, null)) .thenReturn(Arrays.asList(SourceStringBuilder.standard().setProjectId(42L).setIdentifiers(801L, "old", "old", "old", null).build())); action = new StringEditAction(true, null, null, null, null, null, null, null); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); - verify(client).listSourceString(null, null, null); + verify(client).listSourceString(null, null, null, null); verifyNoMoreInteractions(client); } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java index fa7faf42c..f39ee3d87 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java @@ -41,20 +41,20 @@ public void testStringList(String file, String filter) throws ResponseException when(client.downloadFullProject()) .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) .addFile("first.csv", "csv", 101L, null, null).build()); - when(client.listSourceString(101L, null, filter)) + when(client.listSourceString(101L, null, null, filter)) .thenReturn(Arrays.asList(SourceStringBuilder.standard() .setProjectId(Long.parseLong(pb.getProjectId())) .setIdentifiers(701L, "7-0-1", "seven-o-one", "7.0.1", 101L).build())); - action = new StringListAction(true, true, file, filter); + action = new StringListAction(true, true, file, filter, null); action.act(Outputter.getDefault(), pb, client); verify(client).downloadFullProject(); verify(client).listLabels(); if (file != null) { - verify(client).listSourceString(101L, null, filter); + verify(client).listSourceString(101L, null, null, filter); } else { - verify(client).listSourceString(null, null, filter); + verify(client).listSourceString(null, null, null, filter); } verifyNoMoreInteractions(client); } @@ -76,7 +76,7 @@ public void testGetProjectThrows() throws ResponseException { when(client.downloadFullProject()) .thenThrow(new RuntimeException("Whoops")); - action = new StringListAction(true, true, null, null); + action = new StringListAction(true, true, null, null, null); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject(); @@ -94,7 +94,7 @@ public void testFileNotExistThrows() throws ResponseException { .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) .addFile("first.csv", "csv", 101L, null, null).build()); - action = new StringListAction(true, true, "notexist.csv", null); + action = new StringListAction(true, true, "notexist.csv", null, null); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject(); diff --git a/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java b/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java index ce991aa99..7593f8057 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java @@ -79,7 +79,7 @@ void mockActions() { .thenReturn(actionMock); when(actionsMock.stringEdit(anyBoolean(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(actionMock); - when(actionsMock.stringList(anyBoolean(), anyBoolean(), any(), any())) + when(actionsMock.stringList(anyBoolean(), anyBoolean(), any(), any(), any())) .thenReturn(actionMock); when(actionsMock.uploadSources(any(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())) .thenReturn(actionMock); diff --git a/src/test/java/com/crowdin/cli/commands/picocli/StringListSubcommandTest.java b/src/test/java/com/crowdin/cli/commands/picocli/StringListSubcommandTest.java index 11af312ad..71bb046f0 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/StringListSubcommandTest.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/StringListSubcommandTest.java @@ -12,7 +12,7 @@ public class StringListSubcommandTest extends PicocliTestUtils { public void testStringList() { this.execute(CommandNames.STRING, CommandNames.STRING_LIST); verify(actionsMock) - .stringList(anyBoolean(), anyBoolean(), any(), any()); + .stringList(anyBoolean(), anyBoolean(), any(), any(), any()); this.check(true); } @@ -20,7 +20,7 @@ public void testStringList() { public void testStringList2() { this.execute(CommandNames.STRING, CommandNames.STRING_LIST, "--file", "some/path/to/file.txt"); verify(actionsMock) - .stringList(anyBoolean(), anyBoolean(), any(), any()); + .stringList(anyBoolean(), anyBoolean(), any(), any(), any()); this.check(true); } } \ No newline at end of file From af6407b4448c69ea6d50c4f2f687aac55bd2bc0f Mon Sep 17 00:00:00 2001 From: Daniil Barabash Date: Mon, 13 Sep 2021 19:01:30 +0300 Subject: [PATCH 4/5] Little fix - add handler for response about invalid srx file --- .../java/com/crowdin/cli/client/CrowdinProjectClient.java | 8 ++++++-- src/main/java/com/crowdin/cli/client/ProjectClient.java | 2 +- .../java/com/crowdin/cli/client/ResponseException.java | 8 ++++++++ .../com/crowdin/cli/client/CrowdinProjectClientTest.java | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index 757b9788a..f44d34745 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -164,9 +164,13 @@ public void deleteDirectory(Long directoryId) { } @Override - public void updateSource(Long sourceId, UpdateFileRequest request) { + public void updateSource(Long sourceId, UpdateFileRequest request) throws ResponseException { + Map, ResponseException> errorHandlers = new LinkedHashMap, ResponseException>() {{ + put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException()); + put((code, message) -> StringUtils.contains(message, "Invalid SRX specified"), new ResponseException("Invalid SRX file specified")); + }}; executeRequestWithPossibleRetry( - (code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), + errorHandlers, () -> this.client.getSourceFilesApi() .updateOrRestoreFile(this.projectId, sourceId, request)); } diff --git a/src/main/java/com/crowdin/cli/client/ProjectClient.java b/src/main/java/com/crowdin/cli/client/ProjectClient.java index 1c683ff93..7f959f7f6 100644 --- a/src/main/java/com/crowdin/cli/client/ProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/ProjectClient.java @@ -43,7 +43,7 @@ public interface ProjectClient extends Client { void deleteDirectory(Long directoryId); - void updateSource(Long sourceId, UpdateFileRequest request); + void updateSource(Long sourceId, UpdateFileRequest request) throws ResponseException ; void addSource(AddFileRequest request) throws ResponseException; diff --git a/src/main/java/com/crowdin/cli/client/ResponseException.java b/src/main/java/com/crowdin/cli/client/ResponseException.java index 3da61d20d..4192876dd 100644 --- a/src/main/java/com/crowdin/cli/client/ResponseException.java +++ b/src/main/java/com/crowdin/cli/client/ResponseException.java @@ -1,4 +1,12 @@ package com.crowdin.cli.client; public class ResponseException extends Exception { + + public ResponseException() { + + } + + public ResponseException(String message) { + super(message); + } } diff --git a/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java b/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java index af9aa2ce7..29ac876df 100644 --- a/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java +++ b/src/test/java/com/crowdin/cli/client/CrowdinProjectClientTest.java @@ -371,7 +371,7 @@ public void testAddDirectoryThrows() throws ResponseException { } @Test - public void testUpdateSource() { + public void testUpdateSource() throws ResponseException { FileResponseObject response = new FileResponseObject() {{ setData(new File()); }}; From d324b5fefd0afaa2686c651855ce65a826abcb22 Mon Sep 17 00:00:00 2001 From: Andrii Bodnar Date: Fri, 17 Sep 2021 10:26:24 +0300 Subject: [PATCH 5/5] Fix: add handler for response about invalid srx file to addSource method --- src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java | 1 + src/main/java/com/crowdin/cli/client/ProjectClient.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index f44d34745..e2381c22d 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -180,6 +180,7 @@ public void addSource(AddFileRequest request) throws ResponseException { Map, ResponseException> errorHandlers = new LinkedHashMap, ResponseException>() {{ put((code, message) -> message.contains("File from storage with id #" + request.getStorageId() + " was not found"), new RepeatException()); put((code, message) -> StringUtils.contains(message, "Name must be unique"), new ExistsResponseException()); + put((code, message) -> StringUtils.contains(message, "Invalid SRX specified"), new ResponseException("Invalid SRX file specified")); }}; executeRequestWithPossibleRetry( errorHandlers, diff --git a/src/main/java/com/crowdin/cli/client/ProjectClient.java b/src/main/java/com/crowdin/cli/client/ProjectClient.java index 7f959f7f6..b5f4d9f5d 100644 --- a/src/main/java/com/crowdin/cli/client/ProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/ProjectClient.java @@ -43,7 +43,7 @@ public interface ProjectClient extends Client { void deleteDirectory(Long directoryId); - void updateSource(Long sourceId, UpdateFileRequest request) throws ResponseException ; + void updateSource(Long sourceId, UpdateFileRequest request) throws ResponseException; void addSource(AddFileRequest request) throws ResponseException;