Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add cfg command for projects override #29

Merged
merged 11 commits into from
Oct 1, 2024
1 change: 1 addition & 0 deletions docs/p.tree
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<toc-element topic="pakku-init.md"/>
<toc-element topic="pakku-import.md"/>
<toc-element topic="pakku-set.md"/>
<toc-element topic="pakku-cfg.md"/>
<toc-element topic="pakku-add.md">
<toc-element topic="pakku-add-prj.md"/>
</toc-element>
Expand Down
3 changes: 2 additions & 1 deletion docs/topics/Config-File.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ modpack export.

`projects`
: A list of project slugs, names, IDs or filenames from the [lock file](Lock-File.md)
with properties you want to change.
with properties you want to change.
You can use [cfg](pakku-cfg.md) command to change the properties as well.
47 changes: 47 additions & 0 deletions docs/topics/pakku-cfg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# pakku cfg

Configure various options of your modpack or projects

## Usage

<snippet id="snippet-cmd">

<var name="cmd">cfg</var>
<var name="params">[&lt;options&gt;] [&lt;projects&gt;]...</var>
<include from="_template_cmd.md" element-id="template-cmd"/>

</snippet>

## Arguments

<snippet id="snippet-args">

`[<projects>]...`
: The `projects` argument.

</snippet>

## Options

<snippet id="snippet-options-all">

<snippet id="snippet-options">

`-s`, `--side`
: Change the side of a project.

`-u`, `--update-strategy`
: Change the update strategy of a project.

`-r`, `--redistributable`
: Change whether the project can be redistributed.

`-p`, `--subpath`
: Change the subpath of the project.

</snippet>

`-h`, `--help`
: Show this message and exit

</snippet>
8 changes: 4 additions & 4 deletions docs/topics/pakku-set.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Set various properties of your modpack or projects
<snippet id="snippet-args">

`[<projects>]...`
: The `projects` argument
: The `projects` argument. **Deprecated, use [cfg](pakku-cfg.md) command or config file instead**

</snippet>

Expand All @@ -28,13 +28,13 @@ Set various properties of your modpack or projects
<snippet id="snippet-options">

`-s`, `--side`
: Change the side of a project
: Change the side of a project. **Deprecated, use [cfg](pakku-cfg.md) command or config file instead**

`-u`, `--update-strategy`
: Change the update strategy of a project
: Change the update strategy of a project. **Deprecated, use [cfg](pakku-cfg.md) command or config file instead**

`-r`, `--redistributable`
: Change whether the project can be redistributed
: Change whether the project can be redistributed. **Deprecated, use [cfg](pakku-cfg.md) command or config file instead**

`-t`, `--target`
: Change the target of the pack
Expand Down
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/teksturepako/pakku/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun main(args: Array<String>)
Pakku().context {
terminal = cliConfig?.toTerminal() ?: Terminal(theme = CliThemes.Default)
}.subcommands(
Init(), Import(), Set(), Add(), Rm(), Status(), Update(), Ls(), Fetch(), Link(), Export(), Diff()
Init(), Import(), Set(), Add(), Rm(), Cfg(), Status(), Update(), Ls(), Fetch(), Link(), Export(), Diff()
).main(args)

