Skip to content

Commit e07c17a

Browse files
authoredNov 20, 2024··
feat: app commands (#868)
1 parent 7b93ceb commit e07c17a

27 files changed

+544
-2
lines changed
 

‎src/main/java/com/crowdin/cli/client/CrowdinClientCore.java

+7
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ protected static <T> T executeRequest(Supplier<T> r) {
100100
return executeRequest(new HashMap<BiPredicate<String, String>, RuntimeException>(), r);
101101
}
102102

103+
protected static void executeRequest(Runnable r) {
104+
executeRequest(() -> {
105+
r.run();
106+
return null;
107+
});
108+
}
109+
103110
protected static <T, R extends Exception> T executeRequest(Map<BiPredicate<String, String>, R> errorHandlers, Supplier<T> r) throws R {
104111
try {
105112
return r.get();

‎src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java

+40
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
44
import com.crowdin.cli.utils.Utils;
5+
import com.crowdin.client.applications.installations.model.ApplicationInstallation;
6+
import com.crowdin.client.applications.installations.model.InstallApplicationRequest;
57
import com.crowdin.client.branches.model.*;
68
import com.crowdin.client.core.model.PatchRequest;
79
import com.crowdin.client.labels.model.AddLabelRequest;
@@ -18,10 +20,15 @@
1820
import com.crowdin.client.stringcomments.model.StringComment;
1921
import com.crowdin.client.translations.model.*;
2022
import com.crowdin.client.translationstatus.model.LanguageProgress;
23+
import lombok.SneakyThrows;
2124
import org.apache.commons.lang3.StringUtils;
25+
import org.json.JSONArray;
26+
import org.json.JSONObject;
2227

2328
import java.io.InputStream;
2429
import java.net.URL;
30+
import java.net.URLEncoder;
31+
import java.nio.charset.StandardCharsets;
2532
import java.util.*;
2633
import java.util.function.BiPredicate;
2734

@@ -530,4 +537,37 @@ public Project addProject(AddProjectRequest request) {
530537
.addProject(request)
531538
.getData());
532539
}
540+
541+
@Override
542+
public List<ApplicationInstallation> listApplications() {
543+
return executeRequestFullList((limit, offset) ->
544+
this.client.getApplicationsApi().listApplicationInstallations(limit, offset)
545+
);
546+
}
547+
548+
@Override
549+
public void uninstallApplication(String id, boolean force) {
550+
executeRequest(() -> this.client.getApplicationsApi().deleteApplicationInstallation(id, force));
551+
}
552+
553+
@Override
554+
public void installApplication(String url) {
555+
var req = new InstallApplicationRequest();
556+
req.setUrl(url);
557+
executeRequest(() -> this.client.getApplicationsApi().installApplication(req));
558+
}
559+
560+
@Override
561+
@SneakyThrows
562+
public Optional<String> findManifestUrl(String id) {
563+
var query = URLEncoder.encode( "{\"slug\":{\"_eq\":\"" + id + "\"}}", StandardCharsets.UTF_8);
564+
var url = new URL("https://developer.app.crowdin.net/items/Item?filter=" + query + "&fields=manifest");
565+
var res = new String(url.openStream().readAllBytes());
566+
JSONObject json = new JSONObject(res);
567+
var apps = (JSONArray) json.get("data");
568+
if (apps.isEmpty()) {
569+
return Optional.empty();
570+
}
571+
return Optional.ofNullable(JSONObject.class.cast(apps.get(0)).get("manifest").toString());
572+
}
533573
}

‎src/main/java/com/crowdin/cli/client/ProjectClient.java

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.crowdin.cli.client;
22

3+
import com.crowdin.client.applications.installations.model.ApplicationInstallation;
4+
import com.crowdin.client.applications.model.ApplicationDataResponseObject;
35
import com.crowdin.client.branches.model.*;
46
import com.crowdin.client.core.model.PatchRequest;
57
import com.crowdin.client.labels.model.AddLabelRequest;
@@ -17,6 +19,7 @@
1719
import java.io.InputStream;
1820
import java.net.URL;
1921
import java.util.List;
22+
import java.util.Optional;
2023

2124
public interface ProjectClient extends Client {
2225

@@ -129,4 +132,12 @@ default CrowdinProjectFull downloadFullProject() {
129132
List<? extends Project> listProjects();
130133

131134
Project addProject(AddProjectRequest request);
135+
136+
List<ApplicationInstallation> listApplications();
137+
138+
void uninstallApplication(String id, boolean force);
139+
140+
void installApplication(String url);
141+
142+
Optional<String> findManifestUrl(String id);
132143
}

‎src/main/java/com/crowdin/cli/commands/Actions.java

+6
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,10 @@ NewAction<PropertiesWithFiles, ProjectClient> preTranslate(
149149
NewAction<ProjectProperties, ProjectClient> projectList(boolean isVerbose);
150150

151151
NewAction<ProjectProperties, ProjectClient> projectAdd(String name, boolean isStringBased, String sourceLanguage, List<String> languages, boolean isPublic, boolean plainView);
152+
153+
NewAction<ProjectProperties, ProjectClient> listApps(boolean plainView);
154+
155+
NewAction<ProjectProperties, ProjectClient> uninstallApp(String id, Boolean force);
156+
157+
NewAction<ProjectProperties, ProjectClient> installApp(String identifier);
152158
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.crowdin.cli.commands.actions;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.NewAction;
5+
import com.crowdin.cli.commands.Outputter;
6+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
7+
import com.crowdin.cli.properties.ProjectProperties;
8+
import com.crowdin.cli.utils.console.ExecutionStatus;
9+
import lombok.RequiredArgsConstructor;
10+
11+
import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
12+
13+
@RequiredArgsConstructor
14+
class AppInstallAction implements NewAction<ProjectProperties, ProjectClient> {
15+
16+
private final String id;
17+
18+
@Override
19+
public void act(Outputter out, ProjectProperties pb, ProjectClient client) {
20+
var manifestUrl = client.findManifestUrl(id);
21+
if (manifestUrl.isEmpty()) {
22+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.application_not_found"), this.id));
23+
}
24+
client.installApplication(manifestUrl.get());
25+
out.println(ExecutionStatus.OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.application.install"), id)));
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.crowdin.cli.commands.actions;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.NewAction;
5+
import com.crowdin.cli.commands.Outputter;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
8+
import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
9+
10+
class AppListAction implements NewAction<ProjectProperties, ProjectClient> {
11+
private final boolean plainView;
12+
13+
public AppListAction(boolean plainView) {
14+
this.plainView = plainView;
15+
}
16+
17+
@Override
18+
public void act(Outputter out, ProjectProperties pb, ProjectClient client) {
19+
client
20+
.listApplications()
21+
.forEach(app -> {
22+
if (!plainView) {
23+
out.println(String.format(RESOURCE_BUNDLE.getString("message.application.list"), app.getIdentifier(), app.getName()));
24+
} else {
25+
out.println(app.getIdentifier());
26+
}
27+
});
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.crowdin.cli.commands.actions;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.NewAction;
5+
import com.crowdin.cli.commands.Outputter;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
import com.crowdin.cli.utils.console.ExecutionStatus;
8+
import lombok.RequiredArgsConstructor;
9+
10+
import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
11+
12+
@RequiredArgsConstructor
13+
class AppUninstallAction implements NewAction<ProjectProperties, ProjectClient> {
14+
15+
private final String id;
16+
private final boolean force;
17+
18+
@Override
19+
public void act(Outputter out, ProjectProperties pb, ProjectClient client) {
20+
client.uninstallApplication(id, force);
21+
out.println(ExecutionStatus.OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.application.uninstall"), id)));
22+
}
23+
}

‎src/main/java/com/crowdin/cli/commands/actions/CliActions.java

+15
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,19 @@ public NewAction<ProjectProperties, ProjectClient> projectList(boolean isVerbose
323323
public NewAction<ProjectProperties, ProjectClient> projectAdd(String name, boolean isStringBased, String sourceLanguage, List<String> languages, boolean isPublic, boolean plainView) {
324324
return new ProjectAddAction(name, isStringBased, sourceLanguage, languages, isPublic, plainView);
325325
}
326+
327+
@Override
328+
public NewAction<ProjectProperties, ProjectClient> listApps(boolean plainView) {
329+
return new AppListAction(plainView);
330+
}
331+
332+
@Override
333+
public NewAction<ProjectProperties, ProjectClient> uninstallApp(String id, Boolean force) {
334+
return new AppUninstallAction(id, force);
335+
}
336+
337+
@Override
338+
public NewAction<ProjectProperties, ProjectClient> installApp(String identifier) {
339+
return new AppInstallAction(identifier);
340+
}
326341
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.Actions;
5+
import com.crowdin.cli.commands.NewAction;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
import picocli.CommandLine;
8+
9+
@CommandLine.Command(
10+
sortOptions = false,
11+
name = CommandNames.INSTALL
12+
)
13+
class AppInstallSubcommand extends ActCommandProject {
14+
15+
@CommandLine.Parameters(descriptionKey = "crowdin.app.install.identifier")
16+
protected String identifier;
17+
18+
@Override
19+
protected NewAction<ProjectProperties, ProjectClient> getAction(Actions actions) {
20+
return actions.installApp(identifier);
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.Actions;
5+
import com.crowdin.cli.commands.NewAction;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
import picocli.CommandLine;
8+
9+
@CommandLine.Command(
10+
name = CommandNames.LIST
11+
)
12+
class AppListSubcommand extends ActCommandProject {
13+
14+
@Override
15+
protected NewAction<ProjectProperties, ProjectClient> getAction(Actions actions) {
16+
return actions.listApps(this.plainView);
17+
}
18+
19+
@CommandLine.Option(names = {"--plain"}, descriptionKey = "crowdin.list.usage.plain")
20+
protected boolean plainView;
21+
22+
@Override
23+
protected final boolean isAnsi() {
24+
return super.isAnsi() && !plainView;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.Actions;
5+
import com.crowdin.cli.commands.NewAction;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
import picocli.CommandLine;
8+
9+
@CommandLine.Command(
10+
sortOptions = false,
11+
name = CommandNames.UNINSTALL
12+
)
13+
class AppUninstallSubcommand extends ActCommandProject {
14+
15+
@CommandLine.Parameters(descriptionKey = "crowdin.app.uninstall.identifier")
16+
protected String identifier;
17+
18+
@CommandLine.Option(names = {"--force"}, descriptionKey = "crowdin.app.uninstall.force", order = -2)
19+
protected boolean force;
20+
21+
@Override
22+
protected NewAction<ProjectProperties, ProjectClient> getAction(Actions actions) {
23+
return actions.uninstallApp(identifier, force);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import picocli.CommandLine;
4+
5+
@CommandLine.Command(
6+
name = CommandNames.APP,
7+
subcommands = {
8+
AppListSubcommand.class,
9+
AppInstallSubcommand.class,
10+
AppUninstallSubcommand.class
11+
}
12+
)
13+
class ApplicationSubcommand extends HelpCommand {
14+
15+
@Override
16+
protected CommandLine getCommand(CommandLine rootCommand) {
17+
return rootCommand.getSubcommands().get(CommandNames.APP);
18+
}
19+
}

‎src/main/java/com/crowdin/cli/commands/picocli/CommandNames.java

+3
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,7 @@ public final class CommandNames {
6565

6666
public static final String PROJECT = "project";
6767
public static final String BROWSE = "browse";
68+
public static final String APP = "app";
69+
public static final String UNINSTALL = "uninstall";
70+
public static final String INSTALL = "install";
6871
}

‎src/main/java/com/crowdin/cli/commands/picocli/RootCommand.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
LanguageSubcommand.class,
2626
ConfigSubcommand.class,
2727
ProjectSubcommand.class,
28-
CompletionSubCommand.class
28+
CompletionSubCommand.class,
29+
ApplicationSubcommand.class
2930
})
3031
class RootCommand extends HelpCommand {
3132
@Override

‎src/main/resources/messages/messages.properties

+24
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,25 @@ crowdin.project.add.source-language=Defines the source language. English by defa
476476
crowdin.project.add.public=Defines whether the project is public. Private by default
477477
crowdin.project.add.string-based=Defines whether the project is string-based
478478

479+
# CROWDIN APP COMMAND
480+
crowdin.app.usage.description=Manage apps
481+
crowdin.app.usage.customSynopsis=@|fg(green) crowdin app|@ [SUBCOMMAND] [CONFIG OPTIONS] [OPTIONS]
482+
483+
# CROWDIN APP LIST
484+
crowdin.app.list.usage.description=List installed apps
485+
crowdin.app.list.usage.customSynopsis=@|fg(green) crowdin app list|@ [CONFIG OPTIONS] [OPTIONS]
486+
487+
# CROWDIN APP INSTALL
488+
crowdin.app.install.usage.description=Install the application
489+
crowdin.app.install.usage.customSynopsis=@|fg(green) crowdin app install|@ <identifier> [CONFIG OPTIONS] [OPTIONS]
490+
crowdin.app.install.identifier=Application identifier. You can find it on Crowdin Store
491+
492+
# CROWDIN APP UNINSTALL
493+
crowdin.app.uninstall.usage.description=Uninstall the application
494+
crowdin.app.uninstall.usage.customSynopsis=@|fg(green) crowdin app uninstall|@ <identifier> [CONFIG OPTIONS] [OPTIONS]
495+
crowdin.app.uninstall.identifier=Application identifier
496+
crowdin.app.uninstall.force=Force to delete application installation
497+
479498
error.collect_project_info=Failed to collect project info. Please contact our support team for help
480499
error.no_sources=No sources found for '%s' pattern. Check the source paths in your configuration file
481500
error.only_enterprise=Operation is available only for Crowdin Enterprise
@@ -521,6 +540,7 @@ error.file_not_exists=Project doesn't contain the '%s' file
521540
error.file_required=The '--file' parameter is required for this type of project
522541
error.dir_not_exists=Project doesn't contain the '%s' directory
523542
error.branch_not_exists=Project doesn't contain the '%s' branch
543+
error.application_not_found=Application with identifier '%s' doesn't exist in Crowdin Store
524544
error.source_string_no_edit=Specify some parameters to edit the string
525545
error.branch_no_edit=Specify some parameters to edit the branch
526546
error.unexpected_response=Unexpected response from %s: %s
@@ -771,6 +791,10 @@ message.label.list_empty=No labels found
771791
message.label.already_exists=Label '%s' already exists in the project
772792
message.label.deleted=@|green Label '%s' deleted successfully|@
773793

794+
message.application.list=@|yellow %s|@ @|green %s|@
795+
message.application.uninstall=@|green Application %s has been uninstalled|@
796+
message.application.install=@|green Application %s has been installed|@
797+
774798
message.delete_obsolete.obsolete_file_delete='%s' file was deleted
775799
message.delete_obsolete.obsolete_directory_delete=No obsolete files were found
776800
message.delete_obsolete.no_obsolete_files_found='%s' directory was deleted
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.crowdin.cli.commands.actions;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.NewAction;
5+
import com.crowdin.cli.commands.Outputter;
6+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
7+
import com.crowdin.cli.properties.ProjectProperties;
8+
import com.crowdin.cli.properties.PropertiesWithFiles;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.util.Optional;
12+
13+
import static org.junit.jupiter.api.Assertions.assertThrows;
14+
import static org.mockito.Mockito.*;
15+
16+
public class AppInstallActionTest {
17+
18+
Outputter out = Outputter.getDefault();
19+
PropertiesWithFiles pb;
20+
21+
ProjectClient clientMock = mock(ProjectClient.class);
22+
NewAction<ProjectProperties, ProjectClient> action;
23+
24+
@Test
25+
public void testInstall() {
26+
String id = "test";
27+
String url = "test.com/manifest.json";
28+
when(clientMock.findManifestUrl(id)).thenReturn(Optional.of(url));
29+
doNothing().when(clientMock).installApplication(url);
30+
31+
action = new AppInstallAction(id);
32+
action.act(out, pb, clientMock);
33+
34+
verify(clientMock).findManifestUrl(id);
35+
verify(clientMock).installApplication(url);
36+
verifyNoMoreInteractions(clientMock);
37+
}
38+
39+
@Test
40+
public void testInstallFailed() {
41+
String id = "test";
42+
when(clientMock.findManifestUrl(id)).thenReturn(Optional.empty());
43+
44+
action = new AppInstallAction(id);
45+
assertThrows(ExitCodeExceptionMapper.NotFoundException.class, () -> action.act(out, pb, clientMock));
46+
47+
verify(clientMock).findManifestUrl(id);
48+
verifyNoMoreInteractions(clientMock);
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.crowdin.cli.commands.actions;
2+
3+
import com.crowdin.cli.client.ProjectClient;
4+
import com.crowdin.cli.commands.NewAction;
5+
import com.crowdin.cli.commands.Outputter;
6+
import com.crowdin.cli.properties.ProjectProperties;
7+
import com.crowdin.cli.properties.PropertiesWithFiles;
8+
import com.crowdin.client.applications.installations.model.ApplicationInstallation;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.util.Arrays;
12+
import java.util.Collections;
13+
import java.util.List;
14+
15+
import static org.mockito.Mockito.*;
16+
17+
public class AppListActionTest {
18+
19+
List<ApplicationInstallation> standardList = Arrays.asList(new ApplicationInstallation(), new ApplicationInstallation());
20+
List<ApplicationInstallation> emptyList = Collections.emptyList();
21+
22+
Outputter out = Outputter.getDefault();
23+
PropertiesWithFiles pb;
24+
25+
ProjectClient clientMock = mock(ProjectClient.class);
26+
NewAction<ProjectProperties, ProjectClient> action;
27+
28+
@Test
29+
public void test_standard() {
30+
when(clientMock.listApplications())
31+
.thenReturn(standardList);
32+
33+
action = new AppListAction(false);
34+
action.act(out, pb, clientMock);
35+
36+
verify(clientMock).listApplications();
37+
verifyNoMoreInteractions(clientMock);
38+
}
39+
40+
@Test
41+
public void test_plainView() {
42+
when(clientMock.listApplications())
43+
.thenReturn(standardList);
44+
45+
action = new AppListAction(true);
46+
action.act(out, pb, clientMock);
47+
48+
verify(clientMock).listApplications();
49+
verifyNoMoreInteractions(clientMock);
50+
}
51+
52+
@Test
53+
public void test_emptyList() {
54+
when(clientMock.listApplications())
55+
.thenReturn(emptyList);
56+
57+
action = new AppListAction(false);
58+
action.act(out, pb, clientMock);
59+
60+
verify(clientMock).listApplications();
61+
verifyNoMoreInteractions(clientMock);
62+
}
63+
64+
@Test
65+
public void test_emptyList_plainView() {
66+
when(clientMock.listApplications())
67+
.thenReturn(emptyList);
68+
69+
action = new AppListAction(true);
70+
action.act(out, pb, clientMock);
71+
72+
verify(clientMock).listApplications();
73+
verifyNoMoreInteractions(clientMock);
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.mockito.Mockito.verify;
6+
7+
public class AppInstallSubcommandTest extends PicocliTestUtils {
8+
9+
@Test
10+
public void testAppInstall() {
11+
var appId = "test-app";
12+
this.execute(CommandNames.APP, CommandNames.INSTALL, appId);
13+
verify(actionsMock).installApp(appId);
14+
this.check(true);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.mockito.ArgumentMatchers.anyBoolean;
6+
import static org.mockito.Mockito.verify;
7+
8+
public class AppListSubcommandTest extends PicocliTestUtils {
9+
10+
@Test
11+
public void testAppList() {
12+
this.execute(CommandNames.APP, CommandNames.LIST);
13+
verify(actionsMock).listApps(anyBoolean());
14+
this.check(true);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.crowdin.cli.commands.picocli;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.mockito.ArgumentMatchers.anyBoolean;
6+
import static org.mockito.Mockito.verify;
7+
8+
public class AppUninstallSubcommandTest extends PicocliTestUtils {
9+
10+
@Test
11+
public void testAppUninstall() {
12+
var appId = "test-app";
13+
this.execute(CommandNames.APP, CommandNames.UNINSTALL, appId);
14+
verify(actionsMock).uninstallApp(appId, false);
15+
this.check(true);
16+
}
17+
18+
@Test
19+
public void testAppUninstallForce() {
20+
var appId = "test-app";
21+
this.execute(CommandNames.APP, CommandNames.UNINSTALL, appId, "--force");
22+
verify(actionsMock).uninstallApp(appId, true);
23+
this.check(true);
24+
}
25+
}

‎src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java

+3
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ void mockActions() {
145145
.thenReturn(actionMock);
146146
when(actionsMock.branchEdit(any(), any(), any(), any(), anyBoolean(), anyBoolean()))
147147
.thenReturn(actionMock);
148+
when(actionsMock.listApps(anyBoolean())).thenReturn(actionMock);
149+
when(actionsMock.uninstallApp(anyString(), anyBoolean())).thenReturn(actionMock);
150+
when(actionsMock.installApp(anyString())).thenReturn(actionMock);
148151
}
149152

150153
private void mockBuilders() {

‎versions.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ version.commons-io..commons-io=2.16.1
4343

4444
version.commons-cli..commons-cli=1.7.0
4545

46-
version.com.github.crowdin..crowdin-api-client-java=1.19.2
46+
version.com.github.crowdin..crowdin-api-client-java=1.19.4
4747

4848
plugin.org.asciidoctor.jvm.convert=3.3.2
4949

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:includedir: ../generated-picocli-docs
2+
:command: crowdin-app-install
3+
4+
== crowdin app install
5+
6+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-description]
7+
8+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-synopsis]
9+
10+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-arguments]
11+
12+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-commands]
13+
14+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-options]
15+
16+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-footer]
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:includedir: ../generated-picocli-docs
2+
:command: crowdin-app-list
3+
4+
== crowdin app list
5+
6+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-description]
7+
8+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-synopsis]
9+
10+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-arguments]
11+
12+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-commands]
13+
14+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-options]
15+
16+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-footer]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:includedir: ../generated-picocli-docs
2+
:command: crowdin-app-uninstall
3+
4+
== crowdin app uninstall
5+
6+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-description]
7+
8+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-synopsis]
9+
10+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-arguments]
11+
12+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-commands]
13+
14+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-options]
15+
16+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-footer]

‎website/mantemplates/crowdin-app.adoc

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:includedir: ../generated-picocli-docs
2+
:command: crowdin-app
3+
4+
== crowdin app
5+
6+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-description]
7+
8+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-synopsis]
9+
10+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-arguments]
11+
12+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-commands]
13+
14+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-options]
15+
16+
include::{includedir}/{command}.adoc[tag=picocli-generated-man-section-footer]

‎website/sidebars.js

+15
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,21 @@ const sidebars = {
281281
'commands/crowdin-label-add',
282282
'commands/crowdin-label-delete',
283283
]
284+
},
285+
{
286+
type: 'category',
287+
label: 'crowdin app',
288+
link: {
289+
type: 'doc',
290+
id: 'commands/crowdin-app'
291+
},
292+
collapsible: true,
293+
collapsed: true,
294+
items: [
295+
'commands/crowdin-app-list',
296+
'commands/crowdin-app-install',
297+
'commands/crowdin-app-uninstall',
298+
]
284299
}
285300
],
286301
},

0 commit comments

Comments
 (0)
Please sign in to comment.