Skip to content

Commit

Permalink
Implement the add prj subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
juraj-hrivnak committed Sep 4, 2024
1 parent 3ec1370 commit d06330f
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/commonMain/kotlin/teksturepako/pakku/cli/cmd/Add.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package teksturepako.pakku.cli.cmd

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.terminal
import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.multiple
import com.github.ajalt.clikt.parameters.options.flag
Expand All @@ -15,15 +14,26 @@ import teksturepako.pakku.api.data.LockFile
import teksturepako.pakku.api.platforms.Platform
import teksturepako.pakku.api.projects.Project
import teksturepako.pakku.cli.arg.splitProjectArg
import teksturepako.pakku.cli.cmd.subcmd.Prj
import teksturepako.pakku.cli.resolveDependencies
import teksturepako.pakku.cli.ui.*

class Add : CliktCommand("Add projects")
class Add : CliktCommand("Add projects", allowMultipleSubcommands = true)
{
private val projectArgs: List<String> by argument("projects").multiple(required = true)
private val projectArgs: List<String> by argument("projects", help = "Projects to add").multiple()
private val noDepsFlag: Boolean by option("-D", "--no-deps", help = "Ignore resolving dependencies").flag()

private val flags by findOrSetObject { mutableMapOf<String, Boolean>() }

init
{
this.subcommands(Prj())
}

override fun run(): Unit = runBlocking {
// Pass flags to the context
flags["noDepsFlag"] = noDepsFlag

val lockFile = LockFile.readToResult().getOrElse {
terminal.danger(it.message)
echo()
Expand Down
121 changes: 121 additions & 0 deletions src/commonMain/kotlin/teksturepako/pakku/cli/cmd/subcmd/Prj.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package teksturepako.pakku.cli.cmd.subcmd

import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.parameters.options.option
import com.github.michaelbull.result.fold
import com.github.michaelbull.result.get
import kotlinx.coroutines.runBlocking
import teksturepako.pakku.api.actions.ActionError.NotFoundOnPlatform
import teksturepako.pakku.api.actions.ActionError.ProjNotFound
import teksturepako.pakku.api.actions.createAdditionRequest
import teksturepako.pakku.api.data.LockFile
import teksturepako.pakku.api.platforms.CurseForge
import teksturepako.pakku.api.platforms.Modrinth
import teksturepako.pakku.api.platforms.Platform
import teksturepako.pakku.api.projects.Project
import teksturepako.pakku.cli.arg.splitProjectArg
import teksturepako.pakku.cli.resolveDependencies
import teksturepako.pakku.cli.ui.*

class Prj : CliktCommand("Specify the project precisely")
{
private val cfOpt by option("--cf", "--curseforge")
private val mrOpt by option("--mr", "--modrinth")

private val flags by requireObject<Map<String, Boolean>>()

override fun run(): Unit = runBlocking {
val noDepsFlag = flags.getOrElse("noDepsFlag") { false }

val lockFile = LockFile.readToResult().getOrElse {
terminal.danger(it.message)
echo()
return@runBlocking
}

val platforms: List<Platform> = lockFile.getPlatforms().getOrElse {
terminal.danger(it.message)
echo()
return@runBlocking
}

val projectProvider = lockFile.getProjectProvider().getOrElse {
terminal.danger(it.message)
echo()
return@runBlocking
}

suspend fun add(projectIn: Project?, strict: Boolean = true)
{
suspend fun handleMissingProject(error: NotFoundOnPlatform)
{
val prompt = promptForProject(error.platform, terminal, lockFile)
?: return add(projectIn, strict = false)

val (promptedProject, promptedArgs) = prompt
if (promptedProject == null) return terminal.pError(ProjNotFound(), promptedArgs.first)

(error.project + promptedProject).fold( // Combine projects
failure = { terminal.pError(it) },
success = { add(it) }
)
}

projectIn.createAdditionRequest(
onError = { error ->
terminal.pError(error)

if (error is NotFoundOnPlatform && strict)
{
handleMissingProject(error)
}
},
onSuccess = { project, isRecommended, reqHandlers ->
val projMsg = project.getFullMsg()

if (ynPrompt("Do you want to add $projMsg?", terminal, isRecommended))
{
lockFile.add(project)
lockFile.linkProjectToDependents(project)

if (!noDepsFlag)
{
project.resolveDependencies(terminal, reqHandlers, lockFile, projectProvider, platforms)
}

terminal.pSuccess("$projMsg added")
}
},
lockFile, platforms, strict
)
}

val cf = cfOpt?.let {
val (input, fileId) = splitProjectArg(it)

CurseForge.requestProjectWithFiles(
lockFile.getMcVersions(), lockFile.getLoaders(), input, fileId
)
}

val mr = mrOpt?.let {
val (input, fileId) = splitProjectArg(it)

Modrinth.requestProjectWithFiles(
lockFile.getMcVersions(), lockFile.getLoaders(), input, fileId
)
}

// Combine projects or return just one of them.
val comb = cf?.let { c ->
mr?.let { m ->
(c + m).get() // Combine projects if project is available from both platforms.
} ?: c // Return the CurseForge project if Modrinth project is missing.
} ?: mr // Return the Modrinth project if CurseForge project is missing.

add(comb)
echo()

lockFile.write()?.let { terminal.pError(it) }
}
}

0 comments on commit d06330f

Please sign in to comment.