From adcb315b724fa753c807b3c14a30663e2999e9ea Mon Sep 17 00:00:00 2001 From: Inaki Villar Date: Wed, 2 Sep 2026 14:07:52 -0700 Subject: [PATCH] fix: refactor cli version overrides to explicit options object --- .../cli/GenerateProjectRequest.kt | 17 +++----- .../github/cdsap/projectgenerator/cli/Main.kt | 10 +++-- .../projectgenerator/cli/VersionsResolver.kt | 37 +++++++++------- .../cli/GenerateProjectsCliTest.kt | 40 ++++++++++------- .../cli/VersionsResolverTest.kt | 43 +++++++++---------- 5 files changed, 77 insertions(+), 70 deletions(-) diff --git a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectRequest.kt b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectRequest.kt index 99b2220c..3ab2e77a 100644 --- a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectRequest.kt +++ b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectRequest.kt @@ -3,7 +3,6 @@ package io.github.cdsap.projectgenerator.cli import com.github.ajalt.clikt.core.UsageError import io.github.cdsap.projectgenerator.ProjectGenerator import io.github.cdsap.projectgenerator.model.ClassesPerModule -import io.github.cdsap.projectgenerator.model.DependencyInjection import io.github.cdsap.projectgenerator.model.Gradle import io.github.cdsap.projectgenerator.model.Language import io.github.cdsap.projectgenerator.model.Shape @@ -56,18 +55,15 @@ data class GenerateProjectRequest( generateUnitTest: Boolean, cliGradle: String?, develocityFlag: Boolean, - develocityUrl: String?, versionsFile: VersionsFile?, outputDir: String?, projectName: String?, - dependencyInjection: DependencyInjection, - roomDatabase: Boolean, - kotlinMultiplatformLibrary: Boolean + versionsOverrides: VersionsOverrides ): GenerateProjectRequest { validateAndroidOnlyFeatures( typeOfProjectRequested = typeOfProjectRequested, - roomDatabase = roomDatabase, - kotlinMultiplatformLibrary = kotlinMultiplatformLibrary + roomDatabase = versionsOverrides.roomDatabase, + kotlinMultiplatformLibrary = versionsOverrides.kotlinMultiplatformLibrary ) val resolvedProjectName = resolveProjectName( projectName, @@ -83,17 +79,14 @@ data class GenerateProjectRequest( classesPerModule = classesPerModule, versions = VersionsResolver.resolve( fileVersions = versionsFile, - dependencyInjection = dependencyInjection, - develocityUrl = develocityUrl, - roomDatabase = roomDatabase, - kotlinMultiplatformLibrary = kotlinMultiplatformLibrary + overrides = versionsOverrides ), typeOfStringResources = typeOfStringResources, layers = layers, generateUnitTest = generateUnitTest, gradle = resolveGradle(cliGradle, versionsFile), projectRootPath = resolveProjectRootPath(outputDir, language, resolvedProjectName), - develocity = resolveDevelocityEnabled(develocityFlag, develocityUrl), + develocity = resolveDevelocityEnabled(develocityFlag, versionsOverrides.develocityUrl), projectName = resolvedProjectName ) } diff --git a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/Main.kt b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/Main.kt index 5ffe3663..9a055cc4 100644 --- a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/Main.kt +++ b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/Main.kt @@ -69,13 +69,15 @@ class GenerateProjects : CliktCommand(name = "generate-project") { generateUnitTest = generateUnitTest, cliGradle = gradle, develocityFlag = develocity, - develocityUrl = develocityUrl, versionsFile = versionsFile?.let(VersionsParser::fromFile), outputDir = outputDir, projectName = projectName, - dependencyInjection = DependencyInjection.valueOf(di.uppercase()), - roomDatabase = roomDatabase, - kotlinMultiplatformLibrary = kotlinMultiplatformLibrary + versionsOverrides = VersionsOverrides( + dependencyInjection = DependencyInjection.valueOf(di.uppercase()), + develocityUrl = develocityUrl, + roomDatabase = roomDatabase, + kotlinMultiplatformLibrary = kotlinMultiplatformLibrary + ) ).toProjectGenerator().write() } } diff --git a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolver.kt b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolver.kt index 6ecc080d..2d95c596 100644 --- a/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolver.kt +++ b/cli/src/main/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolver.kt @@ -4,28 +4,23 @@ import io.github.cdsap.projectgenerator.model.DependencyInjection import io.github.cdsap.projectgenerator.model.Versions import io.github.cdsap.projectgenerator.model.VersionsFile -object VersionsResolver { - fun resolve( - fileVersions: VersionsFile?, - dependencyInjection: DependencyInjection, - develocityUrl: String?, - roomDatabase: Boolean, - kotlinMultiplatformLibrary: Boolean - ): Versions { - val versions = if (fileVersions != null) { - fileVersions.resolve() - } else { - Versions() - } - // CLI flags only enable features; false must not clear values from --versions-file. - var androidConfig = versions.android +// CLI-only: false / null means "do not override" so --versions-file values stay intact. +// dependencyInjection is always taken from the CLI (Clikt always supplies a value). +data class VersionsOverrides( + val dependencyInjection: DependencyInjection, + val develocityUrl: String?, + val roomDatabase: Boolean, + val kotlinMultiplatformLibrary: Boolean +) { + fun applyTo(base: Versions): Versions { + var androidConfig = base.android if (roomDatabase) { androidConfig = androidConfig.copy(roomDatabase = true) } if (kotlinMultiplatformLibrary) { androidConfig = androidConfig.copy(kotlinMultiplatformLibrary = true) } - val withAndroidFlags = versions.copy(android = androidConfig, di = dependencyInjection) + val withAndroidFlags = base.copy(android = androidConfig, di = dependencyInjection) return if (develocityUrl != null) { withAndroidFlags.copy(project = withAndroidFlags.project.copy(develocityUrl = develocityUrl)) } else { @@ -33,3 +28,13 @@ object VersionsResolver { } } } + +object VersionsResolver { + fun resolve( + fileVersions: VersionsFile?, + overrides: VersionsOverrides + ): Versions { + val base = fileVersions?.resolve() ?: Versions() + return overrides.applyTo(base) + } +} diff --git a/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectsCliTest.kt b/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectsCliTest.kt index 97d5754e..84cd378e 100644 --- a/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectsCliTest.kt +++ b/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/GenerateProjectsCliTest.kt @@ -63,13 +63,15 @@ class GenerateProjectsCliTest { generateUnitTest = false, cliGradle = null, develocityFlag = false, - develocityUrl = null, versionsFile = null, outputDir = null, projectName = null, - dependencyInjection = DependencyInjection.HILT, - roomDatabase = true, - kotlinMultiplatformLibrary = false + versionsOverrides = VersionsOverrides( + dependencyInjection = DependencyInjection.HILT, + develocityUrl = null, + roomDatabase = true, + kotlinMultiplatformLibrary = false + ) ) } assertTrue(error.message?.contains("--room-database is only available when --type android.") == true) @@ -89,13 +91,15 @@ class GenerateProjectsCliTest { generateUnitTest = false, cliGradle = null, develocityFlag = false, - develocityUrl = null, versionsFile = null, outputDir = null, projectName = null, - dependencyInjection = DependencyInjection.HILT, - roomDatabase = false, - kotlinMultiplatformLibrary = true + versionsOverrides = VersionsOverrides( + dependencyInjection = DependencyInjection.HILT, + develocityUrl = null, + roomDatabase = false, + kotlinMultiplatformLibrary = true + ) ) } assertTrue( @@ -187,13 +191,15 @@ class GenerateProjectsCliTest { generateUnitTest = false, cliGradle = null, develocityFlag = false, - develocityUrl = "https://develocity.example", versionsFile = null, outputDir = null, projectName = "named", - dependencyInjection = DependencyInjection.HILT, - roomDatabase = false, - kotlinMultiplatformLibrary = false + versionsOverrides = VersionsOverrides( + dependencyInjection = DependencyInjection.HILT, + develocityUrl = "https://develocity.example", + roomDatabase = false, + kotlinMultiplatformLibrary = false + ) ) assertTrue(request.develocity) @@ -218,13 +224,15 @@ class GenerateProjectsCliTest { generateUnitTest = false, cliGradle = null, develocityFlag = false, - develocityUrl = null, versionsFile = null, outputDir = null, projectName = null, - dependencyInjection = DependencyInjection.HILT, - roomDatabase = false, - kotlinMultiplatformLibrary = false + versionsOverrides = VersionsOverrides( + dependencyInjection = DependencyInjection.HILT, + develocityUrl = null, + roomDatabase = false, + kotlinMultiplatformLibrary = false + ) ) assertEquals("jvmTriangle12modules", request.projectName) diff --git a/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolverTest.kt b/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolverTest.kt index e6c352ac..b2565ddf 100644 --- a/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolverTest.kt +++ b/cli/src/test/kotlin/io/github/cdsap/projectgenerator/cli/VersionsResolverTest.kt @@ -15,30 +15,31 @@ class VersionsResolverTest { fun `resolve uses defaults when versions file is absent`() { val resolved = VersionsResolver.resolve( fileVersions = null, - dependencyInjection = DependencyInjection.HILT, - develocityUrl = null, - roomDatabase = false, - kotlinMultiplatformLibrary = false + overrides = VersionsOverrides( + dependencyInjection = DependencyInjection.HILT, + develocityUrl = null, + roomDatabase = false, + kotlinMultiplatformLibrary = false + ) ) assertEquals(Versions(), resolved) } @Test - fun `resolve keeps versions-file values when cli overrides are absent`() { - val fileVersions = VersionsFile( + fun `applyTo keeps versions-file values when cli overrides are absent`() { + val base = VersionsFile( project = Project(develocityUrl = "https://develocity.example"), android = Android(roomDatabase = true, kotlinMultiplatformLibrary = true), di = DependencyInjection.METRO - ) + ).resolve() - val resolved = VersionsResolver.resolve( - fileVersions = fileVersions, + val resolved = VersionsOverrides( dependencyInjection = DependencyInjection.HILT, develocityUrl = null, roomDatabase = false, kotlinMultiplatformLibrary = false - ) + ).applyTo(base) assertEquals("https://develocity.example", resolved.project.develocityUrl) assertTrue(resolved.android.roomDatabase) @@ -47,20 +48,19 @@ class VersionsResolverTest { } @Test - fun `resolve applies cli overrides for develocity room kmp and di`() { - val fileVersions = VersionsFile( + fun `applyTo applies cli overrides for develocity room kmp and di`() { + val base = VersionsFile( project = Project(develocityUrl = "https://from-file.example"), android = Android(roomDatabase = false, kotlinMultiplatformLibrary = false), di = DependencyInjection.HILT - ) + ).resolve() - val resolved = VersionsResolver.resolve( - fileVersions = fileVersions, + val resolved = VersionsOverrides( dependencyInjection = DependencyInjection.NONE, develocityUrl = "https://from-cli.example", roomDatabase = true, kotlinMultiplatformLibrary = true - ) + ).applyTo(base) assertEquals("https://from-cli.example", resolved.project.develocityUrl) assertTrue(resolved.android.roomDatabase) @@ -69,18 +69,17 @@ class VersionsResolverTest { } @Test - fun `resolve does not clear file android flags when cli flags are false`() { - val fileVersions = VersionsFile( + fun `applyTo does not clear file android flags when cli flags are false`() { + val base = VersionsFile( android = Android(roomDatabase = true, kotlinMultiplatformLibrary = true) - ) + ).resolve() - val resolved = VersionsResolver.resolve( - fileVersions = fileVersions, + val resolved = VersionsOverrides( dependencyInjection = DependencyInjection.METRO, develocityUrl = null, roomDatabase = false, kotlinMultiplatformLibrary = false - ) + ).applyTo(base) assertTrue(resolved.android.roomDatabase) assertTrue(resolved.android.kotlinMultiplatformLibrary)