From 6ba65aa6ef1b91cf035e09b59eb39d3d401e0a9b Mon Sep 17 00:00:00 2001 From: Yevheniy Oliynyk Date: Sat, 21 Sep 2024 19:03:07 +0200 Subject: [PATCH] feat: branch edit --- .../cli/client/CrowdinProjectClient.java | 7 ++ .../com/crowdin/cli/client/ProjectClient.java | 2 + .../com/crowdin/cli/commands/Actions.java | 2 + .../commands/actions/BranchEditAction.java | 79 +++++++++++++++++++ .../cli/commands/actions/CliActions.java | 5 ++ .../picocli/BranchEditSubcommand.java | 50 ++++++++++++ .../commands/picocli/BranchSubcommand.java | 3 +- .../cli/commands/picocli/CommandNames.java | 2 +- .../picocli/StringEditSubcommand.java | 2 +- .../resources/messages/messages.properties | 10 +++ .../actions/BranchEditActionTest.java | 77 ++++++++++++++++++ .../picocli/BranchEditSubcommandTest.java | 29 +++++++ .../commands/picocli/PicocliTestUtils.java | 2 + .../picocli/StringEditSubcommandTest.java | 6 +- website/mantemplates/crowdin-branch-edit.adoc | 16 ++++ website/sidebars.js | 1 + 16 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/crowdin/cli/commands/actions/BranchEditAction.java create mode 100644 src/main/java/com/crowdin/cli/commands/picocli/BranchEditSubcommand.java create mode 100644 src/test/java/com/crowdin/cli/commands/actions/BranchEditActionTest.java create mode 100644 src/test/java/com/crowdin/cli/commands/picocli/BranchEditSubcommandTest.java create mode 100644 website/mantemplates/crowdin-branch-edit.adoc diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index 4fe642b1f..b4a1fdc6b 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -203,6 +203,13 @@ public void deleteBranch(Long branchId) { }); } + @Override + public Branch editBranch(Long branchId, List requests) { + return executeRequest(() -> this.client.getSourceFilesApi() + .editBranch(this.projectId, branchId, requests) + .getData()); + } + @Override public List listBranches() { return executeRequestFullList((limit, offset) -> this.client.getSourceFilesApi() diff --git a/src/main/java/com/crowdin/cli/client/ProjectClient.java b/src/main/java/com/crowdin/cli/client/ProjectClient.java index e18441216..d659e3e20 100644 --- a/src/main/java/com/crowdin/cli/client/ProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/ProjectClient.java @@ -47,6 +47,8 @@ default CrowdinProjectFull downloadFullProject() { void deleteBranch(Long branchId); + Branch editBranch(Long branchId, List requests); + List listBranches(); Long uploadStorage(String fileName, InputStream content) throws ResponseException; diff --git a/src/main/java/com/crowdin/cli/commands/Actions.java b/src/main/java/com/crowdin/cli/commands/Actions.java index ed1bbb3df..dbaf837e9 100644 --- a/src/main/java/com/crowdin/cli/commands/Actions.java +++ b/src/main/java/com/crowdin/cli/commands/Actions.java @@ -120,6 +120,8 @@ NewAction preTranslate( NewAction branchDelete(String name); + NewAction branchEdit(String branch, String name, String title, Priority priority, String exportPattern, boolean noProgress, boolean plainView); + NewAction screenshotList(Long stringId, boolean plainView); NewAction screenshotUpload(File file, String branchName, List labelNames, String directoryPath, String filePath, boolean autoTag, boolean plainView, boolean noProgress, ProjectClient projectClient); diff --git a/src/main/java/com/crowdin/cli/commands/actions/BranchEditAction.java b/src/main/java/com/crowdin/cli/commands/actions/BranchEditAction.java new file mode 100644 index 000000000..e10a62413 --- /dev/null +++ b/src/main/java/com/crowdin/cli/commands/actions/BranchEditAction.java @@ -0,0 +1,79 @@ +package com.crowdin.cli.commands.actions; + +import com.crowdin.cli.client.CrowdinProjectFull; +import com.crowdin.cli.client.ProjectClient; +import com.crowdin.cli.commands.NewAction; +import com.crowdin.cli.commands.Outputter; +import com.crowdin.cli.commands.functionality.RequestBuilder; +import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper; +import com.crowdin.cli.properties.ProjectProperties; +import com.crowdin.cli.utils.console.ConsoleSpinner; +import com.crowdin.cli.utils.console.ExecutionStatus; +import com.crowdin.client.core.model.PatchOperation; +import com.crowdin.client.core.model.PatchRequest; +import com.crowdin.client.core.model.Priority; +import com.crowdin.client.sourcefiles.model.Branch; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; + +class BranchEditAction implements NewAction { + + private final String branch; + private final String name; + private final String title; + private final Priority priority; + private final String exportPattern; + private final boolean noProgress; + private final boolean plainView; + + BranchEditAction(String branch, String name, String title, Priority priority, String exportPattern, boolean noProgress, boolean plainView) { + this.branch = branch; + this.name = name; + this.title = title; + this.priority = priority; + this.exportPattern = exportPattern; + this.noProgress = noProgress; + this.plainView = plainView; + } + + @Override + 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, this.plainView, client::downloadFullProject); + + Optional branchObj = project.findBranchByName(this.branch); + if (branchObj.isEmpty()) { + throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.branch_not_exists"), this.branch)); + } + + List requests = new ArrayList<>(); + if (name != null) { + PatchRequest request = RequestBuilder.patch(name, PatchOperation.REPLACE, "/name"); + requests.add(request); + } + if (title != null) { + PatchRequest request = RequestBuilder.patch(title, PatchOperation.REPLACE, "/title"); + requests.add(request); + } + if (priority != null) { + PatchRequest request = RequestBuilder.patch(priority, PatchOperation.REPLACE, "/priority"); + requests.add(request); + } + if (exportPattern != null) { + PatchRequest request = RequestBuilder.patch(exportPattern, PatchOperation.REPLACE, "/exportPattern"); + requests.add(request); + } + + Branch updatedBranch = client.editBranch(branchObj.get().getId(), requests); + + if (!plainView) { + out.println(ExecutionStatus.OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.branch.list"), updatedBranch.getId(), updatedBranch.getName()))); + } else { + out.println(updatedBranch.getName()); + } + } +} 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 f77e8c8f3..c57211898 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java +++ b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java @@ -249,6 +249,11 @@ public NewAction branchDelete(String name) { return new BranchDeleteAction(name); } + @Override + public NewAction branchEdit(String branch, String name, String title, Priority priority, String exportPattern, boolean noProgress, boolean plainView) { + return new BranchEditAction(branch, name, title, priority, exportPattern, noProgress, plainView); + } + @Override public NewAction screenshotList(Long stringId, boolean plainView) { return new ScreenshotListAction(stringId, plainView); diff --git a/src/main/java/com/crowdin/cli/commands/picocli/BranchEditSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/BranchEditSubcommand.java new file mode 100644 index 000000000..a869ed6b7 --- /dev/null +++ b/src/main/java/com/crowdin/cli/commands/picocli/BranchEditSubcommand.java @@ -0,0 +1,50 @@ +package com.crowdin.cli.commands.picocli; + +import com.crowdin.cli.client.ProjectClient; +import com.crowdin.cli.commands.Actions; +import com.crowdin.cli.commands.NewAction; +import com.crowdin.cli.properties.ProjectProperties; +import com.crowdin.client.core.model.Priority; +import picocli.CommandLine; + +import java.util.ArrayList; +import java.util.List; + +@CommandLine.Command( + sortOptions = false, + name = CommandNames.EDIT +) +class BranchEditSubcommand extends ActCommandProject { + + @CommandLine.Parameters(descriptionKey = "crowdin.branch.edit.name") + protected String name; + + @CommandLine.Option(names = "--name", descriptionKey = "crowdin.branch.edit.new-name", paramLabel = "...", order = -2) + protected String newName; + + @CommandLine.Option(names = "--title", descriptionKey = "crowdin.branch.edit.title", paramLabel = "...", order = -2) + protected String title; + + @CommandLine.Option(names = "--priority", descriptionKey = "crowdin.branch.edit.priority", paramLabel = "...", order = -2) + protected Priority priority; + + @CommandLine.Option(names = "--export-pattern", descriptionKey = "crowdin.branch.edit.export-pattern", paramLabel = "...", order = -2) + protected String exportPattern; + + @CommandLine.Option(names = {"--plain"}, descriptionKey = "crowdin.list.usage.plain") + protected boolean plainView; + + @Override + protected List checkOptions() { + List errors = new ArrayList<>(); + if (newName == null && title == null && priority == null && exportPattern == null) { + errors.add(RESOURCE_BUNDLE.getString("error.branch_no_edit")); + } + return errors; + } + + @Override + protected NewAction getAction(Actions actions) { + return actions.branchEdit(name, newName, title, priority, exportPattern, noProgress, plainView); + } +} diff --git a/src/main/java/com/crowdin/cli/commands/picocli/BranchSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/BranchSubcommand.java index c258b9ac1..8d6958942 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/BranchSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/BranchSubcommand.java @@ -9,7 +9,8 @@ BranchCloneSubcommand.class, BranchDeleteSubcommand.class, BranchListSubcommand.class, - BranchMergeSubcommand.class + BranchMergeSubcommand.class, + BranchEditSubcommand.class } ) class BranchSubcommand extends HelpCommand { diff --git a/src/main/java/com/crowdin/cli/commands/picocli/CommandNames.java b/src/main/java/com/crowdin/cli/commands/picocli/CommandNames.java index ec2fd1b61..cd89e29f3 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/CommandNames.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/CommandNames.java @@ -11,6 +11,7 @@ public final class CommandNames { public static final String LIST = "list"; public static final String ADD = "add"; + public static final String EDIT = "edit"; public static final String DELETE = "delete"; public static final String STATUS = "status"; @@ -18,7 +19,6 @@ public final class CommandNames { public static final String STATUS_PROOFREADING = "proofreading"; public static final String STRING = "string"; - public static final String STRING_EDIT = "edit"; public static final String BRANCH = "branch"; public static final String BRANCH_CLONE = "clone"; diff --git a/src/main/java/com/crowdin/cli/commands/picocli/StringEditSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/StringEditSubcommand.java index fbd082170..9d2e29b57 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/StringEditSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/StringEditSubcommand.java @@ -10,7 +10,7 @@ import java.util.List; @CommandLine.Command( - name = CommandNames.STRING_EDIT, + name = CommandNames.EDIT, sortOptions = false ) class StringEditSubcommand extends ActCommandProject { diff --git a/src/main/resources/messages/messages.properties b/src/main/resources/messages/messages.properties index a1e9717a0..79a0dc59c 100755 --- a/src/main/resources/messages/messages.properties +++ b/src/main/resources/messages/messages.properties @@ -248,6 +248,15 @@ crowdin.branch.merge.target=Target branch name crowdin.branch.merge.dryrun=Simulate merging without making any real changes crowdin.branch.merge.delete-after-merge=Whether to delete branch after merge +# CROWDIN BRANCH EDIT COMMAND +crowdin.branch.edit.usage.description=Edit existing branch +crowdin.branch.edit.usage.customSynopsis=@|fg(green) crowdin branch edit|@ [CONFIG OPTIONS] [OPTIONS] +crowdin.branch.edit.name=Branch name +crowdin.branch.edit.new-name=Rename branch +crowdin.branch.edit.title=Specify new title for the branch +crowdin.branch.edit.priority=Specify new priority for the branch +crowdin.branch.edit.export-pattern=Specify new export pattern for the branch + crowdin.glossary.upload.usage.description=Upload glossary to localization resources crowdin.glossary.upload.usage.customSynopsis=@|fg(green) crowdin glossary upload|@ [CONFIG OPTIONS] [OPTIONS] crowdin.glossary.upload.file=File to upload @@ -501,6 +510,7 @@ error.file_or_directory_required=The '--file' or '--directory' parameter is requ error.dir_not_exists=Project doesn't contain the '%s' directory error.branch_not_exists=Project doesn't contain the '%s' branch error.source_string_no_edit=Specify some parameters to edit the string +error.branch_no_edit=Specify some parameters to edit the branch error.unexpected_response=Unexpected response from %s: %s error.error_response=Error from %s: %s error.in_local_server=Error in raised local server diff --git a/src/test/java/com/crowdin/cli/commands/actions/BranchEditActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/BranchEditActionTest.java new file mode 100644 index 000000000..9450fef33 --- /dev/null +++ b/src/test/java/com/crowdin/cli/commands/actions/BranchEditActionTest.java @@ -0,0 +1,77 @@ +package com.crowdin.cli.commands.actions; + +import com.crowdin.cli.client.ProjectBuilder; +import com.crowdin.cli.client.ProjectClient; +import com.crowdin.cli.commands.NewAction; +import com.crowdin.cli.commands.Outputter; +import com.crowdin.cli.commands.functionality.RequestBuilder; +import com.crowdin.cli.properties.NewPropertiesWithFilesUtilBuilder; +import com.crowdin.cli.properties.ProjectProperties; +import com.crowdin.cli.properties.PropertiesWithFiles; +import com.crowdin.cli.utils.Utils; +import com.crowdin.client.core.model.PatchOperation; +import com.crowdin.client.core.model.PatchRequest; +import com.crowdin.client.core.model.Priority; +import com.crowdin.client.sourcefiles.model.Branch; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.*; + +public class BranchEditActionTest { + + private PropertiesWithFiles pb; + private ProjectClient client = mock(ProjectClient.class); + private NewAction action; + + @ParameterizedTest + @MethodSource + public void testBranchEdit(String branch, String name, String title, Priority priority, String exportPattern) { + Long branchId = 1L; + + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(Utils.PATH_SEPARATOR); + pb = pbBuilder.build(); + when(client.downloadFullProject()) + .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addBranches(branchId, branch).build()); + + when(client.editBranch(any(), any())).thenReturn(new Branch()); + + action = new BranchEditAction(branch, name, title, priority, exportPattern, false, false); + action.act(Outputter.getDefault(), pb, client); + + List patches = new ArrayList<>() {{ + if (name != null) { + add(RequestBuilder.patch(name, PatchOperation.REPLACE, "/name")); + } + if (title != null) { + add(RequestBuilder.patch(title, PatchOperation.REPLACE, "/title")); + } + if (priority != null) { + add(RequestBuilder.patch(priority, PatchOperation.REPLACE, "/priority")); + } + if (exportPattern != null) { + add(RequestBuilder.patch(exportPattern, PatchOperation.REPLACE, "/exportPattern")); + } + }}; + verify(client).editBranch(branchId, patches); + } + + public static Stream testBranchEdit() { + return Stream.of( + arguments("main", "dev", null, null, null), + arguments("main", null, "test", null, null), + arguments("main", null, null, Priority.HIGH, null), + arguments("main", null, null, null, "%three_letters_code%"), + arguments("main", "dev", "test", Priority.HIGH, "%three_letters_code%") + ); + } +} diff --git a/src/test/java/com/crowdin/cli/commands/picocli/BranchEditSubcommandTest.java b/src/test/java/com/crowdin/cli/commands/picocli/BranchEditSubcommandTest.java new file mode 100644 index 000000000..54d140a66 --- /dev/null +++ b/src/test/java/com/crowdin/cli/commands/picocli/BranchEditSubcommandTest.java @@ -0,0 +1,29 @@ +package com.crowdin.cli.commands.picocli; + +import com.crowdin.client.core.model.Priority; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.verify; + +public class BranchEditSubcommandTest extends PicocliTestUtils { + + @Test + public void testBranchEdit() { + String branchName = "main"; + Priority priority = Priority.HIGH; + this.execute(CommandNames.BRANCH, CommandNames.EDIT, branchName, "--priority", priority.name()); + verify(actionsMock) + .branchEdit(branchName, null, null, priority, null, false, false); + this.check(true); + } + + @Test + public void testBranchEditInvalidOptions() { + this.executeInvalidParams(CommandNames.BRANCH, CommandNames.EDIT); + } + + @Test + public void testBranchEditInvalidOptions2() { + this.executeInvalidParams(CommandNames.BRANCH, CommandNames.EDIT, "--name", "test"); + } +} \ No newline at end of file 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 8156b153d..0b7ce4958 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java @@ -142,6 +142,8 @@ void mockActions() { .thenReturn(actionMock); when(actionsMock.branchMerge(any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())) .thenReturn(actionMock); + when(actionsMock.branchEdit(any(), any(), any(), any(), any(), anyBoolean(), anyBoolean())) + .thenReturn(actionMock); } private void mockBuilders() { diff --git a/src/test/java/com/crowdin/cli/commands/picocli/StringEditSubcommandTest.java b/src/test/java/com/crowdin/cli/commands/picocli/StringEditSubcommandTest.java index bdea150be..0a4d7d875 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/StringEditSubcommandTest.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/StringEditSubcommandTest.java @@ -10,7 +10,7 @@ public class StringEditSubcommandTest extends PicocliTestUtils { @Test public void testStringEdit() { - this.execute(CommandNames.STRING, CommandNames.STRING_EDIT, "42", "--text", "NeW tExT"); + this.execute(CommandNames.STRING, CommandNames.EDIT, "42", "--text", "NeW tExT"); verify(actionsMock) .stringEdit(anyBoolean(), anyBoolean(), any(), any(), any(), any(), any(), any(), any(), anyBoolean()); this.check(true); @@ -18,11 +18,11 @@ public void testStringEdit() { @Test public void testStringEditInvalidOptions() { - this.executeInvalidParams(CommandNames.STRING, CommandNames.STRING_EDIT); + this.executeInvalidParams(CommandNames.STRING, CommandNames.EDIT); } @Test public void testStringEditInvalidOptions2() { - this.executeInvalidParams(CommandNames.STRING, CommandNames.STRING_EDIT, "--id", "42", "--identifier", "4242"); + this.executeInvalidParams(CommandNames.STRING, CommandNames.EDIT, "--id", "42", "--identifier", "4242"); } } \ No newline at end of file diff --git a/website/mantemplates/crowdin-branch-edit.adoc b/website/mantemplates/crowdin-branch-edit.adoc new file mode 100644 index 000000000..d828c2230 --- /dev/null +++ b/website/mantemplates/crowdin-branch-edit.adoc @@ -0,0 +1,16 @@ +:includedir: ../generated-picocli-docs +:command: crowdin-branch-edit + +== crowdin branch edit + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-description] + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-synopsis] + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-arguments] + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-commands] + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-options] + +include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-footer] diff --git a/website/sidebars.js b/website/sidebars.js index b6c40e0ac..a60daa106 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -100,6 +100,7 @@ const sidebars = { 'commands/crowdin-branch-clone', 'commands/crowdin-branch-merge', 'commands/crowdin-branch-delete', + 'commands/crowdin-branch-edit', ] }, {