diff --git a/src/main/java/me/itzg/helpers/modrinth/ModrinthApiClient.java b/src/main/java/me/itzg/helpers/modrinth/ModrinthApiClient.java index 1dcacccf..224a7c0e 100644 --- a/src/main/java/me/itzg/helpers/modrinth/ModrinthApiClient.java +++ b/src/main/java/me/itzg/helpers/modrinth/ModrinthApiClient.java @@ -130,10 +130,8 @@ public Mono resolveProjectVersion(Project project, ProjectRef projectRe @Nullable Loader loader, String gameVersion, VersionType defaultVersionType) { - final Loader loaderToQuery = projectRef.isDatapack() ? Loader.datapack : loader; - if (projectRef.hasVersionName()) { - return getVersionsForProject(project.getId(), loaderToQuery, gameVersion) + return getVersionsForProject(project.getId(), loader, gameVersion) .flatMap(versions -> Mono.justOrEmpty(versions.stream() .filter(version -> @@ -144,7 +142,7 @@ public Mono resolveProjectVersion(Project project, ProjectRef projectRe )); } if (projectRef.hasVersionType()) { - return getVersionsForProject(project.getId(), loaderToQuery, gameVersion) + return getVersionsForProject(project.getId(), loader, gameVersion) .mapNotNull(versions -> pickVersion(project, versions, projectRef.getVersionType())); } else if (projectRef.hasVersionId()) { return getVersionFromId(projectRef.getVersionId()) @@ -153,7 +151,7 @@ public Mono resolveProjectVersion(Project project, ProjectRef projectRe projectRef.getVersionId(), project.getSlug())) ); } else { - return getVersionsForProject(project.getId(), loaderToQuery, gameVersion) + return getVersionsForProject(project.getId(), loader, gameVersion) .mapNotNull(versions -> pickVersion(project, versions, defaultVersionType)); } } diff --git a/src/main/java/me/itzg/helpers/modrinth/ModrinthCommand.java b/src/main/java/me/itzg/helpers/modrinth/ModrinthCommand.java index 87a646d1..58d6cf4a 100644 --- a/src/main/java/me/itzg/helpers/modrinth/ModrinthCommand.java +++ b/src/main/java/me/itzg/helpers/modrinth/ModrinthCommand.java @@ -39,34 +39,62 @@ import picocli.CommandLine.ExitCode; import picocli.CommandLine.Option; -@Command(name = "modrinth", description = "Automates downloading of modrinth resources") +@Command( + name = "modrinth", + description = "Automates downloading of modrinth resources" +) @Slf4j public class ModrinthCommand implements Callable { public static final String DATAPACKS_SUBDIR = "datapacks"; - @Option(names = "--projects", description = "Project ID or Slug", - split = SPLIT_COMMA_NL, splitSynopsisLabel = SPLIT_SYNOPSIS_COMMA_NL, - paramLabel = "id|slug" + + @Option( + names = "--projects", + description = "Project ID or Slug. Prefix with loader: e.g. fabric:project-id", + split = SPLIT_COMMA_NL, + splitSynopsisLabel = SPLIT_SYNOPSIS_COMMA_NL, + paramLabel = "[loader:]id|slug" ) List projects; - @Option(names = "--game-version", description = "Applicable Minecraft version", required = true) + @Option( + names = "--game-version", + description = "Applicable Minecraft version", + required = true + ) String gameVersion; - @Option(names = "--loader", required = true, description = "Valid values: ${COMPLETION-CANDIDATES}") + @Option( + names = "--loader", + required = true, + description = "Valid values: ${COMPLETION-CANDIDATES}" + ) Loader loader; - @Option(names = "--output-directory", defaultValue = ".", paramLabel = "DIR") + @Option( + names = "--output-directory", + defaultValue = ".", + paramLabel = "DIR" + ) Path outputDirectory; - @Option(names = "--download-dependencies", defaultValue = "NONE", - description = "Default is ${DEFAULT-VALUE}\nValid values: ${COMPLETION-CANDIDATES}") + @Option( + names = "--download-dependencies", + defaultValue = "NONE", + description = "Default is ${DEFAULT-VALUE}\nValid values: ${COMPLETION-CANDIDATES}" + ) DownloadDependencies downloadDependencies; - @Option(names = "--skip-existing", defaultValue = "${env:MODRINTH_SKIP_EXISTING}") + @Option( + names = "--skip-existing", + defaultValue = "${env:MODRINTH_SKIP_EXISTING}" + ) boolean skipExisting = true; - @Option(names = "--skip-up-to-date", defaultValue = "${env:MODRINTH_SKIP_UP_TO_DATE}") + @Option( + names = "--skip-up-to-date", + defaultValue = "${env:MODRINTH_SKIP_UP_TO_DATE}" + ) boolean skipUpToDate = true; public enum DownloadDependencies { @@ -75,18 +103,26 @@ public enum DownloadDependencies { /** * Implies {@link #REQUIRED} */ - OPTIONAL + OPTIONAL, } - @Option(names = "--allowed-version-type", defaultValue = "release", description = "Valid values: ${COMPLETION-CANDIDATES}") + @Option( + names = "--allowed-version-type", + defaultValue = "release", + description = "Valid values: ${COMPLETION-CANDIDATES}" + ) VersionType defaultVersionType; - @Option(names = "--api-base-url", defaultValue = "${env:MODRINTH_API_BASE_URL:-https://api.modrinth.com}", + @Option( + names = "--api-base-url", + defaultValue = "${env:MODRINTH_API_BASE_URL:-https://api.modrinth.com}", description = "Default: ${DEFAULT-VALUE}" ) String baseUrl; - @Option(names = "--world-directory", defaultValue = "${env:LEVEL:-world}", + @Option( + names = "--world-directory", + defaultValue = "${env:LEVEL:-world}", description = "Used for datapacks, a path relative to the output directory or an absolute path\nDefault: ${DEFAULT-VALUE}" ) Path worldDirectory; @@ -94,7 +130,8 @@ public enum DownloadDependencies { @ArgGroup(exclusive = false) SharedFetchArgs sharedFetchArgs = new SharedFetchArgs(); - final Set projectsProcessed = Collections.synchronizedSet(new HashSet<>()); + final Set projectsProcessed = + Collections.synchronizedSet(new HashSet<>()); @Override public Integer call() throws Exception { @@ -117,34 +154,48 @@ public Integer call() throws Exception { } private List processProjects(List projects) { - try (ModrinthApiClient modrinthApiClient = new ModrinthApiClient(baseUrl, "modrinth", sharedFetchArgs.options())) { + try ( + ModrinthApiClient modrinthApiClient = new ModrinthApiClient( + baseUrl, + "modrinth", + sharedFetchArgs.options() + ) + ) { //noinspection DataFlowIssue since it thinks block() may return null - return - modrinthApiClient.bulkGetProjects( - projects.stream() + return modrinthApiClient + .bulkGetProjects( + projects + .stream() .filter(s -> !s.trim().isEmpty()) .map(ProjectRef::parse) ) .defaultIfEmpty(Collections.emptyList()) .block() .stream() - .flatMap(resolvedProject -> processProject( - modrinthApiClient, resolvedProject.getProjectRef(), resolvedProject.getProject() - )) + .flatMap(resolvedProject -> + processProject( + modrinthApiClient, + resolvedProject.getProjectRef(), + resolvedProject.getProject() + ) + ) .collect(Collectors.toList()); } } private ModrinthManifest loadManifest() throws IOException { - final Path legacyManifestPath = outputDirectory.resolve(LegacyModrinthManifest.FILENAME); + final Path legacyManifestPath = outputDirectory.resolve( + LegacyModrinthManifest.FILENAME + ); if (Files.exists(legacyManifestPath)) { final ObjectMapper objectMapper = ObjectMappers.defaultMapper(); - final LegacyModrinthManifest legacyManifest = objectMapper.readValue( - legacyManifestPath.toFile(), - LegacyModrinthManifest.class - ); + final LegacyModrinthManifest legacyManifest = + objectMapper.readValue( + legacyManifestPath.toFile(), + LegacyModrinthManifest.class + ); Files.delete(legacyManifestPath); @@ -154,12 +205,24 @@ private ModrinthManifest loadManifest() throws IOException { .build(); } - return Manifests.load(outputDirectory, ModrinthManifest.ID, ModrinthManifest.class); + return Manifests.load( + outputDirectory, + ModrinthManifest.ID, + ModrinthManifest.class + ); } - private Stream expandDependencies(ModrinthApiClient modrinthApiClient, Project project, Version version) { + private Stream expandDependencies( + ModrinthApiClient modrinthApiClient, + Loader loader, + String gameVersion, + Project project, + Version version + ) { log.debug("Expanding dependencies of version={}", version); - return version.getDependencies().stream() + return version + .getDependencies() + .stream() .filter(this::filterDependency) .filter(dep -> projectsProcessed.add(dep.getProjectId())) .flatMap(dep -> { @@ -168,40 +231,71 @@ private Stream expandDependencies(ModrinthApiClient modrinthApiClient, final Version depVersion; try { if (dep.getVersionId() == null) { - log.debug("Fetching versions of dep={} and picking", dep); + log.debug( + "Fetching versions of dep={} and picking", + dep + ); depVersion = pickVersion( - getVersionsForProject(modrinthApiClient, dep.getProjectId()) + getVersionsForProject( + modrinthApiClient, + dep.getProjectId(), + loader, + gameVersion + ) ); - } - else { + } else { log.debug("Fetching version for dep={}", dep); - depVersion = modrinthApiClient.getVersionFromId(dep.getVersionId()) + depVersion = modrinthApiClient + .getVersionFromId(dep.getVersionId()) .block(); } } catch (GenericException e) { - throw new GenericException(String.format("Failed to expand %s of project '%s'", - dep, project.getTitle()), e); + throw new GenericException( + String.format( + "Failed to expand %s of project '%s'", + dep, + project.getTitle() + ), + e + ); } catch (NoFilesAvailableException e) { throw new InvalidParameterException( - String.format("No matching files for %s of project '%s': %s", - dep, project.getTitle(), e.getMessage() - ), e + String.format( + "No matching files for %s of project '%s': %s", + dep, + project.getTitle(), + e.getMessage() + ), + e ); } if (depVersion != null) { - log.debug("Resolved version={} for dep={}", depVersion.getVersionNumber(), dep); + log.debug( + "Resolved version={} for dep={}", + depVersion.getVersionNumber(), + dep + ); return Stream.concat( - Stream.of(depVersion), - expandDependencies(modrinthApiClient, project, depVersion) + Stream.of(depVersion), + expandDependencies( + modrinthApiClient, + loader, + gameVersion, + project, + depVersion ) - .peek(expandedVer -> log.debug("Expanded dependency={} into version={}", dep, expandedVer)); - } - else { + ).peek(expandedVer -> + log.debug( + "Expanded dependency={} into version={}", + dep, + expandedVer + ) + ); + } else { return Stream.empty(); } }); - } private boolean filterDependency(VersionDependency dep) { @@ -209,10 +303,12 @@ private boolean filterDependency(VersionDependency dep) { return false; } - return (downloadDependencies == DownloadDependencies.REQUIRED && dep.getDependencyType() == DependencyType.required) - || ( - downloadDependencies == DownloadDependencies.OPTIONAL - && (dep.getDependencyType() == DependencyType.required || dep.getDependencyType() == DependencyType.optional) + return ( + (downloadDependencies == DownloadDependencies.REQUIRED && + dep.getDependencyType() == DependencyType.required) || + (downloadDependencies == DownloadDependencies.OPTIONAL && + (dep.getDependencyType() == DependencyType.required || + dep.getDependencyType() == DependencyType.optional)) ); } @@ -220,7 +316,10 @@ private Version pickVersion(List versions) { return this.pickVersion(versions, defaultVersionType); } - private Version pickVersion(List versions, VersionType versionType) { + private Version pickVersion( + List versions, + VersionType versionType + ) { for (final Version version : versions) { if (version.getVersionType().sufficientFor(versionType)) { return version; @@ -229,33 +328,34 @@ private Version pickVersion(List versions, VersionType versionType) { return null; } - private Path download(boolean isDatapack, VersionFile versionFile) { + private Path download(Loader loader, VersionFile versionFile) { final Path outPath; try { - if (!isDatapack) { - outPath = Files.createDirectories(outputDirectory - .resolve(loader.getType()) - ) - .resolve(versionFile.getFilename()); - } - else { + final Loader effectiveLoader = loader != null + ? loader + : this.loader; + final String outputType = effectiveLoader.getType(); + + if (outputType == null) { + // Datapack case if (worldDirectory.isAbsolute()) { - outPath = Files.createDirectories(worldDirectory - .resolve(DATAPACKS_SUBDIR) - ) - .resolve(versionFile.getFilename()); - } - else { - outPath = Files.createDirectories(outputDirectory + outPath = Files.createDirectories( + worldDirectory.resolve(DATAPACKS_SUBDIR) + ).resolve(versionFile.getFilename()); + } else { + outPath = Files.createDirectories( + outputDirectory .resolve(worldDirectory) .resolve(DATAPACKS_SUBDIR) - ) - .resolve(versionFile.getFilename()); + ).resolve(versionFile.getFilename()); } + } else { + outPath = Files.createDirectories( + outputDirectory.resolve(outputType) + ).resolve(versionFile.getFilename()); } - } catch (IOException e) { - throw new RuntimeException("Creating mods directory", e); + throw new RuntimeException("Creating output directory", e); } try { @@ -267,75 +367,112 @@ private Path download(boolean isDatapack, VersionFile versionFile) { .handleStatus(Fetch.loggingDownloadStatusHandler(log)) .execute(); } catch (IOException e) { - throw new RuntimeException("Downloading mod file", e); + throw new RuntimeException("Downloading file", e); } } - private List getVersionsForProject(ModrinthApiClient modrinthApiClient, String project) { - final List versions = modrinthApiClient.getVersionsForProject( - project, loader, gameVersion - ) + private List getVersionsForProject( + ModrinthApiClient modrinthApiClient, + String project, + Loader loader, + String gameVersion + ) { + final List versions = modrinthApiClient + .getVersionsForProject(project, loader, gameVersion) .block(); if (versions == null) { - throw new GenericException("Unable to retrieve versions for project " + project); + throw new GenericException( + "Unable to retrieve versions for project " + project + ); } return versions; } - - private Stream processProject(ModrinthApiClient modrinthApiClient, ProjectRef projectRef, Project project) { + private Stream processProject( + ModrinthApiClient modrinthApiClient, + ProjectRef projectRef, + Project project + ) { if (project.getProjectType() != ProjectType.mod) { throw new InvalidParameterException( - String.format("Requested project '%s' is not a mod, but has type %s", - project.getTitle(), project.getProjectType() - )); + String.format( + "Requested project '%s' is not a mod, but has type %s", + project.getTitle(), + project.getProjectType() + ) + ); } - log.debug("Starting with project='{}' slug={}", project.getTitle(), project.getSlug()); + log.debug( + "Starting with project='{}' slug={}", + project.getTitle(), + project.getSlug() + ); if (projectsProcessed.add(project.getId())) { + final Loader effectiveLoader = projectRef.getLoader() != null + ? projectRef.getLoader() + : this.loader; + final Version version; try { - version = modrinthApiClient.resolveProjectVersion( - project, projectRef, loader, gameVersion, defaultVersionType + version = modrinthApiClient + .resolveProjectVersion( + project, + projectRef, + effectiveLoader, + gameVersion, + defaultVersionType ) .block(); - } catch (NoApplicableVersionsException | NoFilesAvailableException e) { + } catch ( + NoApplicableVersionsException | NoFilesAvailableException e + ) { throw new InvalidParameterException(e.getMessage(), e); } if (version != null) { if (version.getFiles().isEmpty()) { - throw new GenericException(String.format("Project %s has no files declared", project.getSlug())); + throw new GenericException( + String.format( + "Project %s has no files declared", + project.getSlug() + ) + ); } - final boolean isDatapack = isDatapack(version); - return Stream.concat( - Stream.of(version), - expandDependencies(modrinthApiClient, project, version) + Stream.of(version), + expandDependencies( + modrinthApiClient, + effectiveLoader, + gameVersion, + project, + version ) + ) .map(ModrinthApiClient::pickVersionFile) - .map(versionFile -> download(isDatapack, versionFile)) - .flatMap(downloadedFile -> !isDatapack ? expandIfZip(downloadedFile) : Stream.empty()); - } - else { + .map(versionFile -> download(effectiveLoader, versionFile)) + .flatMap(downloadedFile -> { + // Only expand ZIPs for non-datapack loaders + return effectiveLoader == Loader.datapack + ? Stream.of(downloadedFile) + : expandIfZip(downloadedFile); + }); + } else { throw new InvalidParameterException( - String.format("Project %s does not have any matching versions for loader %s, game version %s", - projectRef, loader, gameVersion - )); + String.format( + "Project %s does not have any matching versions for loader %s, game version %s", + projectRef, + effectiveLoader, + gameVersion + ) + ); } } return Stream.empty(); } - private boolean isDatapack(Version version) { - return - version.getLoaders() != null - && version.getLoaders().size() == 1 - && version.getLoaders().get(0).equals(Constants.LOADER_DATAPACK); - } - /** * If downloadedFile ends in .zip, then expand it, return its files and given file. * @@ -347,8 +484,7 @@ private Stream expandIfZip(Path downloadedFile) { Stream.of(downloadedFile), expandZip(downloadedFile) ); - } - else { + } else { return Stream.of(downloadedFile); } } @@ -359,7 +495,11 @@ private Stream expandZip(Path zipFile) { final ArrayList contents = new ArrayList<>(); - try (ZipInputStream zipIn = new ZipInputStream(Files.newInputStream(zipFile))) { + try ( + ZipInputStream zipIn = new ZipInputStream( + Files.newInputStream(zipFile) + ) + ) { ZipEntry entry; while ((entry = zipIn.getNextEntry()) != null) { if (!entry.isDirectory()) { @@ -371,8 +511,7 @@ private Stream expandZip(Path zipFile) { Files.createDirectories(resolved.getParent()); } Files.copy(zipIn, resolved); - } - else { + } else { log.debug("File={} from zip already exists", resolved); } contents.add(resolved); diff --git a/src/main/java/me/itzg/helpers/modrinth/ProjectRef.java b/src/main/java/me/itzg/helpers/modrinth/ProjectRef.java index 7dfb780d..fb2187e8 100644 --- a/src/main/java/me/itzg/helpers/modrinth/ProjectRef.java +++ b/src/main/java/me/itzg/helpers/modrinth/ProjectRef.java @@ -7,8 +7,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import lombok.Getter; import lombok.ToString; import me.itzg.helpers.errors.InvalidParameterException; @@ -22,10 +25,13 @@ public class ProjectRef { private static final Pattern MODPACK_PAGE_URL = Pattern.compile( "https://modrinth.com/modpack/(?.+?)(/version/(?.+))?" ); - private static final Pattern PROJECT_REF = Pattern.compile("(?datapack:)?(?[^:]+?)(:(?[^:]+))?"); + private static final Set VALID_LOADERS = Arrays.stream(Loader.values()) + .map(Enum::name) + .map(String::toLowerCase) + .collect(Collectors.toSet()); private final String idOrSlug; - private final boolean datapack; + private final Loader loader; /** * Either a remote URI or a file URI for a locally provided file @@ -36,16 +42,39 @@ public class ProjectRef { private final String versionNumber; public static ProjectRef parse(String projectRef) { - final Matcher m = PROJECT_REF.matcher(projectRef); - if (!m.matches()) { - throw new InvalidParameterException("Invalid project reference: " + projectRef); + final String[] parts = projectRef.split(":", 3); + + // Handle cases with no colon + if (parts.length == 1) { + return new ProjectRef(parts[0], null, null); } - - return new ProjectRef( - m.group("idSlug"), - m.group("version"), - m.group("datapack") != null - ); + + // Check if first part is a valid loader + Loader loader = null; + int idIndex = 0; + if (VALID_LOADERS.contains(parts[0].toLowerCase())) { + loader = Loader.valueOf(parts[0].toLowerCase()); + idIndex = 1; + } + + // Handle remaining parts + if (parts.length == 2) { + // Either loader:id or id:version + if (loader != null) { + return new ProjectRef(parts[1], null, loader); + } else { + return new ProjectRef(parts[0], parts[1], null); + } + } + else if (parts.length == 3) { + // Must be loader:id:version + if (loader == null) { + throw new InvalidParameterException("Invalid loader in project reference: " + parts[0]); + } + return new ProjectRef(parts[1], parts[2], loader); + } + + throw new InvalidParameterException("Invalid project reference: " + projectRef); } /** @@ -53,15 +82,15 @@ public static ProjectRef parse(String projectRef) { * @param version can be a {@link VersionType}, ID, or name/number */ public ProjectRef(String projectSlug, String version) { - this(projectSlug, version, false); + this(projectSlug, version, null); } /** * @param version can be a {@link VersionType}, ID, or name/number */ - public ProjectRef(String projectSlug, @Nullable String version, boolean datapack) { + public ProjectRef(String projectSlug, @Nullable String version, Loader loader) { this.idOrSlug = projectSlug; - this.datapack = datapack; + this.loader = loader; this.projectUri = null; this.versionType = parseVersionType(version); if (this.versionType == null) { @@ -81,7 +110,7 @@ public ProjectRef(String projectSlug, @Nullable String version, boolean datapack } public ProjectRef(URI projectUri, String versionId) { - this.datapack = false; + this.loader = null; this.projectUri = projectUri; final String filename = extractFilename(projectUri); @@ -103,37 +132,40 @@ public static ProjectRef fromPossibleUrl( String possibleUrl, String defaultVersion) { // First, see if it is a modrinth page URL - - final Matcher m = MODPACK_PAGE_URL.matcher(possibleUrl); - if(m.matches()) { - String projectSlug = m.group("slug"); - String projectVersion = m.group("versionName") != null ? - m.group("versionName") : defaultVersion; - return new ProjectRef(projectSlug, projectVersion); - } else { - try { - // Might be custom URL, local file, or slug - // ...try as a (remote or file) URL first - return new ProjectRef( - new URL(possibleUrl).toURI(), defaultVersion - ); - } catch(MalformedURLException | URISyntaxException e) { - // Not a valid URL, so - // narrow down if it is a file path by looking at suffix - if (possibleUrl.endsWith(".mrpack")) { - final Path path = Paths.get(possibleUrl); - if (!Files.exists(path)) { - throw new InvalidParameterException("Given modrinth project looks like a file, but doesn't exist"); - } - + try { + final Matcher m = MODPACK_PAGE_URL.matcher(possibleUrl); + if(m.matches()) { + String projectSlug = m.group("slug"); + String projectVersion = m.group("versionName") != null ? + m.group("versionName") : defaultVersion; + return new ProjectRef(projectSlug, projectVersion); + } else { + try { + // Might be custom URL, local file, or slug + // ...try as a (remote or file) URL first return new ProjectRef( - path.toUri(), - defaultVersion + new URL(possibleUrl).toURI(), defaultVersion ); - } + } catch(MalformedURLException | URISyntaxException e) { + // Not a valid URL, so + // narrow down if it is a file path by looking at suffix + if (possibleUrl.endsWith(".mrpack")) { + final Path path = Paths.get(possibleUrl); + if (!Files.exists(path)) { + throw new InvalidParameterException("Given modrinth project looks like a file, but doesn't exist"); + } + + return new ProjectRef( + path.toUri(), + defaultVersion + ); + } - return new ProjectRef(possibleUrl, defaultVersion); + return new ProjectRef(possibleUrl, defaultVersion); + } } + } catch (Exception e) { + throw new InvalidParameterException("Invalid project reference: " + possibleUrl, e); } } diff --git a/src/test/java/me/itzg/helpers/modrinth/ModrinthCommandTest.java b/src/test/java/me/itzg/helpers/modrinth/ModrinthCommandTest.java index 29032f76..bc77a237 100644 --- a/src/test/java/me/itzg/helpers/modrinth/ModrinthCommandTest.java +++ b/src/test/java/me/itzg/helpers/modrinth/ModrinthCommandTest.java @@ -311,7 +311,7 @@ void handlesDatapacksSpecificVersion(boolean absoluteWorldDir, @TempDir Path tem tempDir.resolve(worldDir).toString() : worldDir, "--game-version", "1.21.1", - "--loader", "datapack", + "--loader", "paper", "--projects", String.format("datapack:%s:%s", projectId, versionId) ); @@ -496,4 +496,4 @@ private static void setupStubs() { ) ); } -} \ No newline at end of file +} diff --git a/src/test/java/me/itzg/helpers/modrinth/ProjectRefTest.java b/src/test/java/me/itzg/helpers/modrinth/ProjectRefTest.java index d40e45cb..d544c37a 100644 --- a/src/test/java/me/itzg/helpers/modrinth/ProjectRefTest.java +++ b/src/test/java/me/itzg/helpers/modrinth/ProjectRefTest.java @@ -139,22 +139,22 @@ void constructorPullsProjectSlugFromFileURI(String input) { @ParameterizedTest @MethodSource("parseProjectRef_parameters") - void parseProjectRef(String input, String slugId, VersionType versionType, String versionId, String versionName, boolean datapack) { + void parseProjectRef(String input, String slugId, VersionType versionType, String versionId, String versionName, Loader loader) { final ProjectRef result = ProjectRef.parse(input); assertThat(result.getIdOrSlug()).isEqualTo(slugId); assertThat(result.getVersionType()).isEqualTo(versionType); assertThat(result.getVersionId()).isEqualTo(versionId); assertThat(result.getVersionNumber()).isEqualTo(versionName); - assertThat(result.isDatapack()).isEqualTo(datapack); + assertThat(result.getLoader()).isEqualTo(loader); } public static Stream parseProjectRef_parameters() { return Stream.of( - argumentSet("just slugId","terralith", "terralith", null, null, null, false), - argumentSet("datapack","datapack:terralith", "terralith", null, null, null, true), - argumentSet("with version ID","terralith:rEF3UnUI", "terralith", null, "rEF3UnUI", null, false), - argumentSet("with version type","terralith:release", "terralith", VersionType.release, null, null, false), - argumentSet("with version name","terralith:2.5.5", "terralith", null, null, "2.5.5", false) + argumentSet("just slugId","terralith", "terralith", null, null, null, null), + argumentSet("with loader prefix","fabric:terralith", "terralith", null, null, null, Loader.fabric), + argumentSet("with loader and version ID","paper:terralith:rEF3UnUI", "terralith", null, "rEF3UnUI", null, Loader.paper), + argumentSet("with loader and version type","datapack:terralith:release", "terralith", VersionType.release, null, null, Loader.datapack), + argumentSet("with loader and version name","forge:terralith:2.5.5", "terralith", null, null, "2.5.5", Loader.forge) ); } }