Skip to content

Commit

Permalink
Refactor remove command
Browse files Browse the repository at this point in the history
  • Loading branch information
juraj-hrivnak committed Jan 30, 2024
1 parent 4605d8f commit e8eb53c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 84 deletions.
41 changes: 8 additions & 33 deletions src/main/kotlin/teksturepako/pakku/api/actions/Addition.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import teksturepako.pakku.api.data.json
import teksturepako.pakku.api.platforms.Platform
import teksturepako.pakku.api.projects.Project

data class RequestHandlers(
val onError: ErrorBlock,
val onRetry: RetryBlock,
val onSuccess: SuccessBlock
)

suspend fun Project?.createAdditionRequest(
onError: ErrorBlock,
onRetry: RetryBlock,
Expand All @@ -15,13 +21,13 @@ suspend fun Project?.createAdditionRequest(
)
{
// Exist
var project = this ?: return onError.error(Error.ProjectNotFound("Project not found"))
var project = this ?: return onError.error(Error.ProjNotFound("Project not found"))
var isRecommended = true

// Already added
if (pakkuLock.isProjectAdded(project))
{
return onError.error(Error.CouldNotAdd("Could not add ${project.slug}. It is already added"))
return onError.error(Error.AlreadyAdded("Could not add ${project.slug}. It is already added"))
}

for (platform in platforms)
Expand Down Expand Up @@ -62,34 +68,3 @@ suspend fun Project?.createAdditionRequest(

onSuccess.success(project, isRecommended, RequestHandlers(onError, onRetry, onSuccess))
}

data class RequestHandlers(
val onError: ErrorBlock,
val onRetry: RetryBlock,
val onSuccess: SuccessBlock
)

sealed class Error(val message: String)
{
class ProjectNotFound(message: String) : Error(message)
class CouldNotAdd(message: String) : Error(message)
class NotFoundOnPlatform(message: String) : Error(message)
class NoFilesOnPlatform(message: String) : Error(message)
class NoFiles(message: String) : Error(message)
class FileNamesDoNotMatch(message: String) : Error(message)
}

fun interface ErrorBlock
{
suspend fun error(error: Error)
}

fun interface RetryBlock
{
suspend fun retryWith(platform: Platform): Project?
}

fun interface SuccessBlock
{
suspend fun success(project: Project, isRecommended: Boolean, ctx: RequestHandlers)
}
51 changes: 51 additions & 0 deletions src/main/kotlin/teksturepako/pakku/api/actions/Removal.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package teksturepako.pakku.api.actions

import teksturepako.pakku.api.data.PakkuLock
import teksturepako.pakku.api.projects.Project
import teksturepako.pakku.typoSuggester

suspend fun Project?.createRemovalRequest(
onWarning: WarningBlock,
onRemoval: RemovalBlock,
onDepRemoval: RemovalBlock,
projectArg: String,
pakkuLock: PakkuLock,
)
{
if (this != null)
{
val linkedProjects = pakkuLock.getLinkedProjects(this.pakkuId!!, ignore = this)

if (linkedProjects.isEmpty())
{
onRemoval.remove(this, true)
}
else
{
onWarning.warning("$projectArg is required by ${linkedProjects.map { it.slug }}")
onRemoval.remove(this, false)
}

x@ for (pakkuLink in this.pakkuLinks)
{
val dependency = pakkuLock.getProjectByPakkuId(pakkuLink) ?: continue@x
val depLinkedProjects = pakkuLock.getLinkedProjects(dependency.pakkuId!!)

if (depLinkedProjects.isNotEmpty())
{
onWarning.warning("${dependency.slug} is required by ${depLinkedProjects.map { it.slug }}")
onDepRemoval.remove(dependency, false)
}
else onDepRemoval.remove(dependency, true)
}
}
else
{
onWarning.warning("$projectArg not found")
val slugs = pakkuLock.getAllProjects().flatMap { it.slug.values }

typoSuggester(projectArg, slugs).firstOrNull()?.let { arg ->
onWarning.warning("Did you mean $arg?")
}
}
}
29 changes: 29 additions & 0 deletions src/main/kotlin/teksturepako/pakku/api/actions/RequestHandlers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package teksturepako.pakku.api.actions

import teksturepako.pakku.api.platforms.Platform
import teksturepako.pakku.api.projects.Project

fun interface WarningBlock
{
suspend fun warning(message: String)
}

fun interface ErrorBlock
{
suspend fun error(error: Error)
}

fun interface RetryBlock
{
suspend fun retryWith(platform: Platform): Project?
}

fun interface SuccessBlock
{
suspend fun success(project: Project, isRecommended: Boolean, ctx: RequestHandlers)
}

fun interface RemovalBlock
{
suspend fun remove(project: Project, isRecommended: Boolean)
}
80 changes: 29 additions & 51 deletions src/main/kotlin/teksturepako/pakku/cli/cmd/Rm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import com.github.ajalt.clikt.parameters.arguments.multiple
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.mordant.terminal.YesNoPrompt
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import teksturepako.pakku.api.actions.createRemovalRequest
import teksturepako.pakku.api.data.PakkuLock
import teksturepako.pakku.typoSuggester

class Rm : CliktCommand("Remove projects")
{
private val projectArgs: List<String> by argument("projects").multiple()
private val allFlag: Boolean by option("-a", "--all", help = "Remove all mods").flag()
private val allFlag: Boolean by option("-a", "--all", help = "Remove all projects").flag()

override fun run() = runBlocking {
val pakkuLock = PakkuLock.readToResult().getOrElse {
Expand All @@ -34,62 +33,41 @@ class Rm : CliktCommand("Remove projects")
echo()
}
}
else for (deferred in projectArgs.map { arg ->
async {
pakkuLock.getProject(arg) to arg
}
else for (pair in projectArgs.map { arg ->
pakkuLock.getProject(arg) to arg
})
{
val (project, arg) = deferred.await()

if (project != null)
{
val linkedProjects = pakkuLock.getLinkedProjects(project.pakkuId!!, ignore = project)

if (linkedProjects.isEmpty())
{
if (YesNoPrompt("Do you want to remove ${project.slug}?", terminal, true).ask() == false) continue
}
else
{
terminal.warning("$arg is required by ${linkedProjects.map { it.slug }}")
if (YesNoPrompt("Do you want to remove it?", terminal, false).ask() == false) continue
}
val (projectIn, arg) = pair

pakkuLock.remove(project)
terminal.danger("${project.slug} removed")

dependencies@ for (pakkuLink in project.pakkuLinks)
{
val dep = pakkuLock.getProjectByPakkuId(pakkuLink) ?: continue@dependencies
val linkedProjects2 = pakkuLock.getLinkedProjects(dep.pakkuId!!)

if (linkedProjects2.isNotEmpty())
projectIn.createRemovalRequest(
onWarning = { warning -> terminal.warning(warning) },
onRemoval = { project, isRecommended ->
if (YesNoPrompt("Do you want to remove ${project.slug}?", terminal, isRecommended).ask() == true)
{
terminal.warning("${dep.slug} is required by ${linkedProjects2.map { it.slug }}")
if (YesNoPrompt("Do you want to remove it?", terminal, false).ask() == false)
continue@dependencies
pakkuLock.remove(project)
pakkuLock.removePakkuLinkFromAllProjects(project.pakkuId!!)
terminal.danger("${project.slug} removed")
}

pakkuLock.remove(dep)
pakkuLock.removePakkuLink(dep.pakkuId!!)
terminal.danger("${dep.slug} removed")
}

pakkuLock.removePakkuLink(project.pakkuId!!)
}
else
{
terminal.warning("$arg not found")
pakkuLock.getAllProjects().flatMap { it.slug.values }.also { args ->
typoSuggester(arg, args).firstOrNull()?.let { arg ->
terminal.warning("Did you mean $arg?")
},
onDepRemoval = { dependency, isRecommended ->
if (isRecommended)
{
pakkuLock.remove(dependency)
pakkuLock.removePakkuLinkFromAllProjects(dependency.pakkuId!!)
terminal.info("${dependency.slug} removed")
}
}
}
else if (YesNoPrompt("Do you want to remove ${dependency.slug}?", terminal, false).ask() == true)
{
pakkuLock.remove(dependency)
pakkuLock.removePakkuLinkFromAllProjects(dependency.pakkuId!!)
terminal.info("${dependency.slug} removed")
}
},
arg, pakkuLock
)

echo()
}

pakkuLock.write()
}
}

0 comments on commit e8eb53c

Please sign in to comment.