Skip to content

Commit 6ac90f1

Browse files
authored
modrinth: handle empty projects list as removing all (#635)
1 parent 05f83a9 commit 6ac90f1

File tree

2 files changed

+79
-10
lines changed

2 files changed

+79
-10
lines changed

src/main/java/me/itzg/helpers/modrinth/ModrinthCommand.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,38 @@ public enum DownloadDependencies {
111111
public Integer call() throws Exception {
112112
Files.createDirectories(outputDirectory);
113113

114-
final ModrinthManifest prevManifest = loadManifest();
114+
// Unlike @Parameters, the argument of @Option could be a list with a single empty string
115+
// when --projects="". So, trim away any blanks.
116+
final List<String> trimmedProjects = projects == null ? Collections.emptyList() :
117+
projects.stream()
118+
.filter(s -> !s.trim().isEmpty())
119+
.collect(Collectors.toList());
115120

116-
final List<Path> outputFiles = processProjects(projects);
121+
final List<Path> outputFiles = processProjects(trimmedProjects);
117122

118123
final ModrinthManifest newManifest = ModrinthManifest.builder()
119124
.files(Manifests.relativizeAll(outputDirectory, outputFiles))
120125
.projects(projects)
121126
.build();
122127

128+
final ModrinthManifest prevManifest = loadManifest();
123129
Manifests.cleanup(outputDirectory, prevManifest, newManifest, log);
124130

125-
Manifests.save(outputDirectory, ModrinthManifest.ID, newManifest);
131+
if (!outputFiles.isEmpty()) {
132+
Manifests.save(outputDirectory, ModrinthManifest.ID, newManifest);
133+
}
134+
else {
135+
Manifests.remove(outputDirectory, ModrinthManifest.ID);
136+
}
126137

127138
return ExitCode.OK;
128139
}
129140

130141
private List<Path> processProjects(List<String> projects) {
142+
if (projects == null || projects.isEmpty()) {
143+
return Collections.emptyList();
144+
}
145+
131146
try (ModrinthApiClient modrinthApiClient = new ModrinthApiClient(baseUrl, "modrinth", sharedFetchArgs.options())) {
132147
//noinspection DataFlowIssue since it thinks block() may return null
133148
return

src/test/java/me/itzg/helpers/modrinth/ModrinthCommandTest.java

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemErrNormalized;
44
import static com.github.tomakehurst.wiremock.client.WireMock.*;
55
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
6-
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
7-
import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
86
import static org.assertj.core.api.Assertions.assertThat;
97

108
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -24,6 +22,7 @@
2422
import me.itzg.helpers.modrinth.ModrinthCommand.DownloadDependencies;
2523
import me.itzg.helpers.modrinth.model.Project;
2624
import me.itzg.helpers.modrinth.model.ProjectType;
25+
import org.apache.commons.lang3.RandomStringUtils;
2726
import org.assertj.core.api.AbstractPathAssert;
2827
import org.jetbrains.annotations.NotNull;
2928
import org.junit.jupiter.api.Test;
@@ -48,6 +47,8 @@ class ModrinthCommandTest {
4847
.configureStaticDsl(true)
4948
.build();
5049

50+
private final RandomStringUtils randomStringUtils = RandomStringUtils.insecure();
51+
5152
@Test
5253
void commaNewlineDelimited(@TempDir Path tempDir) {
5354
setupStubs();
@@ -153,6 +154,15 @@ else if (downloadDependencies == DownloadDependencies.OPTIONAL) {
153154
}
154155
}
155156

157+
private String randomAlphanumeric(int n) {
158+
return randomStringUtils.nextAlphanumeric(n);
159+
}
160+
161+
@SuppressWarnings("SameParameterValue")
162+
private String randomAlphabetic(int n) {
163+
return randomStringUtils.nextAlphabetic(n);
164+
}
165+
156166
@Test
157167
void failsWhenNoDependenciesForModLoader(@TempDir Path tempDir) throws JsonProcessingException {
158168
final String projectId = randomAlphanumeric(6);
@@ -162,11 +172,11 @@ void failsWhenNoDependenciesForModLoader(@TempDir Path tempDir) throws JsonProce
162172

163173
stubProjectBulkRequest(projectId, projectSlug);
164174

165-
stubVersionRequest(projectId, versionId, deps -> {
175+
stubVersionRequest(projectId, versionId, deps ->
166176
deps.addObject()
167-
.put("project_id", requiredDepProjectId)
168-
.put("dependency_type", "required");
169-
});
177+
.put("project_id", requiredDepProjectId)
178+
.put("dependency_type", "required")
179+
);
170180
stubVersionRequestEmptyResponse(requiredDepProjectId, "paper");
171181
stubVersionRequestEmptyResponse(requiredDepProjectId, "spigot");
172182
stubGetProject(requiredDepProjectId, new Project().setProjectType(ProjectType.resourcepack));
@@ -277,7 +287,6 @@ void handlesDatapacksSpecificVersion(boolean absoluteWorldDir, @TempDir Path tem
277287

278288
stubProjectBulkRequest(projectId, projectSlug);
279289

280-
final ArrayNode versionResp = objectMapper.createArrayNode();
281290
final ObjectNode versionNode = objectMapper.createObjectNode()
282291
.put("id", versionId)
283292
.put("project_id", projectId)
@@ -412,6 +421,51 @@ void usingListingFile(@TempDir Path tempDir) throws Exception {
412421
assertThat(tempDir.resolve("mods/cloth-config-8.3.103-fabric.jar")).exists();
413422
}
414423

424+
@Test
425+
void removesAllWhenEmpty(@TempDir Path tempDir) {
426+
setupStubs();
427+
428+
{
429+
final int exitCode = new CommandLine(
430+
new ModrinthCommand()
431+
)
432+
.execute(
433+
"--api-base-url", wm.getRuntimeInfo().getHttpBaseUrl(),
434+
"--output-directory", tempDir.toString(),
435+
"--game-version", "1.19.2",
436+
"--loader", "fabric",
437+
"--projects", "fabric-api,cloth-config"
438+
);
439+
440+
assertThat(exitCode).isEqualTo(ExitCode.OK);
441+
442+
assertThat(tempDir.resolve("mods/fabric-api-0.76.1+1.19.2.jar")).exists();
443+
assertThat(tempDir.resolve("mods/cloth-config-8.3.103-fabric.jar")).exists();
444+
}
445+
446+
// now process an empty projects list to uninstall all
447+
{
448+
final int exitCode = new CommandLine(
449+
new ModrinthCommand()
450+
)
451+
.execute(
452+
"--api-base-url", wm.getRuntimeInfo().getHttpBaseUrl(),
453+
"--output-directory", tempDir.toString(),
454+
"--game-version", "1.19.2",
455+
"--loader", "fabric",
456+
"--projects", ""
457+
);
458+
459+
assertThat(exitCode).isEqualTo(ExitCode.OK);
460+
461+
// assert files now do NOT exist
462+
assertThat(tempDir.resolve("mods/fabric-api-0.76.1+1.19.2.jar"))
463+
.doesNotExist();
464+
assertThat(tempDir.resolve("mods/cloth-config-8.3.103-fabric.jar"))
465+
.doesNotExist();
466+
}
467+
}
468+
415469
@NotNull
416470
private static RequestPatternBuilder projectVersionsRequest(String projectId) {
417471
return getRequestedFor(urlPathEqualTo("/v2/project/" + projectId + "/version"));

0 commit comments

Comments
 (0)