// Check Modrinth's rate limit
Expand Down
10 changes: 5 additions & 5 deletions src/commonMain/kotlin/teksturepako/pakku/api/data/ConfigFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ data class ConfigFile(

@Serializable
data class ProjectConfig(
var type: ProjectType?,
var side: ProjectSide?,
@SerialName("update_strategy") var updateStrategy: UpdateStrategy?,
@SerialName("redistributable") var redistributable: Boolean?,
var subpath: String?
var type: ProjectType? = null,
var side: ProjectSide? = null,
@SerialName("update_strategy") var updateStrategy: UpdateStrategy? = null,
@SerialName("redistributable") var redistributable: Boolean? = null,
var subpath: String? = null
)

// -- FILE I/O --
Expand Down
102 changes: 102 additions & 0 deletions src/commonMain/kotlin/teksturepako/pakku/cli/cmd/Cfg.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package teksturepako.pakku.cli.cmd

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.core.terminal
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.multiple
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.types.boolean
import com.github.ajalt.clikt.parameters.types.choice
import kotlinx.coroutines.runBlocking
import teksturepako.pakku.api.actions.ActionError
import teksturepako.pakku.api.data.ConfigFile
import teksturepako.pakku.api.data.LockFile
import teksturepako.pakku.api.projects.ProjectSide
import teksturepako.pakku.api.projects.UpdateStrategy
import teksturepako.pakku.cli.ui.pError

class Cfg : CliktCommand()
{
override val printHelpOnEmptyArgs = true

override fun help(context: Context) = "Configure various options of your modpack or projects"

// -- PROJECTS --

private val projectArgs: List<String> by argument("projects").multiple()
SettingDust marked this conversation as resolved.
Show resolved Hide resolved

SettingDust marked this conversation as resolved.
Show resolved Hide resolved
private val sideOpt: String? by option("-s", "--side")
.help("Change the side of a project")
.choice("client", "server", "both", ignoreCase = true)
SettingDust marked this conversation as resolved.
Show resolved Hide resolved

private val updateStrategyOpt: String? by option("-u", "--update-strategy")
.help("Change the update strategy of a project")
.choice("latest", "none", ignoreCase = true)

private val redistributableOpt: Boolean? by option("-r", "--redistributable")
.help("Change whether the project can be redistributed")
.boolean()

private val subpathOpt: String? by option("-p", "--subpath")
.help("Change the subpath of the project")

override fun run() = runBlocking {
val lockFile = LockFile.readToResult().getOrElse {
terminal.danger(it.message)
echo()
return@runBlocking
}
val configFile = ConfigFile.readOrNew()

// -- PROJECTS --

if (projectArgs.isNotEmpty())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this if expression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming the name, version and others will be added to this command

{
val projects = configFile.getProjects()

for (arg in projectArgs)
{
val project = lockFile.getProject(arg)
if (project == null)
{
terminal.pError(ActionError.ProjNotFound(), arg)
continue
}
val projectConfig = projects.getOrPut(arg) {
SettingDust marked this conversation as resolved.
Show resolved Hide resolved
ConfigFile.ProjectConfig()
}

projectConfig.apply {
sideOpt?.let { opt ->
ProjectSide.valueOf(opt.uppercase())
}?.let {
side = it
terminal.success("'side' set to '$it' for $arg")
}

updateStrategyOpt?.let { opt ->
UpdateStrategy.valueOf(opt.uppercase())
}?.let {
updateStrategy = it
terminal.success("'update_strategy' set to '$it' for $arg")
}

redistributableOpt?.let { opt ->
redistributable = opt
terminal.success("'redistributable' set to '$opt' for $arg")
}

subpathOpt?.let { opt ->
subpath = opt
terminal.success("'subpath' set to '$opt' for $arg")
}
}
}
}

lockFile.write()
configFile.write()
SettingDust marked this conversation as resolved.
Show resolved Hide resolved
echo()
}
}
12 changes: 9 additions & 3 deletions src/commonMain/kotlin/teksturepako/pakku/cli/cmd/Set.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,31 @@ import teksturepako.pakku.api.projects.UpdateStrategy

class Set : CliktCommand()
{
override val printHelpOnEmptyArgs = true

override fun help(context: Context) = "Set various properties of your modpack or projects"

// -- PROJECTS --

private val projectArgs: List<String> by argument("projects").multiple()
private val projectArgs: List<String> by argument(
"projects",
help = "Use the config file (pakku.json) or 'cfg' command instead."
SettingDust marked this conversation as resolved.
Show resolved Hide resolved
).multiple()

private val sideOpt: String? by option("-s", "--side")
.help("Change the side of a project")
.choice("client", "server", "both", ignoreCase = true)
.deprecated("Use the config file (pakku.json) instead.")
.deprecated("Use the config file (pakku.json) or 'cfg' command instead.")

private val updateStrategyOpt: String? by option("-u", "--update-strategy")
.help("Change the update strategy of a project")
.choice("latest", "none", ignoreCase = true)
.deprecated("Use the config file (pakku.json) or 'cfg' command instead.")

private val redistributableOpt: Boolean? by option("-r", "--redistributable")
.help("Change whether the project can be redistributed")
.boolean()
.deprecated("Use the config file (pakku.json) instead.")
.deprecated("Use the config file (pakku.json) or 'cfg' command instead.")

// -- PACK --

Expand Down
66 changes: 66 additions & 0 deletions src/commonTest/kotlin/teksturepako/pakku/cli/cmd/CfgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package teksturepako.pakku.cli.cmd

import com.github.ajalt.clikt.testing.test
import com.github.michaelbull.result.runCatching
import kotlinx.coroutines.runBlocking
import teksturepako.pakku.api.data.ConfigFile
import teksturepako.pakku.api.data.LockFile
import teksturepako.pakku.api.data.workingPath
import teksturepako.pakku.api.projects.Project
import teksturepako.pakku.api.projects.ProjectSide
import teksturepako.pakku.api.projects.ProjectType
import teksturepako.pakku.api.projects.UpdateStrategy
import kotlin.io.path.*
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

@OptIn(ExperimentalPathApi::class)
class CfgTest
{
init
{
workingPath = "./build/test"
runCatching { Path("./build/test").deleteRecursively() }
runCatching { Path("./build/test").createDirectory() }
}

@Test
fun `should fail without lock file`()
{
val cmd = Cfg()
val output = cmd.test("test -p test").output

assertContains(output, "Can't find project 'test'")
}

@Test
fun `should success with lock file & project`()
{
runBlocking {
val lockFile = LockFile.readOrNew()
lockFile.add(
Project(
type = ProjectType.MOD,
slug = mutableMapOf("modrinth" to "test"),
name = mutableMapOf("modrinth" to "Test"),
id = mutableMapOf("modrinth" to "test"),
files = mutableSetOf()
)
)
lockFile.write()
}

val cmd = Cfg()
val output = cmd.test("test -p test -s both -u latest -r true")
assertEquals("", output.stderr, "Command failed to execute")
assertNotNull(ConfigFile.readOrNull(), "Config file should be created")
val config = ConfigFile.readOrNull()!!.getProjects()["test"]
assertNotNull(config, "Project config should be created")
assertEquals(UpdateStrategy.LATEST, config.updateStrategy)
assertEquals(true, config.redistributable)
assertEquals("test", config.subpath)
assertEquals(ProjectSide.BOTH, config.side)
}
}
SettingDust marked this conversation as resolved.
Show resolved Hide resolved