diff --git a/.vscode/settings.json b/.vscode/settings.json index 7686efc..388fa65 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,8 @@ "**/.DS_Store": true, "**/Thumbs.db": true, "nimcache/": true, - "testresults/": true + "testresults/": true, + "tests/**/*.exe": true }, "nim.nimprettyIndent": 2 } diff --git a/pax.nimble b/pax.nimble index 14ad6e2..2ef390d 100644 --- a/pax.nimble +++ b/pax.nimble @@ -11,7 +11,7 @@ bin = @["pax"] # Dependencies -requires "nim >= 1.4.6" +requires "nim >= 1.6.4" requires "regex >= 0.19.0" requires "therapist >= 0.2.0" requires "zippy >= 0.6.2" diff --git a/src/api/cfclient.nim b/src/api/cfclient.nim index 4a41f65..1fc4042 100644 --- a/src/api/cfclient.nim +++ b/src/api/cfclient.nim @@ -1,4 +1,4 @@ -## Provides functions for connecting to the CF proxy [https://github.com/bmpm-mc/cfproxy]. +## Provides functions for connecting to the CF proxy [https://cfproxy.bmpm.workers.dev]. ## ## The proxy connects to the official API internally, and has capabilities like: ## - Searching for a addon. @@ -8,53 +8,92 @@ ## Docs for the official API are available at https://docs.curseforge.com. ## Requests to the proxy stay the same, except the base URL is switched out. -import asyncdispatch, json, options, strutils +import std/[asyncdispatch, json, options, sequtils, strutils, sugar, tables] import uri except Url import cfcore, http const ## base url of the cfproxy endpoint - addonsBaseUrl = "https://cfproxy.fly.dev" + addonsBaseUrl = "https://cfproxy.bmpm.workers.dev" ## base url of the curse metadata api endpoint ## used for retrieving mods by their slug, which isn't possible with the curse api addonsSlugBaseUrl = "https://curse.nikky.moe/graphql" +type + CfClientError* = object of HttpRequestError + +proc sortTo[T, X](s: seq[T], x: seq[X], pred: proc (x: T): X): seq[T] = + ## sort `s` so that the order of its items matches `x`. + ## `pred` should be a function that returns a unique value to which `s` is sorted. + assert s.len == x.len + + var table = initTable[X, T]() + for sItem in s: + table[pred(sItem)] = sItem + for xItem in x: + result.add(table[xItem]) + proc fetchAddonsByQuery*(query: string, category: Option[CfAddonGameCategory]): Future[seq[CfAddon]] {.async.} = ## retrieves all addons that match the given `query` search and `category`. let encodedQuery = encodeUrl(query, usePlus = false) var url = addonsBaseUrl & "/v1/mods/search?gameId=432&pageSize=50&sortField=6&sortOrder=desc&searchFilter=" & encodedQuery if category.isSome: url = url & "&classId=" & $ord(category.get()) - try: - return get(url.Url).await.parseJson["data"].addonsFromForgeSvc - except HttpRequestError: - return @[] + return get(url.Url).await.parseJson["data"].addonsFromForgeSvc + +proc fetchAddonsByQuery*(query: string, category: CfAddonGameCategory): Future[seq[CfAddon]] = + ## retrieves all addons that match the given `query` search and `category`. + return fetchAddonsByQuery(query, category = some(category)) -proc fetchAddonsByQuery*(query: string): Future[seq[CfAddon]] {.async.} = - return await fetchAddonsByQuery(query, category = none[CfAddonGameCategory]()) +proc fetchAddonsByQuery*(query: string): Future[seq[CfAddon]] = + ## retrieves all addons that match the given `query` search. + return fetchAddonsByQuery(query, category = none[CfAddonGameCategory]()) -proc fetchAddon*(projectId: int): Future[Option[CfAddon]] {.async.} = +proc fetchAddon*(projectId: int): Future[CfAddon] {.async.} = ## get the addon with the given `projectId`. let url = addonsBaseUrl & "/v1/mods/" & $projectId try: - return get(url.Url).await.parseJson["data"].addonFromForgeSvc.some + return get(url.Url).await.parseJson["data"].addonFromForgeSvc except HttpRequestError: - return none[CfAddon]() + raise newException(CfClientError, "addon with project id '" & $projectId & "' not found.") + +proc fetchAddons*(projectIds: seq[int], chunk = true): Future[seq[CfAddon]] {.async.} = + ## get all addons with their given `projectId`. + ## + ## chunks the projectIds to minimize request size and to pinpoint errors better. + if projectIds.len > 10 and chunk: + let futures: seq[Future[seq[CfAddon]]] = collect: + for chunkedIds in projectIds.distribute(int(projectIds.len / 10), spread = true): + fetchAddons(chunkedIds, chunk = false) + let addons: seq[seq[CfAddon]] = await all(futures) + return collect: + for addonSeq in addons: + for addon in addonSeq: + addon + else: + let url = addonsBaseUrl & "/v1/mods/" + let body = %* { "modIds": projectIds } + try: + let addons = post(url.Url, $body).await.parseJson["data"].addonsFromForgeSvc + if addons.len != projectIds.len: + raise newException(CfClientError, "one of the addons of project ids '" & $projectIds & "' was not found.") + return addons.sortTo(projectIds, (x) => x.projectId) + except HttpRequestError: + let futures: seq[Future[CfAddon]] = collect: + for projectId in projectIds: + fetchAddon(projectId) + return await all(futures) -proc fetchAddon*(slug: string): Future[Option[CfAddon]] {.async.} = +proc fetchAddon*(slug: string): Future[CfAddon] {.async.} = ## get the addon matching the `slug`. let reqBody = %* { "query": "{ addons(slug: \"" & slug & "\") { id }}" } let curseProxyInfo = await post(addonsSlugBaseUrl.Url, body = $reqBody) - var projectId: int - try: - let addons = curseProxyInfo.parseJson["data"]["addons"] - if addons.len == 0: - return none[CfAddon]() - projectId = addons[0]["id"].getInt() - except KeyError: - return none[CfAddon]() + let addons = curseProxyInfo.parseJson["data"]["addons"] + if addons.len == 0: + raise newException(CfClientError, "addon with slug '" & slug & "' not found") + let projectId = addons[0]["id"].getInt() return await fetchAddon(projectId) proc fetchAddonFiles*(projectId: int): Future[seq[CfAddonFile]] {.async.} = @@ -63,12 +102,24 @@ proc fetchAddonFiles*(projectId: int): Future[seq[CfAddonFile]] {.async.} = try: return get(url.Url).await.parseJson["data"].addonFilesFromForgeSvc except HttpRequestError: - return @[] + raise newException(CfClientError, "addon with project id '" & $projectId & "' not found.") + +proc fetchAddonFiles*(fileIds: seq[int]): Future[seq[CfAddonFile]] {.async.} = + ## get all addon files with their given `fileIds`. + let url = addonsBaseUrl & "/v1/mods/files" + let body = %* { "fileIds": fileIds } + try: + let addonFiles = post(url.Url, $body).await.parseJson["data"].addonFilesFromForgeSvc + if addonFiles.len != fileIds.len: + raise newException(CfClientError, "one of the addon files of file ids '" & $fileIds & "' was not found.") + return addonFiles.sortTo(fileIds, (x) => x.fileId) + except HttpRequestError: + raise newException(CfClientError, "one of the addon files of file ids '" & $fileIds & "' was not found.") -proc fetchAddonFile*(projectId: int, fileId: int): Future[Option[CfAddonFile]] {.async.} = +proc fetchAddonFile*(projectId: int, fileId: int): Future[CfAddonFile] {.async.} = ## get the addon file with the given `fileId` & `projectId`. let url = addonsBaseUrl & "/v1/mods/" & $projectId & "/files/" & $fileId try: - return get(url.Url).await.parseJson["data"].addonFileFromForgeSvc.some + return get(url.Url).await.parseJson["data"].addonFileFromForgeSvc except HttpRequestError: - return none[CfAddonFile]() + raise newException(CfClientError, "addon with project & file id '" & $projectId & ':' & $fileId & "' not found.") diff --git a/src/api/cfcore.nim b/src/api/cfcore.nim index 7956613..182ecb4 100644 --- a/src/api/cfcore.nim +++ b/src/api/cfcore.nim @@ -1,11 +1,14 @@ -## Provides the types returned by the `cfclient` module. +## Provides the types returned by the Curseforge API. ## ## Curseforge has two main entities: -## - Addons, which are modifications to the source game in one way or another. -## In Minecraft, mods are one type of CF addon, resourcepacks are another. -## - Addon files, which are files attached to one addon and can be seen of versions of an addon. +## - Addons (https://docs.curseforge.com/#search-mods), +## which are modifications to the source game in one way or another. +## For Minecraft, mods are one type of CF addon, resourcepacks are another. +## - Addon files (https://docs.curseforge.com/#curseforge-core-api-files), +## which are files attached to an addon and can be seen as versions of an addon. -import json, regex, sequtils, strutils, sugar +import std/[json, sequtils, strutils, sugar] +import regex import ../modpack/version type diff --git a/src/api/http.nim b/src/api/http.nim index 68a84ca..899a1eb 100644 --- a/src/api/http.nim +++ b/src/api/http.nim @@ -1,7 +1,7 @@ ## A simple wrapper for the `httpclient` module. ## Used for convenience over creating a `newAsyncHttpClient()` instance. -import asyncdispatch, httpclient, os +import std/[asyncdispatch, httpclient, os] export HttpRequestError let @@ -17,24 +17,24 @@ type proc `$`(v: Url): string {.borrow.} -proc getHttpClient(): AsyncHttpClient = +template getHttpClient(): AsyncHttpClient = ## returns an async http client using the proxy (if it exists). let http = case proxy: of "": newAsyncHttpClient() else: newAsyncHttpClient(proxy = newProxy(proxy)) http.headers = newHttpHeaders({"Content-Type": "application/json"}) - return http + http -proc get*(url: Url): Future[string] {.async.} = +proc get*(url: Url): Future[string] = ## creates a GET request targeting the given `url`. ## throws OSError or HttpRequestError if the request failed. ## returns the body of the response. let http = getHttpClient() - return await http.getContent($url) + result = http.getContent($url) -proc post*(url: Url, body: string = ""): Future[string] {.async.} = +proc post*(url: Url, body: string = ""): Future[string] = ## creates a POST request targeting the given `url`, with an optional `body`. ## throws OSError or HttpRequestError if the request failed. ## returns the body of the response. let http = getHttpClient() - return await http.postContent($url, body) + result = http.postContent($url, body) diff --git a/src/api/metadata.nim b/src/api/metadata.nim index 99406df..b15acb1 100644 --- a/src/api/metadata.nim +++ b/src/api/metadata.nim @@ -1,11 +1,11 @@ ## Provides `getModLoaderId` which retrieves the modloader id (a string specifying -## the type & version of the modloader) given a minecraft version and modloader. +## the type & version of the modloader) given a minecraft version and type of modloader. ## ## Pax currently has support for the Forge & Fabric modloader. The information about ## what loader version corresponds to what minecraft version is retrieved online ## and should be generally up-to-date 99% of the time. -import asyncdispatch, json, options, strutils, sugar +import std/[asyncdispatch, json, strutils] import http import ../modpack/version, ../modpack/loader @@ -13,32 +13,36 @@ const ## base url of the fabric metadata endpoint fabricBaseUrl = "https://meta.fabricmc.net/v2/versions/loader/" ## base url of the curse metadata api endpoint - forgeBaseUrl = "http://raw.githubusercontent.com/MultiMC/meta-upstream/master/forge/derived_index.json" + forgeBaseUrl = "https://cfproxy.fly.dev/v1/minecraft/modloader" -proc getFabricLoaderVersion(mcVersion: Version): Future[Option[string]] {.async.} = +type + MetadataClientError* = object of HttpRequestError + +proc getFabricLoaderVersion(mcVersion: Version): Future[string] {.async.} = ## get the fabric loader version fitting for the given minecraft version let url = fabricBaseUrl & $mcVersion - var json: JsonNode - try: - json = get(url.Url).await.parseJson + let json: JsonNode = try: + get(url.Url).await.parseJson except HttpRequestError: - return none[string]() + raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.") let loaderElems = json.getElems() if loaderElems.len == 0: - return none[string]() + raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.") let ver = loaderElems[0]["loader"]["version"].getStr() - return some(ver) + return ver -proc getForgeLoaderVersion(mcVersion: Version, latest: bool): Future[Option[string]] {.async.} = +proc getForgeLoaderVersion(mcVersion: Version, latest: bool): Future[string] {.async.} = ## get the forge loader version fitting for the given minecraft version - let json = get(forgeBaseUrl.Url).await.parseJson - let recommendedVersion = json{"by_mcversion", $mcVersion, "recommended"}.getStr() - let latestVersion = json{"by_mcversion", $mcVersion, "latest"}.getStr() - let forgeVersion = if latest: - latestVersion - else: - if $recommendedVersion != "": recommendedVersion else: latestVersion - return if forgeVersion != "": some(forgeVersion) else: none[string]() + let url = forgeBaseUrl & "?version=" & $mcVersion + let json: JsonNode = try: + get(url.Url).await.parseJson + except HttpRequestError: + raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.") + let searchKey = if latest: "latest" else: "recommended" + for item in json["data"].items(): + if item[searchKey].getBool(): + return item["name"].getStr() + raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.") proc toModloaderId(loaderVersion: string, loader: Loader): string = ## get the modloader id fitting for the given loader version and loader @@ -46,9 +50,9 @@ proc toModloaderId(loaderVersion: string, loader: Loader): string = of Loader.Forge: "forge-" & loaderVersion.split("-")[1] of Loader.Fabric: "fabric-" & loaderVersion -proc getModloaderId*(mcVersion: Version, loader: Loader, latest: bool = false): Future[Option[string]] {.async.} = +proc getModloaderId*(mcVersion: Version, loader: Loader, latest: bool = false): Future[string] {.async.} = ## get the modloader id fitting for the given minecraft version and loader let loaderVersion = case loader: of Loader.Forge: await mcVersion.getForgeLoaderVersion(latest) - of Loader.Fabric: await mcVersion.getFabricLoaderVersion() - return loaderVersion.map((x) => toModloaderId(x, loader)) \ No newline at end of file + of Loader.Fabric: mcVersion.getFabricLoaderVersion().await.toModloaderId(loader) + return loaderVersion \ No newline at end of file diff --git a/src/cmd/add.nim b/src/cmd/add.nim index 0a64069..b57c8bd 100644 --- a/src/cmd/add.nim +++ b/src/cmd/add.nim @@ -1,8 +1,8 @@ -import asyncdispatch, options, strscans +import std/[asyncdispatch, options, strscans] import common -import ../api/cfclient, ../api/cfcore -import ../modpack/install, ../modpack/manifest -import ../term/log, ../term/prompt +import ../api/[cfclient, cfcore] +import ../modpack/[install, manifest] +import ../term/[log, prompt] import ../util/flow proc addDependencies(manifest: var Manifest, file: ManifestFile, strategy: string): void = @@ -13,17 +13,13 @@ proc addDependencies(manifest: var Manifest, file: ManifestFile, strategy: strin let mcMod = fetchAddon(id) let mcModFiles = fetchAddonFiles(id) waitFor(mcMod and mcModFiles) - let selectedMcModFile = mcModFiles.read().selectAddonFile(manifest, strategy) - if mcMod.read().isNone or selectedMcModFile.isNone: - echoError "Warning: unable to resolve dependencies." - quit(1) - let mcModFile = selectedMcModFile.get() - echoInfo "Installing ", mcMod.read().get().name.fgCyan, ".." + let mcModFile = mcModFiles.read().selectAddonFile(manifest.loader, manifest.mcVersion, strategy) + echoInfo "Installing ", mcMod.read().name.fgCyan, ".." let modToInstall = initManifestFile( projectId = id, fileId = mcModFile.fileId, metadata = initManifestMetadata( - name = mcMod.read().get().name, + name = mcMod.read().name, explicit = false, pinned = false, dependencies = mcModFile.dependencies @@ -55,64 +51,32 @@ proc paxAdd*(input: string, noDepends: bool, strategy: string, addonType: string if input.scanf("https://www.curseforge.com/minecraft/mc-mods/${strScan}/files/$i", slug, fileId): ## Curseforge URL with slug & fileId - let mcModOption = waitFor(fetchAddon(slug)) - if mcModOption.isNone: - echoError "This url is not correct." - quit(1) - mcMod = mcModOption.get() + mcMod = waitFor(fetchAddon(slug)) manifest.rejectInstalledAddon(mcMod.projectId) - let mcModFileOption = waitFor(fetchAddonFile(mcMod.projectId, fileId)) - if mcModOption.isNone: - echoError "This url is not correct." - quit(1) - mcModFile = mcModFileOption.get() + mcModFile = waitFor(fetchAddonFile(mcMod.projectId, fileId)) elif input.scanf("https://www.curseforge.com/minecraft/mc-mods/${strScan}", slug): ## Curseforge URL with slug - let mcModOption = waitFor(fetchAddon(slug)) - if mcModOption.isNone: - echoError "This url is not correct." - quit(1) - mcMod = mcModOption.get() + mcMod = waitFor(fetchAddon(slug)) manifest.rejectInstalledAddon(mcMod.projectId) echoDebug "Found mod ", mcMod.name.fgCyan, "." let mcModFiles = waitFor(fetchAddonFiles(mcMod.projectId)) - let selectedMcModFile = mcModFiles.selectAddonFile(manifest, strategy) - if selectedMcModFile.isNone: - echoError "No compatible version found." - quit(1) - mcModFile = selectedMcModFile.get() + mcModFile = mcModFiles.selectAddonFile(manifest.loader, manifest.mcVersion, strategy) elif input.scanf("$i#$i", projectId, fileId): ## Input in # format - let mcModOption = waitFor(fetchAddon(projectId)) - if mcModOption.isNone: - echoError "There exists no addon with the given projectId." - quit(1) - mcMod = mcModOption.get() + mcMod = waitFor(fetchAddon(projectId)) manifest.rejectInstalledAddon(mcMod.projectId) echoDebug "Found mod ", mcMod.name.fgCyan, "." - let mcModFileOption = waitFor(fetchAddonFile(mcMod.projectId, fileId)) - if mcModOption.isNone: - echoError "There exists no addon with the given fileId." - quit(1) - mcModFile = mcModFileOption.get() + mcModFile = waitFor(fetchAddonFile(mcMod.projectId, fileId)) elif input.scanf("$i", projectId): ## Input in format - let mcModOption = waitFor(fetchAddon(projectId)) - if mcModOption.isNone: - echoError "There exists no addon with the given projectId." - quit(1) - mcMod = mcModOption.get() + mcMod = waitFor(fetchAddon(projectId)) manifest.rejectInstalledAddon(mcMod.projectId) echoDebug "Found mod ", mcMod.name.fgCyan, "." let mcModFiles = waitFor(fetchAddonFiles(mcMod.projectId)) - let selectedMcModFile = mcModFiles.selectAddonFile(manifest, strategy) - if selectedMcModFile.isNone: - echoError "No compatible version found." - quit(1) - mcModFile = selectedMcModFile.get() + mcModFile = mcModFiles.selectAddonFile(manifest.loader, manifest.mcVersion, strategy) else: ## Just search normally @@ -124,19 +88,11 @@ proc paxAdd*(input: string, noDepends: bool, strategy: string, addonType: string else: none[CfAddonGameCategory]() let mcMods = waitFor(fetchAddonsByQuery(input, addonType)) - let mcModOption = manifest.promptAddonChoice(mcMods, selectInstalled = false) - if mcModOption.isNone: - echoError "No mods found for your search." - quit(1) - mcMod = mcModOption.get() + mcMod = manifest.promptAddonChoice(mcMods, selectInstalled = false) manifest.rejectInstalledAddon(mcMod.projectId) echoDebug "Found mod ", mcMod.name.fgCyan, "." let mcModFiles = waitFor(fetchAddonFiles(mcMod.projectId)) - let selectedMcModFile = mcModFiles.selectAddonFile(manifest, strategy) - if selectedMcModFile.isNone: - echoError "No compatible version found." - quit(1) - mcModFile = selectedMcModFile.get() + mcModFile = mcModFiles.selectAddonFile(manifest.loader, manifest.mcVersion, strategy) echo "" echoRoot "SELECTED MOD".dim diff --git a/src/cmd/common.nim b/src/cmd/common.nim index 4b10e68..f1d70f4 100644 --- a/src/cmd/common.nim +++ b/src/cmd/common.nim @@ -1,9 +1,18 @@ -import algorithm, sequtils, strutils, sugar, options +import std/[algorithm, sequtils, strutils, sugar] import ../api/cfcore import ../modpack/manifest -import ../term/log, ../term/prompt +import ../term/[log, prompt] -proc echoAddon*(mcMod: CfAddon, prefix: TermOut = "", postfix: TermOut = "", url: TermOut = mcMod.websiteUrl.dim, moreInfo: bool = false): void = +type + PaxSearchError* = object of IOError + +proc echoAddon*( + mcMod: CfAddon, + prefix: TermOut = "", + postfix: TermOut = "", + url: TermOut = mcMod.websiteUrl.dim, + moreInfo: bool = false +): void = ## output a single `mcMod`. ## `prefix` and `postfix` is displayed before and after the mod name respectively. ## if `moreInfo` is true, description and downloads will be printed as well. @@ -20,18 +29,18 @@ proc echoAddon*(mcMod: CfAddon, prefix: TermOut = "", postfix: TermOut = "", url echoClr indentPrefix.indent(3 + prefixIndent), "Description: ".fgCyan, mcMod.description echoClr indentPrefix.indent(3 + prefixIndent), "Downloads: ".fgCyan, mcMod.downloads.`$`.insertSep('.') -proc promptAddonChoice*(manifest: Manifest, mcMods: seq[CfAddon], selectInstalled: bool = false): Option[CfAddon] = +proc promptAddonChoice*(manifest: Manifest, mcMods: seq[CfAddon], selectInstalled: bool = false): CfAddon = ## prompt the user for a choice between `mcMods`. ## if `selectInstalled` is true, only installed mods may be selected, otherwise installed mods may not be selected. var mcMods = mcMods.reversed if selectInstalled: mcMods.keepIf((x) => manifest.isInstalled(x.projectId)) if manifest.files.len == 0: - return none[CfAddon]() + raise newException(PaxSearchError, "No installed mods detected.") if mcMods.len == 0: - return none[CfAddon]() + raise newException(PaxSearchError, "No mods found.") if mcMods.len == 1: - return some(mcMods[0]) + return mcMods[0] var availableIndexes = newSeq[int]() @@ -53,4 +62,4 @@ proc promptAddonChoice*(manifest: Manifest, mcMods: seq[CfAddon], selectInstalle echoAddon(mcMod, prefix.fgCyan, postfix.fgMagenta) let selectedIndex = prompt("Select a mod", choices = availableIndexes.map((x) => $x), choiceFormat = "1 - " & $mcMods.len).parseInt - return some(mcMods[mcMods.len - selectedIndex]) \ No newline at end of file + return mcMods[mcMods.len - selectedIndex] \ No newline at end of file diff --git a/src/cmd/expo.nim b/src/cmd/expo.nim index df64de3..adbe61a 100644 --- a/src/cmd/expo.nim +++ b/src/cmd/expo.nim @@ -1,4 +1,5 @@ -import os, zippy/ziparchives +import std/os +import zippy/ziparchives import ../modpack/manifest import ../term/log diff --git a/src/cmd/impo.nim b/src/cmd/impo.nim index 3a91789..43043a9 100644 --- a/src/cmd/impo.nim +++ b/src/cmd/impo.nim @@ -1,4 +1,5 @@ -import os, zippy/ziparchives +import std/os +import zippy/ziparchives import init import ../modpack/manifest import ../term/log @@ -23,7 +24,7 @@ proc paxImport*(path: string, force: bool, skipGit: bool): void = else: moveDir(tempPackFolder, packFolder) - if not fileExists(manifestFile): + if not fileExists(packFolder / "manifest.json"): echoError "Could not import .zip: manifest.json not found." echoClr indentPrefix, "Make sure your .zip file is a valid minecraft modpack in the curseforge modpack format." quit(1) diff --git a/src/cmd/init.nim b/src/cmd/init.nim index 0afad51..c899b0b 100644 --- a/src/cmd/init.nim +++ b/src/cmd/init.nim @@ -1,7 +1,7 @@ -import asyncdispatch, options, os, osproc +import std/[asyncdispatch, os, osproc] import ../api/metadata -import ../modpack/manifest, ../modpack/loader, ../modpack/version -import ../term/log, ../term/prompt +import ../modpack/[manifest, loader, version] +import ../term/[log, prompt] import ../util/flow proc paxInitManifest(): void = @@ -14,11 +14,7 @@ proc paxInitManifest(): void = manifest.mcVersion = Version(prompt(indentPrefix & "Minecraft version", default = "1.16.5")) let loader = prompt(indentPrefix & "Loader", choices = @["forge", "fabric"], default = "forge").toLoader - let loaderId = waitFor(manifest.mcVersion.getModloaderId(loader)) - if loaderId.isNone: - echoError "This is either not a minecraft version, or no ", $loader, " version exists for this minecraft version." - quit(1) - manifest.mcModloaderId = loaderId.get() + manifest.mcModloaderId = waitFor(manifest.mcVersion.getModloaderId(loader)) echoDebug "Installed ", $loader, " version ", manifest.mcModloaderId.fgGreen echoInfo "Creating manifest.." diff --git a/src/cmd/list.nim b/src/cmd/list.nim index 098199c..f2d25bb 100644 --- a/src/cmd/list.nim +++ b/src/cmd/list.nim @@ -1,7 +1,7 @@ -import algorithm, asyncdispatch, asyncfutures, sequtils, strutils, options, os, sugar +import std/[algorithm, asyncdispatch, sequtils, strutils, os, sugar] import common -import ../api/cfclient, ../api/cfcore -import ../modpack/manifest, ../modpack/modinfo +import ../api/[cfclient, cfcore] +import ../modpack/[manifest, modinfo] import ../term/log proc paxList*(status: bool, info: bool): void = @@ -12,15 +12,12 @@ proc paxList*(status: bool, info: bool): void = let manifest = readManifestFromDisk() let fileCount = manifest.files.len - let mcModRequests = manifest.files.map((x) => fetchAddon(x.projectId)) - let mcModFileRequests = manifest.files.map((x) => fetchAddonFile(x.projectId, x.fileId)) - let mcMods = all(mcModRequests) - let mcModFiles = all(mcModFileRequests) + let mcMods: Future[seq[CfAddon]] = manifest.files.map((x) => x.projectId).fetchAddons + let mcModFiles: Future[seq[CfAddonFile]] = manifest.files.map((x) => x.fileId).fetchAddonFiles echoInfo "Loading mods.." waitFor(mcMods and mcModFiles) - let modDataOptions = zip(mcMods.read(), mcModFiles.read()) - var modData = modDataOptions.map((x) => (x[0].get(), x[1].get())) + var modData = zip(mcMods.read(), mcModFiles.read()) modData = modData.sorted((x,y) => cmp(x[0].name, y[0].name)) echoRoot "ALL MODS ".fgMagenta, ("(" & $fileCount & ")").dim diff --git a/src/cmd/pin.nim b/src/cmd/pin.nim index f6eba49..e605dfc 100644 --- a/src/cmd/pin.nim +++ b/src/cmd/pin.nim @@ -1,8 +1,8 @@ -import asyncdispatch, asyncfutures, options, os +import std/[asyncdispatch, os] import common -import ../api/cfcore, ../api/cfclient -import ../modpack/install, ../modpack/manifest -import ../term/log, ../term/prompt +import ../api/[cfcore, cfclient] +import ../modpack/manifest +import ../term/[log, prompt] import ../util/flow proc paxPin*(name: string): void = @@ -16,11 +16,7 @@ proc paxPin*(name: string): void = let mcMods = waitFor(fetchAddonsByQuery(name)) echoDebug "Searching for mod.." - let mcModOption = manifest.promptAddonChoice(mcMods, selectInstalled = true) - if mcModOption.isNone: - echoError "No installed mods found for your search." - quit(1) - let mcMod = mcModOption.get() + let mcMod = manifest.promptAddonChoice(mcMods, selectInstalled = true) echo "" echoRoot "SELECTED MOD".dim diff --git a/src/cmd/remove.nim b/src/cmd/remove.nim index c56bded..b126011 100644 --- a/src/cmd/remove.nim +++ b/src/cmd/remove.nim @@ -1,8 +1,8 @@ -import asyncdispatch, asyncfutures, options, os +import std/[asyncdispatch, os] import common -import ../api/cfcore, ../api/cfclient -import ../modpack/install, ../modpack/manifest -import ../term/log, ../term/prompt +import ../api/[cfcore, cfclient] +import ../modpack/manifest +import ../term/[log, prompt] import ../util/flow proc removeDependencies(manifest: var Manifest, file: ManifestFile): void {.used.} = @@ -32,11 +32,7 @@ proc paxRemove*(name: string, strategy: string): void = let mcMods = waitFor(fetchAddonsByQuery(name)) echoDebug "Searching for mod.." - let mcModOption = manifest.promptAddonChoice(mcMods, selectInstalled = true) - if mcModOption.isNone: - echoError "No installed mods found for your search." - quit(1) - let mcMod = mcModOption.get() + let mcMod = manifest.promptAddonChoice(mcMods, selectInstalled = true) echo "" echoRoot "SELECTED MOD".dim diff --git a/src/cmd/update.nim b/src/cmd/update.nim index 6d5dac6..655d247 100644 --- a/src/cmd/update.nim +++ b/src/cmd/update.nim @@ -1,8 +1,8 @@ -import asyncdispatch, asyncfutures, options, os +import std/[asyncdispatch, os] import common -import ../api/cfclient, ../api/cfcore -import ../modpack/install, ../modpack/manifest -import ../term/log, ../term/prompt +import ../api/[cfclient, cfcore] +import ../modpack/[install, manifest] +import ../term/[log, prompt] import ../util/flow proc paxUpdate*(name: string, strategy: string): void = @@ -16,11 +16,7 @@ proc paxUpdate*(name: string, strategy: string): void = let mcMods = waitFor(fetchAddonsByQuery(name)) echoDebug "Searching for mod.." - let mcModOption = manifest.promptAddonChoice(mcMods, selectInstalled = true) - if mcModOption.isNone: - echoError "No installed mods found for your search." - quit(1) - let mcMod = mcModOption.get() + let mcMod = manifest.promptAddonChoice(mcMods, selectInstalled = true) echo "" echoRoot "SELECTED MOD".dim @@ -37,12 +33,9 @@ proc paxUpdate*(name: string, strategy: string): void = echoDebug "Retrieving mod versions.." let mcModFiles = waitFor(fetchAddonFiles(mcMod.projectId)) - let mcModFile = mcModFiles.selectAddonFile(manifest, strategy) - if mcModFile.isNone: - echoError "No compatible version found." - quit(1) + let mcModFile = mcModFiles.selectAddonFile(manifest.loader, manifest.mcVersion, strategy) echoInfo "Updating ", mcMod.name.fgCyan, ".." - manifest.updateAddon(mcMod.projectId, mcModFile.get().fileId) + manifest.updateAddon(mcMod.projectId, mcModFile.fileId) echoDebug("Writing to manifest...") manifest.writeToDisk() \ No newline at end of file diff --git a/src/cmd/upgrade.nim b/src/cmd/upgrade.nim index ca90272..47f5aa7 100644 --- a/src/cmd/upgrade.nim +++ b/src/cmd/upgrade.nim @@ -1,7 +1,7 @@ -import asyncdispatch, asyncfutures, sequtils, strutils, sugar, options, os -import ../api/cfclient, ../api/cfcore -import ../modpack/manifest, ../modpack/install -import ../term/log, ../term/prompt +import std/[asyncdispatch, asyncfutures, sequtils, sugar, os] +import ../api/[cfclient, cfcore] +import ../modpack/[manifest, install] +import ../term/[log, prompt] import ../util/flow proc paxUpgrade*(strategy: string): void = @@ -14,9 +14,8 @@ proc paxUpgrade*(strategy: string): void = returnIfNot promptYN($fileCount & " mods will be updated to the " & $strategy & " version. Do you want to continue?", default = true) - let mcModRequests = manifest.files.map((x) => fetchAddon(x.projectId)) + let mcMods = manifest.files.map((x) => x.projectId).fetchAddons let mcModFilesRequests = manifest.files.map((x) => fetchAddonFiles(x.projectId)) - let mcMods = all(mcModRequests) let mcModFiles = all(mcModFilesRequests) echoInfo "Loading mods.." @@ -25,16 +24,17 @@ proc paxUpgrade*(strategy: string): void = for pairs in modData: let (mcMod, mcModFiles) = pairs - let mcModFile = mcModFiles.selectAddonFile(manifest, strategy) - let manifestFile = manifest.getFile(mcMod.get().projectId) + let manifestFile = manifest.getFile(mcMod.projectId) if manifestFile.metadata.pinned: - echoWarn mcMod.get().name.fgCyan, " is pinned. Skipping.." + echoWarn mcMod.name.fgCyan, " is pinned. Skipping.." continue - if mcModFile.isNone: - echoWarn mcMod.get().name.fgCyan, " does not have a compatible version. Skipping.." + let mcModFile = try: + mcModFiles.selectAddonFile(manifest.loader, manifest.mcVersion, strategy) + except PaxInstallError: + echoWarn mcMod.name.fgCyan, " does not have a compatible version. Skipping.." continue - echoInfo "Updating ", mcMod.get().name.fgCyan, ".." - manifest.updateAddon(mcMod.get().projectId, mcModFile.get().fileId) + echoInfo "Updating ", mcMod.name.fgCyan, ".." + manifest.updateAddon(mcMod.projectId, mcModFile.fileId) echoDebug "Writing to manifest..." manifest.writeToDisk() \ No newline at end of file diff --git a/src/cmd/version.nim b/src/cmd/version.nim index ec5d191..8195b61 100644 --- a/src/cmd/version.nim +++ b/src/cmd/version.nim @@ -1,6 +1,6 @@ -import asyncdispatch, asyncfutures, options, os +import std/[asyncdispatch, os] import ../api/metadata -import ../modpack/manifest, ../modpack/loader, ../modpack/version +import ../modpack/[manifest, loader, version] import ../term/log proc paxVersion*(version: string, loader: string, latest: bool): void = @@ -12,12 +12,8 @@ proc paxVersion*(version: string, loader: string, latest: bool): void = let loader = if loader == "": manifest.loader else: loader let loaderId = waitFor(version.Version.getModloaderId(loader, latest)) - if loaderId.isNone: - echoError "This is either not a minecraft version, or no ", $loader, " version exists for this minecraft version." - return - manifest.mcVersion = version.Version - manifest.mcModloaderId = loaderId.get() + manifest.mcModloaderId = loaderId echoDebug "Writing to manifest..." manifest.writeToDisk() diff --git a/src/modpack/install.nim b/src/modpack/install.nim index 923fed2..fb0a898 100644 --- a/src/modpack/install.nim +++ b/src/modpack/install.nim @@ -3,10 +3,9 @@ ## Users of Pax can choose between three different strategies which decide how the "best" version ## of a mod to install is selected. -import options, sequtils -import manifest +import std/sequtils import ../api/cfcore -import ../modpack/loader, ../modpack/version +import ../modpack/[loader, version] type InstallStrategy* = enum @@ -16,6 +15,8 @@ type ## newest = newest version which is compatible with the minor modpack version. Stable, Recommended, Newest + PaxInstallError* = object of IOError + converter toInstallStrategy*(str: string): InstallStrategy = ## Convert `str` to an InstallStrategy. case str: @@ -36,24 +37,25 @@ proc isNewest(file: CfAddonFile, modpackVersion: Version): bool = ## returns true if `file` is compatible according to InstallStrategy.newest. return modpackVersion.minor in file.gameVersions.map(minor) -proc selectAddonFile*(files: seq[CfAddonFile], manifest: Manifest, strategy: InstallStrategy): Option[CfAddonFile] = +proc selectAddonFile*(files: seq[CfAddonFile], mpLoader: Loader, mpMcVersion: Version, strategy: InstallStrategy): CfAddonFile = ## Select the best mod file out of `files`, given the `manifest` and `strategy`. - var latestFile = none[CfAddonFile]() for file in files: - let onFabric = manifest.loader == Loader.Fabric and file.isFabricCompatible - let onForge = manifest.loader == Loader.Forge and file.isForgeCompatible - let onStable = strategy == InstallStrategy.Stable and file.isStable(manifest.mcVersion) - let onRecommended = strategy == InstallStrategy.Recommended and file.isRecommended(manifest.mcVersion) - let onNewest = strategy == InstallStrategy.Newest and file.isNewest(manifest.mcVersion) - if latestFile.isNone or latestFile.get().fileId < file.fileId: + if result.isNil or result.fileId < file.fileId: + let onFabric = mpLoader == Loader.Fabric and file.isFabricCompatible + let onForge = mpLoader == Loader.Forge and file.isForgeCompatible + let onStable = strategy == InstallStrategy.Stable and file.isStable(mpMcVersion) + let onRecommended = strategy == InstallStrategy.Recommended and file.isRecommended(mpMcVersion) + let onNewest = strategy == InstallStrategy.Newest and file.isNewest(mpMcVersion) if onFabric or onForge: if onStable or onRecommended or onNewest: - latestFile = some(file) + result = file - if latestFile.isNone: - return case strategy: - of InstallStrategy.Stable: selectAddonFile(files, manifest, InstallStrategy.Recommended) - of InstallStrategy.Recommended: selectAddonFile(files, manifest, InstallStrategy.Newest) - else: latestFile - - return latestFile \ No newline at end of file + # In case nothing has been found, fallback to more generous install strategies + if result.isNil: + case strategy: + of InstallStrategy.Stable: + return selectAddonFile(files, mpLoader, mpMcVersion, InstallStrategy.Recommended) + of InstallStrategy.Recommended: + return selectAddonFile(files, mpLoader, mpMcVersion, InstallStrategy.Newest) + else: + raise newException(PaxInstallError, "No suitable version found for file '" & files[0].name & "'.") \ No newline at end of file diff --git a/src/modpack/loader.nim b/src/modpack/loader.nim index 004b221..5754c97 100644 --- a/src/modpack/loader.nim +++ b/src/modpack/loader.nim @@ -1,9 +1,9 @@ ## Exports `Loader` which specifies the modloader type for a given modpack. ## -## Pax currently has support for the Fabric & Forge modloaders and assumes that mods that work on one modloader -## do not work on another. +## Pax currently has support for the Fabric & Forge modloaders and assumes that +## mods that work on one modloader do not work on another. -import strformat, strutils +import std/[strformat, strutils] type Loader* = enum diff --git a/src/modpack/manifest.nim b/src/modpack/manifest.nim index 19ed334..f02c0c9 100644 --- a/src/modpack/manifest.nim +++ b/src/modpack/manifest.nim @@ -1,16 +1,15 @@ ## Defines methods for interacting with a curseforge manifest file. ## -## In the CF modpack format, modpack information & mods/resourcepacks are tracked within -## a specific file known as the `manifest.json`. Each addon is tracked with a given projectid (identifies the addon) -## and a file id (identifies the version of the addon.) +## In the CF modpack format, modpack information & mods/resourcepacks are tracked within a specific file +## known as the `manifest.json`. Each addon is tracked with a given projectid (identifies the addon) +## and a file id (identifies the version of the addon). -import algorithm, asyncdispatch, json, options, os, sequtils, strformat, sugar +import std/[algorithm, asyncdispatch, json, options, os, sequtils, sugar] import loader -import ../api/cfclient, ../api/cfcore +import ../api/[cfclient, cfcore] import ../modpack/version -import ../term/color, ../term/log -export color -export log +import ../term/[color, log] +export color, log type ManifestMetadata* = ref object @@ -48,7 +47,6 @@ const tempPackFolder* = projectFolder / "temppack/" overridesFolder* = packFolder / "overrides/" paxFile* = overridesFolder / ".pax" - manifestFile* = packFolder / "manifest.json" outputFolder* = projectFolder / ".out/" proc initManifestMetadata*(name: string, explicit: bool, pinned: bool, dependencies: seq[int]): ManifestMetadata = @@ -76,15 +74,10 @@ proc toManifestFile(json: JsonNode): Future[ManifestFile] {.async.} = let addon = fetchAddon(result.projectId) let addonFile = fetchAddonFile(result.projectId, result.fileId) await addon and addonFile - if addon.read().isNone() or addonFile.read().isNone(): - raise newException( - ValueError, - fmt"projectID {result.projectId} & fileID {result.fileId} are not correct!" - ) - result.metadata.name = addon.read().get().name + result.metadata.name = addon.read().name result.metadata.explicit = true result.metadata.pinned = false - result.metadata.dependencies = addonFile.read().get().dependencies + result.metadata.dependencies = addonFile.read().dependencies else: result.metadata.name = json["__meta"]["name"].getStr() result.metadata.explicit = json["__meta"]{"explicit"}.getBool(true) @@ -165,7 +158,7 @@ proc removeAddon*(manifest: var Manifest, projectId: int): ManifestFile = ## remove a mod from the project with the given `projectId`, returns removed mod. for i, file in manifest.files: if file.projectId == projectId: - manifest.files.delete(i, i) + manifest.files.delete(i..i) return file proc updateAddon*(manifest: var Manifest, file: ManifestFile): void = @@ -175,24 +168,24 @@ proc updateAddon*(manifest: var Manifest, file: ManifestFile): void = proc updateAddon*(manifest: var Manifest, projectId: int, fileId: int): void = ## update a mod with the given `projectId` to the given `fileId` - var modToUpdate = removeAddon(manifest, projectId) - modToUpdate.fileId = fileId - installAddon(manifest, modToUpdate) + for file in manifest.files: + if file.projectId == projectId: + file.fileId = fileId -template isPaxProject*: bool = +template isPaxProject*(path = packFolder): bool = ## returns true if the current folder is a pax project folder - fileExists(manifestFile) + fileExists(path / "manifest.json") -template requirePaxProject*: void = +template requirePaxProject*(path = packFolder): void = ## will error if the current folder isn't a pax project - if not isPaxProject(): + if not isPaxProject(path): echoError "The current folder isn't a pax project." echoClr indentPrefix, "To initialize a pax project, enter ".fgRed, "pax init" return -template rejectPaxProject*: void = +template rejectPaxProject*(path = packFolder): void = ## will error if the current folder is a pax project - if isPaxProject: + if isPaxProject(path): echoError "The current folder is already a pax project." echoClr indentPrefix, "If you are sure you want to overwrite existing files, use the ", "--force".fgRed, " option" return @@ -203,10 +196,10 @@ template rejectInstalledAddon*(manifest: Manifest, projectId: int): void = echoError "This mod is already installed." return -proc readManifestFromDisk*(path = manifestFile): Manifest = +proc readManifestFromDisk*(path = packFolder): Manifest = ## get a Manifest from disk (with `path` as the path) - return readFile(path).parseJson.toManifest + return readFile(path / "manifest.json").parseJson.toManifest -proc writeToDisk*(manifest: Manifest, path = manifestFile): void = +proc writeToDisk*(manifest: Manifest, path = packFolder): void = ## write `manifest` to disk (with `path` as the path) - writeFile(path, manifest.toJson.pretty) + writeFile(path / "manifest.json", manifest.toJson.pretty) diff --git a/src/modpack/modinfo.nim b/src/modpack/modinfo.nim index bb21bd2..834d869 100644 --- a/src/modpack/modinfo.nim +++ b/src/modpack/modinfo.nim @@ -4,10 +4,10 @@ ## - if the addon is up-to-date ## - if the addon is compatible with the modpack -import sequtils, sugar +import std/[sequtils, sugar] import ../api/cfcore -import ../term/color import ../modpack/version +import ../term/color type Compability* = enum @@ -50,14 +50,14 @@ proc getMessage*(c: Compability): string = of Compability.Major: "The installed mod only matches the major version as the modpack. Issues may arise." of Compability.None: "The installed mod is incompatible with the modpack's minecraft version." -proc getFreshness*(file: CfAddonFile, modpackVersion: Version, addon: CfAddon): Freshness = +proc getFreshness*(file: CfAddonFile, mpVersion: Version, addon: CfAddon): Freshness = ## get freshness of a file let latestFiles = addon.gameVersionLatestFiles - let modpackVersionFiles = latestFiles.filter((x) => x.version == modpackVersion) + let modpackVersionFiles = latestFiles.filter((x) => x.version == mpVersion) if modpackVersionFiles.len == 1: if modpackVersionFiles[0].fileId == file.fileId: return Freshness.Newest - if latestFiles.any((x) => x.fileId == file.fileId and x.version.minor == modpackVersion.minor): + if latestFiles.any((x) => x.fileId == file.fileId and x.version.minor == mpVersion.minor): return Freshness.NewestForAVersion return Freshness.Old diff --git a/src/modpack/templates/main.yml b/src/modpack/templates/main.yml index 7e07ba1..ee82ac7 100644 --- a/src/modpack/templates/main.yml +++ b/src/modpack/templates/main.yml @@ -128,5 +128,5 @@ jobs: file_path: ${{ needs.modpack-info.outputs.projectname }}-${{ needs.modpack-info.outputs.tag }}.zip changelog: "${{ needs.changelog.outputs.changelog }}" changelog_type: markdown - game_versions: ${{ needs.modpack-info.outputs.version }} - release_type: ${{ steps.release-type.outputs.type }} \ No newline at end of file + game_versions: "Minecraft ${{ needs.modpack-info.outputs.version }}" + release_type: ${{ steps.release-type.outputs.type }} diff --git a/src/modpack/version.nim b/src/modpack/version.nim index 03ef97b..abc078f 100644 --- a/src/modpack/version.nim +++ b/src/modpack/version.nim @@ -1,7 +1,7 @@ ## Defines several common functions for working with minecraft versions, such as ## equality checking & comparisons to check whether a version is older or newer than another one. -import hashes, sequtils, strutils, sugar +import std/[hashes, sequtils, strutils, sugar] type ## A minecraft version (1.11, 1.12.2, 1.16.4, 1.14.1, ...) diff --git a/src/pax.nim b/src/pax.nim index 47be05b..338a56f 100644 --- a/src/pax.nim +++ b/src/pax.nim @@ -202,9 +202,9 @@ spec.parseOrHelp() # GLOBAL OPTIONS if commonArgs.yes.seen: - skipYNSetting = true + enableSkipYN() if commonArgs.noColor.seen: - terminalColorEnabledSetting = false + disableTermColors() # COMMANDS if spec.init.seen: diff --git a/src/term/color.nim b/src/term/color.nim index 4d6bef0..293322a 100644 --- a/src/term/color.nim +++ b/src/term/color.nim @@ -24,7 +24,7 @@ import terminal, unicode var ## if false, terminal color will be disabled. - terminalColorEnabledSetting* = true + isTerminalColorEnabled = true type TermOutKind = enum @@ -109,16 +109,16 @@ proc clrWrite*(f: File, args: varargs[TermOut]): void = for part in arg: case part.kind: of okForeground: - if terminalColorEnabledSetting: + if isTerminalColorEnabled: f.setForegroundColor(part.fgColor) of okBackground: - if terminalColorEnabledSetting: + if isTerminalColorEnabled: f.setBackgroundColor(part.bgColor) of okStyle: - if terminalColorEnabledSetting: + if isTerminalColorEnabled: f.setStyle({part.style}) of okReset: - if terminalColorEnabledSetting: + if isTerminalColorEnabled: f.resetAttributes() of okString: f.write(part.text) @@ -137,4 +137,12 @@ proc strLen*(term: TermOut): Natural = result = 0 for part in term: if part.kind == okString: - result += part.text.runeLen \ No newline at end of file + result += part.text.runeLen + +proc enableTermColors*() = + ## enable colors for the `term/color` module. + isTerminalColorEnabled = true + +proc disableTermColors*() = + ## disable colors for the `term/color` module. + isTerminalColorEnabled = false \ No newline at end of file diff --git a/src/term/prompt.nim b/src/term/prompt.nim index 480bb87..3b946e2 100644 --- a/src/term/prompt.nim +++ b/src/term/prompt.nim @@ -8,12 +8,12 @@ ## - Outputting a question and expecting a selected singular choice out of multiple choices. ## - Outputting a yes/no question and expecting a yes/no answer. -import strutils, terminal +import std/[strutils, terminal] import color var ## if true, all promptYN will be skipped and return true. - skipYNSetting*: bool = false + skipYN: bool = false proc pretty[T](s: seq[T]): string = ## pretty-print a sequence @@ -83,6 +83,14 @@ converter fromYN(choice: string): bool = proc promptYN*(prompt: string, default: bool): bool = ## prompt the user for an answer to a yes/no question. ## if `default` is specified, skipping the question by pressing enter without input will return default. - if skipYNSetting: return true + if skipYN: return true let answer = prompt(prompt, choices = @["y", "Y", "n", "N"], choiceFormat = "y/n", default = default.toYN.`$`) return answer.fromYN + +proc enableSkipYN*() = + ## enable skipping all prompts (automatically answers with Y). + skipYN = true + +proc disableSkipYN*() = + ## disable skipping all prompts (automatically answers with Y). + skipYN = false \ No newline at end of file diff --git a/tests/api/tcfclient.nim b/tests/api/tcfclient.nim index 820e96a..bccb5d6 100644 --- a/tests/api/tcfclient.nim +++ b/tests/api/tcfclient.nim @@ -1,48 +1,84 @@ -discard """ - cmd: "nim $target --hints:on -d:testing -d:ssl --nimblePath:tests/deps $options $file" -""" +import std/[asyncdispatch, options, sequtils, strutils, sugar] +import api/[cfclient, cfcore] +import ../tutils -import asyncdispatch, options, sequtils, strutils, sugar -import api/cfclient, api/cfcore - -block: # fetch by query - let mods = waitFor(fetchAddonsByQuery("jei")) +asyncBlock: # fetch by query + let mods = await fetchAddonsByQuery("jei") doAssert mods[0].projectId == 238222 doAssert mods[0].name == "Just Enough Items (JEI)" -block: # fetch mods by query - let mods = waitFor(fetchAddonsByQuery("jei", some(CfAddonGameCategory.Mod))) +asyncBlock: # fetch mods by query + let mods = await fetchAddonsByQuery("jei", some(CfAddonGameCategory.Mod)) doAssert mods.all(m => m.websiteUrl.contains("/mc-mods/")) -block: # fetch resource packs by query - let mods = waitFor(fetchAddonsByQuery("jei", some(CfAddonGameCategory.Resourcepack))) +asyncBlock: # fetch resource packs by query + let mods = await fetchAddonsByQuery("jei", some(CfAddonGameCategory.Resourcepack)) doAssert mods.all(m => m.websiteUrl.contains("/texture-packs/")) -block: # fetch mod by id - let mcMod = waitFor(fetchAddon(220318)).get() +asyncBlock: # fetch non-existing by query + let mods = await fetchAddonsByQuery("---------------------------") + doAssert mods.len == 0 + +asyncBlock: # fetch mod by id + let mcMod = await fetchAddon(220318) doAssert mcMod.projectId == 220318 doAssert mcMod.name == "Biomes O' Plenty" -## Skip failing test because the curse.nikky.moe api doesn't update anymore -#[ -block: # fetch mod by slug - var mcMod = waitFor(fetchAddon("appleskin")).get() +asyncBlock: # fetch mod by non-existing id + doAssertRaises(CfClientError): + discard await fetchAddon(99999999) + +asyncBlock: # fetch mods by id + let mcMods = await fetchAddons(@[220318, 238222]) + doAssert mcMods[0].projectId == 220318 + doAssert mcMods[1].projectId == 238222 + +asyncBlock: # fetch mods by non-existing id + doAssertRaises(CfClientError): + discard await fetchAddons(@[220318, 99999999]) + +asyncBlock: # fetch mod by slug + var mcMod = await fetchAddon("appleskin") doAssert mcMod.projectId == 248787 - mcMod = waitFor(fetchAddon("dtbop")).get() + mcMod = await fetchAddon("dtbop") doAssert mcMod.projectId == 289529 - mcMod = waitFor(fetchAddon("dtphc")).get() + mcMod = await fetchAddon("dtphc") doAssert mcMod.projectId == 307560 -]# -block: # fetch mod files - let modFiles = waitFor(fetchAddonFiles(248787)) +asyncBlock: # fetch mod by non-existing slug + doAssertRaises(CfClientError): + discard await fetchAddon("abcdefghijklmnopqrstuvwxyz") + +asyncBlock: # fetch mod files by project id + let modFiles = await fetchAddonFiles(248787) doAssert modFiles.any((x) => x.fileId == 3035787) -block: # fetch mod file - let modFile = waitFor(fetchAddonFile(306770, 2992184)).get() +asyncBlock: # fetch mod files by non-existing project id + doAssertRaises(CfClientError): + discard await fetchAddonFiles(99999999) + +asyncBlock: # fetch mod files by file ids + let modFiles = await fetchAddonFiles(@[2992184, 3098571]) + doAssert modFiles[0].fileId == 2992184 + doAssert modFiles[1].fileId == 3098571 + +asyncBlock: # fetch mod files by non-existing file ids + doAssertRaises(CfClientError): + discard await fetchAddonFiles(@[2992184, 99999999]) + +asyncBlock: # fetch mod file by project & file id + let modFile = await fetchAddonFile(306770, 2992184) doAssert modFile.fileId == 2992184 doAssert modFile.name == "Patchouli-1.0-21.jar" -block: # check if dependencies are tracked - let modFile = waitFor(fetchAddonFile(243121, 3366626)).get() +asyncBlock: # fetch mod files by non-existing project & file id + doAssertRaises(CfClientError): + discard await fetchAddonFile(306770, 99999999) + doAssertRaises(CfClientError): + discard await fetchAddonFile(99999999, 2992184) + +asyncBlock: # check if dependencies are tracked + let modFile = await fetchAddonFile(243121, 3366626) doAssert modFile.dependencies == @[250363] + +runTests() \ No newline at end of file diff --git a/tests/api/thttp.nim b/tests/api/thttp.nim index 6b51499..3a9cd6a 100644 --- a/tests/api/thttp.nim +++ b/tests/api/thttp.nim @@ -1,24 +1,27 @@ -import asyncdispatch +import std/asyncdispatch import api/http +import ../tutils -block: # get with successful response - discard waitFor(get("http://httpbin.org/get".Url)) +asyncBlock: # get with successful response + discard await get("http://httpbin.org/get".Url) -block: # get with non-existing website +asyncBlock: # get with non-existing website doAssertRaises(OSError): - discard waitFor(get("http://non-existing-website.web".Url)) + discard await get("http://non-existing-website.web".Url) -block: # get on endpoint that does not support get +asyncBlock: # get on endpoint that does not support get doAssertRaises(HttpRequestError): - discard waitFor(get("http://httpbin.org/post".Url)) + discard await get("http://httpbin.org/post".Url) -block: # post with successful response - discard waitFor(post("http://httpbin.org/post".Url)) +asyncBlock: # post with successful response + discard await post("http://httpbin.org/post".Url) -block: # post with non-existing website +asyncBlock: # post with non-existing website doAssertRaises(OSError): - discard waitFor(post("http://non-existing-website.web".Url)) + discard await post("http://non-existing-website.web".Url) -block: # post on endpoint that does not support get +asyncBlock: # post on endpoint that does not support get doAssertRaises(HttpRequestError): - discard waitFor(post("http://httpbin.org/get".Url)) \ No newline at end of file + discard await post("http://httpbin.org/get".Url) + +runTests() \ No newline at end of file diff --git a/tests/api/tmetadata.nim b/tests/api/tmetadata.nim index d42934d..e5fc830 100644 --- a/tests/api/tmetadata.nim +++ b/tests/api/tmetadata.nim @@ -1,54 +1,53 @@ -discard """ - cmd: "nim $target --hints:on -d:testing -d:ssl --nimblePath:tests/deps $options $file" -""" - -import asyncdispatch, sequtils, strutils, sugar, options +import std/[asyncdispatch, sequtils, strutils, sugar, options] import api/metadata import modpack/loader, modpack/version +import ../tutils -block: # getModloaderId - Fabric - let id1 = getModloaderId("1.10.2".Version, Loader.Fabric) - let id2 = getModloaderId("1.128.0".Version, Loader.Fabric) - let id3 = getModloaderId("0.0.0".Version, Loader.Fabric) - let id4 = getModloaderId("1.16.3".Version, Loader.Fabric) - let id5 = getModloaderId("1.17".Version, Loader.Fabric) - let id6 = getModloaderId("1.14.4".Version, Loader.Fabric) - let id7 = getModloaderId("1.16.1".Version, Loader.Fabric) +asyncBlock: # getModLoaderId on Fabric for versions + let id = await getModloaderId("1.16.3".Version, Loader.Fabric) + doAssert id != "" +asyncBlock: + let id = await getModloaderId("1.17".Version, Loader.Fabric) + doAssert id != "" +asyncBlock: + let id = await getModloaderId("1.14.4".Version, Loader.Fabric) + doAssert id != "" - let allIdPromises = @[id1, id2, id3, id4, id5, id6, id7] - let allIds = waitFor(all(allIdPromises)) +asyncBlock: # getModLoaderId on Fabric for non-existing versions + doAssertRaises(MetadataClientError): + discard await getModloaderId("1.10.2".Version, Loader.Fabric) +asyncBlock: + doAssertRaises(MetadataClientError): + discard await getModloaderId("1.128.0".Version, Loader.Fabric) +asyncBlock: + doAssertRaises(MetadataClientError): + discard await getModloaderId("0.0.0".Version, Loader.Fabric) - doAssert id1.read().isNone() - doAssert id2.read().isNone() - doAssert id3.read().isNone() - doAssert id4.read().isSome() - doAssert id5.read().isSome() - doAssert id6.read().isSome() - doAssert id7.read().isSome() - doAssert allIds.filter((x) => x.isSome()).all((x) => x.get().startsWith("fabric-")) +asyncBlock: # getModLoaderId on Forge for versions + let id = await getModloaderId("1.12.2".Version, Loader.Forge) + doAssert id == "forge-14.23.5.2859" +asyncBlock: + let id = await getModloaderId("1.12".Version, Loader.Forge) + doAssert id == "forge-14.21.1.2387" +asyncBlock: + let id = await getModloaderId("1.16.1".Version, Loader.Forge) + doAssert id == "forge-32.0.108" -block: # getModloaderId - Forge - let id1 = getModloaderId("1.128.0".Version, Loader.Forge) - let id2 = getModloaderId("0.0.0".Version, Loader.Forge) - let id3 = getModloaderId("1.1.0".Version, Loader.Forge) - let id4 = getModloaderId("1.12.2".Version, Loader.Forge) - let id5 = getModloaderId("1.12".Version, Loader.Forge) - let id6 = getModloaderId("1.16.1".Version, Loader.Forge) - let id7 = getModloaderId("1.16.3".Version, Loader.Forge) - let id8 = getModloaderId("1.12".Version, Loader.Forge, latest=true) - let id9 = getModloaderId("1.16.1".Version, Loader.Forge, latest=true) - let id10 = getModloaderId("1.16.3".Version, Loader.Forge, latest=true) +asyncBlock: # getModLoaderId on Forge for latest versions + let id = await getModloaderId("1.12".Version, Loader.Forge, latest = true) + doAssert id == "forge-14.21.1.2443" +asyncBlock: + let id = await getModloaderId("1.16.1".Version, Loader.Forge, latest = true) + doAssert id == "forge-32.0.108" - let allIdPromises = @[id1, id2, id3, id4, id5, id6, id7, id8, id9, id10] - discard waitFor(all(allIdPromises)) +asyncBlock: # getModLoaderId on Forge for non-existing versions + doAssertRaises(MetadataClientError): + discard await getModloaderId("1.1.0".Version, Loader.Forge) +asyncBlock: + doAssertRaises(MetadataClientError): + discard await getModloaderId("1.128.0".Version, Loader.Forge) +asyncBlock: + doAssertRaises(MetadataClientError): + discard await getModloaderId("0.0.0".Version, Loader.Forge) - doAssert id1.read().isNone() - doAssert id2.read().isNone() - doAssert id3.read().isNone() - doAssert id4.read().get() == "forge-14.23.5.2859" - doAssert id5.read().get() == "forge-14.21.1.2387" - doAssert id6.read().get() == "forge-32.0.108" - doAssert id7.read().get() == "forge-34.1.0" - doAssert id8.read().get() == "forge-14.21.1.2443" - doAssert id9.read().get() == "forge-32.0.108" - doAssert id10.read().get() == "forge-34.1.42" \ No newline at end of file +runTests() \ No newline at end of file diff --git a/tests/cmd/tadd/tadd_cffilestring.nim b/tests/cmd/tadd/tadd_cffilestring.nim index c873803..9151a40 100644 --- a/tests/cmd/tadd/tadd_cffilestring.nim +++ b/tests/cmd/tadd/tadd_cffilestring.nim @@ -15,12 +15,12 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) -paxAdd("https://www.curseforge.com/minecraft/mc-mods/jei/files/3383214", noDepends = false, strategy = "recommended") +paxAdd("https://www.curseforge.com/minecraft/mc-mods/jei/files/3383214", noDepends = false, strategy = "recommended", addonType = "") let manifest = readFile("./modpack/manifest.json").parseJson doAssert fileExists("./modpack/manifest.json") diff --git a/tests/cmd/tadd/tadd_cfstring.nim b/tests/cmd/tadd/tadd_cfstring.nim index 878d83a..561b70e 100644 --- a/tests/cmd/tadd/tadd_cfstring.nim +++ b/tests/cmd/tadd/tadd_cfstring.nim @@ -15,8 +15,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/tadd/tadd_duplicates.nim b/tests/cmd/tadd/tadd_duplicates.nim index 0cd5629..070f531 100644 --- a/tests/cmd/tadd/tadd_duplicates.nim +++ b/tests/cmd/tadd/tadd_duplicates.nim @@ -14,8 +14,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/tadd/tadd_multistringsearch.nim b/tests/cmd/tadd/tadd_multistringsearch.nim index a79ee65..1cc173b 100644 --- a/tests/cmd/tadd/tadd_multistringsearch.nim +++ b/tests/cmd/tadd/tadd_multistringsearch.nim @@ -14,8 +14,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/tadd/tadd_projectfileids.nim b/tests/cmd/tadd/tadd_projectfileids.nim index 389c975..c53f7af 100644 --- a/tests/cmd/tadd/tadd_projectfileids.nim +++ b/tests/cmd/tadd/tadd_projectfileids.nim @@ -14,8 +14,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/tadd/tadd_projectid.nim b/tests/cmd/tadd/tadd_projectid.nim index 3e68932..6e5cf4f 100644 --- a/tests/cmd/tadd/tadd_projectid.nim +++ b/tests/cmd/tadd/tadd_projectid.nim @@ -14,8 +14,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/tadd/tadd_search.nim b/tests/cmd/tadd/tadd_search.nim index 6a40701..7464265 100644 --- a/tests/cmd/tadd/tadd_search.nim +++ b/tests/cmd/tadd/tadd_search.nim @@ -14,8 +14,8 @@ y ''' """ -import json, os -import cmd/init, cmd/add +import std/[json, os] +import cmd/[add, init] removeDir("./modpack") paxInit(force = false, skipManifest = false, skipGit = true) diff --git a/tests/cmd/texpo/texpo.nim b/tests/cmd/texpo/texpo.nim index 80ec076..4649323 100644 --- a/tests/cmd/texpo/texpo.nim +++ b/tests/cmd/texpo/texpo.nim @@ -3,7 +3,8 @@ discard """ batchable: false """ -import json, os, zippy/ziparchives +import std/[json, os] +import zippy/ziparchives import cmd/expo block: diff --git a/tests/cmd/texpo/texpo_customlocation.nim b/tests/cmd/texpo/texpo_customlocation.nim index 99fe4ce..3ac0b7e 100644 --- a/tests/cmd/texpo/texpo_customlocation.nim +++ b/tests/cmd/texpo/texpo_customlocation.nim @@ -3,7 +3,8 @@ discard """ batchable: false """ -import json, os, zippy/ziparchives +import std/[json, os] +import zippy/ziparchives import cmd/expo block: diff --git a/tests/cmd/timpo/timpo_fabric.nim b/tests/cmd/timpo/timpo_fabric.nim index 396f653..082d60b 100644 --- a/tests/cmd/timpo/timpo_fabric.nim +++ b/tests/cmd/timpo/timpo_fabric.nim @@ -4,7 +4,7 @@ discard """ batchable: false """ -import httpclient, json, strutils, os +import std/[httpclient, json, strutils, os] import cmd/impo block: diff --git a/tests/cmd/timpo/timpo_forge.nim b/tests/cmd/timpo/timpo_forge.nim index 0804706..6d3b5f8 100644 --- a/tests/cmd/timpo/timpo_forge.nim +++ b/tests/cmd/timpo/timpo_forge.nim @@ -4,7 +4,7 @@ discard """ batchable: false """ -import httpclient, json, strutils, os +import std/[httpclient, json, strutils, os] import cmd/impo block: diff --git a/tests/cmd/tinit/tinit_fabric.nim b/tests/cmd/tinit/tinit_fabric.nim index 02e6d59..99b32e8 100644 --- a/tests/cmd/tinit/tinit_fabric.nim +++ b/tests/cmd/tinit/tinit_fabric.nim @@ -12,7 +12,7 @@ fabric ''' """ -import strutils, os, json +import std/[strutils, os, json] import cmd/init block: # init fabric project diff --git a/tests/cmd/tinit/tinit_forge.nim b/tests/cmd/tinit/tinit_forge.nim index 75f9ec0..2b288d6 100644 --- a/tests/cmd/tinit/tinit_forge.nim +++ b/tests/cmd/tinit/tinit_forge.nim @@ -12,7 +12,7 @@ forge ''' """ -import json, strutils, os +import std/[strutils, os, json] import cmd/init block: diff --git a/tests/cmd/tinit/tinit_rejectexisting.nim b/tests/cmd/tinit/tinit_rejectexisting.nim index 4b1f6b8..0fd6a48 100644 --- a/tests/cmd/tinit/tinit_rejectexisting.nim +++ b/tests/cmd/tinit/tinit_rejectexisting.nim @@ -7,7 +7,7 @@ y ''' """ -import os +import std/os import cmd/init block: diff --git a/tests/cmd/tlist/tlist.nim b/tests/cmd/tlist/tlist.nim index 4761d3e..0bc52a4 100644 --- a/tests/cmd/tlist/tlist.nim +++ b/tests/cmd/tlist/tlist.nim @@ -8,10 +8,11 @@ discard """ ''' """ -import json, os -import cmd/list, term/color +import std/[json, os] +import cmd/list +import term/color -terminalColorEnabledSetting = false +disableTermColors() block: removeDir("./modpack/") diff --git a/tests/cmd/tlist/tlist_status.nim b/tests/cmd/tlist/tlist_status.nim index 51e5550..325d2da 100644 --- a/tests/cmd/tlist/tlist_status.nim +++ b/tests/cmd/tlist/tlist_status.nim @@ -10,10 +10,11 @@ discard """ ''' """ -import json, os -import cmd/list, term/color +import std/[json, os] +import cmd/list +import term/color -terminalColorEnabledSetting = false +disableTermColors() block: removeDir("./modpack/") diff --git a/tests/cmd/tlist/tlist_without_version.nim b/tests/cmd/tlist/tlist_without_version.nim index d6a44ae..d5615b2 100644 --- a/tests/cmd/tlist/tlist_without_version.nim +++ b/tests/cmd/tlist/tlist_without_version.nim @@ -10,10 +10,11 @@ discard """ ''' """ -import json, os -import cmd/list, term/color +import std/[json, os] +import cmd/list +import term/color -terminalColorEnabledSetting = false +disableTermColors() block: removeDir("./modpack/") diff --git a/tests/cmd/tpin/tpin.nim b/tests/cmd/tpin/tpin.nim index c7cfb8a..e132a0a 100644 --- a/tests/cmd/tpin/tpin.nim +++ b/tests/cmd/tpin/tpin.nim @@ -7,10 +7,8 @@ y ''' """ -import json, os -import cmd/pin, term/color - -terminalColorEnabledSetting = false +import std/[json, os] +import cmd/pin block: removeDir("./modpack/") diff --git a/tests/cmd/tremove/tremove_with_dependency.nim b/tests/cmd/tremove/tremove_with_dependency.nim index 20cc367..b951620 100644 --- a/tests/cmd/tremove/tremove_with_dependency.nim +++ b/tests/cmd/tremove/tremove_with_dependency.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/remove let manifestJson = %* { diff --git a/tests/cmd/tremove/tremove_with_dependents.nim b/tests/cmd/tremove/tremove_with_dependents.nim index 7760589..3609a27 100644 --- a/tests/cmd/tremove/tremove_with_dependents.nim +++ b/tests/cmd/tremove/tremove_with_dependents.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/remove let manifestJson = %* { diff --git a/tests/cmd/tremove/tremove_with_explicit_dependency.nim b/tests/cmd/tremove/tremove_with_explicit_dependency.nim index f275812..acc8987 100644 --- a/tests/cmd/tremove/tremove_with_explicit_dependency.nim +++ b/tests/cmd/tremove/tremove_with_explicit_dependency.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/remove let manifestJson = %* { diff --git a/tests/cmd/tremove/tremove_without_dependencies.nim b/tests/cmd/tremove/tremove_without_dependencies.nim index d2c6710..2f7e182 100644 --- a/tests/cmd/tremove/tremove_without_dependencies.nim +++ b/tests/cmd/tremove/tremove_without_dependencies.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/remove let manifestJson = %* { diff --git a/tests/cmd/tupdate/tupdate.nim b/tests/cmd/tupdate/tupdate.nim index 1138b7e..6ba15a9 100644 --- a/tests/cmd/tupdate/tupdate.nim +++ b/tests/cmd/tupdate/tupdate.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/update let manifestJson = %* { diff --git a/tests/cmd/tupdate/tupdate_pinned.nim b/tests/cmd/tupdate/tupdate_pinned.nim index bc5bc12..043407f 100644 --- a/tests/cmd/tupdate/tupdate_pinned.nim +++ b/tests/cmd/tupdate/tupdate_pinned.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/update let manifestJson = %* { diff --git a/tests/cmd/tupgrade/tupgrade.nim b/tests/cmd/tupgrade/tupgrade.nim index 0700bdf..fe17365 100644 --- a/tests/cmd/tupgrade/tupgrade.nim +++ b/tests/cmd/tupgrade/tupgrade.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/upgrade let manifestJson = %* { diff --git a/tests/cmd/tupgrade/tupgrade_pinned.nim b/tests/cmd/tupgrade/tupgrade_pinned.nim index ccf9454..d367ab4 100644 --- a/tests/cmd/tupgrade/tupgrade_pinned.nim +++ b/tests/cmd/tupgrade/tupgrade_pinned.nim @@ -7,7 +7,7 @@ y ''' """ -import json, os +import std/[json, os] import cmd/upgrade let manifestJson = %* { diff --git a/tests/cmd/tversion/tversion.nim b/tests/cmd/tversion/tversion.nim index 1a1e0db..f47aac3 100644 --- a/tests/cmd/tversion/tversion.nim +++ b/tests/cmd/tversion/tversion.nim @@ -10,11 +10,11 @@ discard """ ''' """ -import json, os +import std/[json, os] import cmd/version import term/color -terminalColorEnabledSetting = false +disableTermColors() let manifestJson = %* { "minecraft": { diff --git a/tests/cmd/tversion/tversion_latest.nim b/tests/cmd/tversion/tversion_latest.nim index dab0ef9..827a96f 100644 --- a/tests/cmd/tversion/tversion_latest.nim +++ b/tests/cmd/tversion/tversion_latest.nim @@ -10,11 +10,11 @@ discard """ ''' """ -import json, os +import std/[json, os] import cmd/version import term/color -terminalColorEnabledSetting = false +disableTermColors() let manifestJson = %* { "minecraft": { diff --git a/tests/modpack/tinstall.nim b/tests/modpack/tinstall.nim index 4faa0e3..e62552b 100644 --- a/tests/modpack/tinstall.nim +++ b/tests/modpack/tinstall.nim @@ -1,20 +1,14 @@ -import options, sequtils, sugar -import api/cfcore, modpack/install, modpack/loader, modpack/manifest, modpack/version +import std/[sequtils, sugar] +import api/cfcore +import modpack/[install, loader, manifest, version] block: # InstallStrategy - doAssert "stable" == InstallStrategy.Stable - doAssert "recommended" == InstallStrategy.Recommended - doAssert "newest" == InstallStrategy.Newest + doAssert "stable".toInstallStrategy == InstallStrategy.Stable + doAssert "recommended".toInstallStrategy == InstallStrategy.Recommended + doAssert "newest".toInstallStrategy == InstallStrategy.Newest doAssertRaises(ValueError): discard "abcdef".toInstallStrategy -proc initManifest(loader: Loader): Manifest = - result = Manifest() - result.name = "testmodpackname" - result.author = "testmodpackauthor" - result.version = "1.0.0" - result.mcModloaderId = $loader & "-0.11.0" - proc initCfAddonFile(fileId: int, name: string, gameVersions: seq[string], releaseType: CfAddonFileReleaseType): CfAddonFile = result = CfAddonFile() result.fileId = fileId @@ -24,118 +18,136 @@ proc initCfAddonFile(fileId: int, name: string, gameVersions: seq[string], relea result.gameVersions = gameVersions.map((x) => x.Version) block: # select out of specified forge mods - var m = initManifest(loader.Forge) + let loader = Loader.Forge + var mcVersion: Version let mods = @[ initCfAddonFile(300, "jei-1.0.2.jar", @["1.16.1", "1.16.2", "Forge"], CfAddonFileReleaseType.Beta), initCfAddonFile(200, "jei-1.0.1.jar", @["1.16", "1.16.1", "Forge"], CfAddonFileReleaseType.Release), initCfAddonFile(100, "jei-1.0.0.jar", @["1.16", "Forge"], CfAddonFileReleaseType.Alpha) ] - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.16".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.2".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.16".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.2".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] block: # select out of implied forge mods - var m = initManifest(loader.Forge) + let loader = Loader.Forge + var mcVersion: Version let mods = @[ initCfAddonFile(300, "jei-1.0.2.jar", @["1.16.1", "1.16.2"], CfAddonFileReleaseType.Beta), initCfAddonFile(200, "jei-1.0.1.jar", @["1.16", "1.16.1", "Forge"], CfAddonFileReleaseType.Alpha), initCfAddonFile(100, "jei-FORGE-1.0.0.jar", @["1.16"], CfAddonFileReleaseType.Release) ] - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.16".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[2] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.2".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.16".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[2] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.2".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] block: # select out of specified fabric mods - var m = initManifest(loader.Fabric) + let loader = Loader.Fabric + var mcVersion: Version let mods = @[ initCfAddonFile(301, "rei-1.0.2.jar", @["1.14.1", "1.14.4", "Fabric"], CfAddonFileReleaseType.Release), initCfAddonFile(201, "rei-1.0.1.jar", @["1.14", "1.14.1", "Fabric"], CfAddonFileReleaseType.Release), initCfAddonFile(101, "rei-1.0.0.jar", @["1.14", "Fabric"], CfAddonFileReleaseType.Beta) ] - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.14".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.14.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.14.4".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.14".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.14.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.14.4".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] block: # select out of implied fabric mods - var m = initManifest(loader.Fabric) + let loader = Loader.Fabric + var mcVersion: Version let mods = @[ initCfAddonFile(301, "rei-1.0.2-fabric.jar", @["1.14.1", "1.14.4"], CfAddonFileReleaseType.Alpha), initCfAddonFile(201, "rei-1.0.1-fabric.jar", @["1.14", "1.14.1"], CfAddonFileReleaseType.Beta), initCfAddonFile(101, "rei-1.0.0-fabric.jar", @["1.14", "Fabric"], CfAddonFileReleaseType.Release) ] - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.14".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[2] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.14.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.14.4".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.14".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[2] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.14.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.14.4".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] block: # select out of mixed mods + var loader: Loader + var mcVersion: Version let mods = @[ initCfAddonFile(801, "abc-1.3.2-fabric.jar", @["1.16.1", "1.16.2"], CfAddonFileReleaseType.Release), initCfAddonFile(701, "abc-1.3.2-FORGE.jar", @["1.16.1", "1.16.2"], CfAddonFileReleaseType.Release), @@ -148,67 +160,79 @@ block: # select out of mixed mods ] # Set loader to forge - var m = initManifest(loader.Forge) - - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.14".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[7] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[7] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[6] - - m.mcVersion = "1.14.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[7] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[7] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[6] - - m.mcVersion = "1.16".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[4] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[2] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[1] - - m.mcVersion = "1.16.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[1] - - m.mcVersion = "1.16.2".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[1] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[1] + loader = Loader.Forge + + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.14".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[7] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[7] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[6] + + mcVersion = "1.14.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[7] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[7] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[6] + + mcVersion = "1.16".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[4] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[2] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[1] + + mcVersion = "1.16.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[1] + + mcVersion = "1.16.2".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[1] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[1] # Set loader to forge - m = initManifest(loader.Fabric) - - m.mcVersion = "1.12".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.14".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.14.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).isNone - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).isNone - - m.mcVersion = "1.16".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[5] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[5] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.1".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] - - m.mcVersion = "1.16.2".Version - doAssert mods.selectAddonFile(m, InstallStrategy.Stable).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Recommended).get() == mods[0] - doAssert mods.selectAddonFile(m, InstallStrategy.Newest).get() == mods[0] \ No newline at end of file + loader = Loader.Fabric + + mcVersion = "1.12".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.14".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.14.1".Version + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) + doAssertRaises(PaxInstallError): + discard mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) + + mcVersion = "1.16".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[5] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[5] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.1".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] + + mcVersion = "1.16.2".Version + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Stable) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Recommended) == mods[0] + doAssert mods.selectAddonFile(loader, mcVersion, InstallStrategy.Newest) == mods[0] \ No newline at end of file diff --git a/tests/modpack/tmanifest.nim b/tests/modpack/tmanifest.nim new file mode 100644 index 0000000..4be4c5c --- /dev/null +++ b/tests/modpack/tmanifest.nim @@ -0,0 +1,56 @@ +import modpack/[loader, manifest, version] + +block: # manifest loader + let m = Manifest() + m.name = "testmodpack" + m.author = "testauthor" + m.version = "1.0.0" + m.mcVersion = "1.16.3".Version + + m.mcModloaderId = "fabric-0.11.0" + doAssert m.loader == Loader.Fabric + + m.mcModloaderId = "forge-34.1.0" + doAssert m.loader == Loader.Forge + +let file = initManifestFile( + projectId = 111, + fileId = 200, + initManifestMetadata( + name = "test", + explicit = true, + pinned = false, + dependencies = @[] + ) +) + +block: # manifest mods + var m = Manifest() + m.name = "testmodpack" + m.author = "testauthor" + m.version = "1.0.0" + m.mcVersion = "1.16.3".Version + + doAssert m.files.len == 0 + + block: # install + m.installAddon(file) + doAssert m.files.len == 1 + doAssert m.files[0].projectId == 111 + doAssert m.files[0].fileId == 200 + + block: # update with project & file id + m.updateAddon(111, 300) + doAssert m.files.len == 1 + doAssert m.files[0].projectId == 111 + doAssert m.files[0].fileId == 300 + + block: # update with file + m.updateAddon(file) + doAssert m.files.len == 1 + doAssert m.files[0].projectId == 111 + doAssert m.files[0].fileId == 300 + + block: # remove + discard m.removeAddon(111) + doAssert m.files.len == 0 diff --git a/tests/modpack/tmanifest/tmanifest.nim b/tests/modpack/tmanifest/tmanifest.nim deleted file mode 100644 index db72608..0000000 --- a/tests/modpack/tmanifest/tmanifest.nim +++ /dev/null @@ -1,53 +0,0 @@ -import modpack/loader, modpack/manifest, modpack/version - -block: # manifest loader - let m = Manifest() - m.name = "testmodpack" - m.author = "testauthor" - m.version = "1.0.0" - m.mcVersion = "1.16.3".Version - - m.mcModloaderId = "fabric-0.11.0" - doAssert m.loader == Loader.Fabric - - m.mcModloaderId = "forge-34.1.0" - doAssert m.loader == Loader.Forge - -block: # manifest mods - var m = Manifest() - m.name = "testmodpack" - m.author = "testauthor" - m.version = "1.0.0" - m.mcVersion = "1.16.3".Version - - doAssert m.files.len == 0 - - let file = initManifestFile( - projectId = 111, - fileId = 200, - initManifestMetadata( - name = "test", - explicit = true, - pinned = false, - dependencies = @[] - ) - ) - m.installAddon(file) - doAssert m.files.len == 1 - doAssert m.files[0].projectId == 111 - doAssert m.files[0].fileId == 200 - - m.updateAddon(111, 300) - doAssert m.files.len == 1 - doAssert m.files[0].projectId == 111 - doAssert m.files[0].fileId == 300 - - file.metadata.pinned = false - m.updateAddon(file) - doAssert m.files.len == 1 - doAssert m.files[0].projectId == 111 - doAssert m.files[0].fileId == 300 - doAssert m.files[0].metadata.pinned == false - - discard m.removeAddon(111) - doAssert m.files.len == 0 diff --git a/tests/modpack/tmanifest/tmanifest_disk.nim b/tests/modpack/tmanifest/tmanifest_disk.nim deleted file mode 100644 index e01f186..0000000 --- a/tests/modpack/tmanifest/tmanifest_disk.nim +++ /dev/null @@ -1,20 +0,0 @@ -import random, os, json -import modpack/manifest, modpack/version - -randomize() - -block: # manifest write / read from disk - let m = Manifest() - m.name = "testmodpack" - m.author = "testauthor" - m.version = "1.0.0" - m.mcVersion = "1.16.3".Version - - let dirname = joinPath(".", $rand(1000)) - createDir(dirname) - defer: removeDir(dirname) - let mPath = joinPath(dirname, "manifest.json") - - m.writeToDisk(path = mPath) - let readM = readManifestFromDisk(path = mPath) - doAssert m.toJson == readM.toJson \ No newline at end of file diff --git a/tests/modpack/tmanifest_disk.nim b/tests/modpack/tmanifest_disk.nim new file mode 100644 index 0000000..c957035 --- /dev/null +++ b/tests/modpack/tmanifest_disk.nim @@ -0,0 +1,14 @@ +import std/[json, tempfiles, os] +import modpack/[manifest, version] + +block: # manifest write / read from disk + let m = Manifest() + m.name = "testmodpack" + m.author = "testauthor" + m.version = "1.0.0" + m.mcVersion = "1.16.3".Version + + let tmpdir = createTempDir("", "") + m.writeToDisk(path = tmpdir) + let readM = readManifestFromDisk(path = tmpdir) + doAssert m.toJson == readM.toJson \ No newline at end of file diff --git a/tests/modpack/tmanifest/tmanifest_templates.nim b/tests/modpack/tmanifest_templates.nim similarity index 51% rename from tests/modpack/tmanifest/tmanifest_templates.nim rename to tests/modpack/tmanifest_templates.nim index bd1e9a3..3d5ed5f 100644 --- a/tests/modpack/tmanifest/tmanifest_templates.nim +++ b/tests/modpack/tmanifest_templates.nim @@ -3,10 +3,10 @@ discard """ batchable: false """ -import os -import modpack/loader, modpack/manifest, modpack/version +import std/[os, tempfiles] +import modpack/[loader, manifest, version] -block: # rejectInstalledMod +block: # rejectInstalledAddon let m = Manifest() m.name = "testmodpack" m.author = "testauthor" @@ -22,36 +22,31 @@ block: # rejectInstalledMod doAssert f(1234) == -1 doAssert f(9999) == 1 +block: # isPaxProject + let tmpdir = createTempDir("tmanifest_templates_isPaxProject", "") + + doAssert isPaxProject(tmpdir) == false + writeFile(tmpdir / "manifest.json", "") + doAssert isPaxProject(tmpdir) == true + block: # requirePaxProject + let tmpdir = createTempDir("tmanifest_templates_requirePaxProject", "") let f = proc(): int = result = -1 - requirePaxProject() + requirePaxProject(tmpdir) result = 1 - removeDir(packFolder) - doAssert f() == -1 - - createDir(packFolder) - createDir(overridesFolder) - writeFile(manifestFile, "Hello pax test") - defer: removeDir(packFolder) - + writeFile(tmpdir / "manifest.json", "") doAssert f() == 1 block: # rejectPaxProject + let tmpdir = createTempDir("tmanifest_templates_rejectPaxProject", "") let f = proc(): int = result = -1 - rejectPaxProject() + rejectPaxProject(tmpdir) result = 1 - removeDir(packFolder) - doAssert f() == 1 - - createDir(packFolder) - createDir(overridesFolder) - writeFile(manifestFile, "Hello pax test") - defer: removeDir(packFolder) - + writeFile(tmpdir / "manifest.json", "") doAssert f() == -1 \ No newline at end of file diff --git a/tests/modpack/tmodinfo.nim b/tests/modpack/tmodinfo.nim index 466034d..0467715 100644 --- a/tests/modpack/tmodinfo.nim +++ b/tests/modpack/tmodinfo.nim @@ -1,5 +1,6 @@ -import sequtils, sugar -import api/cfcore, modpack/modinfo, modpack/version +import std/[sequtils, sugar] +import api/cfcore +import modpack/[modinfo, version] proc initCfAddon(projectId: int, name: string, gameVersionLatestFiles: seq[tuple[version: Version, fileId: int]]): CfAddon = result = CfAddon() diff --git a/tests/nim.cfg b/tests/nim.cfg index ac5825b..e8be76f 100644 --- a/tests/nim.cfg +++ b/tests/nim.cfg @@ -1 +1,2 @@ ---path:"../src/" \ No newline at end of file +--path:"../src/" +-d:ssl \ No newline at end of file diff --git a/tests/term/tcolor.nim b/tests/term/tcolor.nim index 9833d61..67c698b 100644 --- a/tests/term/tcolor.nim +++ b/tests/term/tcolor.nim @@ -5,13 +5,12 @@ Wow how nice if this worked! Hello! I hope this works.. Well, I don't think it helps testing this without colors.. But without colors output should be consistent at least. -Concat works too? [RED][BLUE] - ''' +Concat works too? [RED][BLUE]''' """ import term/color -terminalColorEnabledSetting = false +disableTermColors() block: # clrWrite clrWrite(stdout, "Hi ") diff --git a/tests/term/tlog.nim b/tests/term/tlog.nim index bed503d..27286ae 100644 --- a/tests/term/tlog.nim +++ b/tests/term/tlog.nim @@ -4,13 +4,12 @@ discard """ [-] Information here! [!] Warning, for more interesting messages [x] An error has occured! -[Δ] Some funky looking root icon - ''' +[Δ] Some funky looking root icon''' """ -import term/color, term/log +import term/[color, log] -terminalColorEnabledSetting = false +disableTermColors() block: # echos echoDebug "Hello!" diff --git a/tests/term/tprompt/tprompt.nim b/tests/term/tprompt.nim similarity index 100% rename from tests/term/tprompt/tprompt.nim rename to tests/term/tprompt.nim diff --git a/tests/term/tprompt/tprompt_choices.nim b/tests/term/tprompt_choices.nim similarity index 100% rename from tests/term/tprompt/tprompt_choices.nim rename to tests/term/tprompt_choices.nim diff --git a/tests/term/tprompt/tprompt_choices_default.nim b/tests/term/tprompt_choices_default.nim similarity index 100% rename from tests/term/tprompt/tprompt_choices_default.nim rename to tests/term/tprompt_choices_default.nim diff --git a/tests/term/tprompt/tprompt_default.nim b/tests/term/tprompt_default.nim similarity index 100% rename from tests/term/tprompt/tprompt_default.nim rename to tests/term/tprompt_default.nim diff --git a/tests/term/tprompt/tprompt_yn.nim b/tests/term/tprompt_yn.nim similarity index 100% rename from tests/term/tprompt/tprompt_yn.nim rename to tests/term/tprompt_yn.nim diff --git a/tests/term/tprompt/tprompt_yn_skip.nim b/tests/term/tprompt_yn_skip.nim similarity index 93% rename from tests/term/tprompt/tprompt_yn_skip.nim rename to tests/term/tprompt_yn_skip.nim index 662d372..4ad0435 100644 --- a/tests/term/tprompt/tprompt_yn_skip.nim +++ b/tests/term/tprompt_yn_skip.nim @@ -1,6 +1,6 @@ import term/prompt -skipYNSetting = true +enableSkipYN() doAssert promptYn("True or false", default = true) == true doAssert promptYn("Test with y", default = false) == true diff --git a/tests/tutils.nim b/tests/tutils.nim new file mode 100644 index 0000000..da2529b --- /dev/null +++ b/tests/tutils.nim @@ -0,0 +1,13 @@ +import std/[asyncdispatch, asyncfutures] + +var tests*: seq[Future[void]] = @[] + +template asyncBlock*(body: untyped) = + block: + proc test() {.async.} = + body + + tests.add(test()) + +proc runTests*(): void = + waitFor all tests \ No newline at end of file