Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

Commit

Permalink
Update project verifier to ensure that all build file projects are al…
Browse files Browse the repository at this point in the history
…so present in settings includes (#81)

* Spotless

* Detekt
  • Loading branch information
ZacSweers authored Dec 5, 2023
1 parent 840f4b1 commit ce42036
Showing 1 changed file with 74 additions and 6 deletions.
80 changes: 74 additions & 6 deletions src/main/kotlin/slack/cli/gradle/GradleSettingsVerifierCli.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@
package slack.cli.gradle

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.multiple
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required
import com.github.ajalt.clikt.parameters.types.path
import com.google.auto.service.AutoService
import java.io.File
import java.nio.file.Path
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.absolute
import kotlin.io.path.deleteRecursively
import kotlin.io.path.exists
import kotlin.io.path.isDirectory
import kotlin.io.path.name
Expand All @@ -30,6 +35,7 @@ import kotlin.io.path.relativeTo
import kotlin.system.exitProcess
import slack.cli.CommandFactory
import slack.cli.projectDirOption
import slack.cli.skipBuildAndCacheDirs

/** A CLI that verifies a given settings file has only valid projects. */
public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
Expand Down Expand Up @@ -59,8 +65,53 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
.path(mustExist = true, canBeDir = false)
.required()

private val implicitPaths by
option(
"--implicit-path",
"-i",
help =
"Implicit project names that may not be present in the settings file but should be assumed present."
)
.multiple()

private val deleteUnIncludedPaths by
option(
"--delete-un-included-paths",
"-d",
help = "Delete any paths that are not included in the settings file."
)
.flag()

private fun resolveProjectFromGradlePath(relativePath: String): Path {
val gradlePath = relativePath.removePrefix(":").removeSuffix(":").replace(":", File.separator)
return projectDir.resolve(gradlePath)
}

@Suppress("LongMethod")
@ExperimentalPathApi
override fun run() {
val implicitPaths = implicitPaths.associateWith { resolveProjectFromGradlePath(it) }
val projectsViaBuildFiles =
projectDir
.absolute()
.toFile()
.walkTopDown()
.skipBuildAndCacheDirs()
.filter { it.name == "build.gradle.kts" }
.associate {
val path = it.toPath()
// Get the gradle path relative to the root project dir as the key
val gradlePath =
":" +
path.parent // project dir
.relativeTo(projectDir)
.toString()
.replace(File.separator, ":")
gradlePath to path
}
.filterValues { it.parent != projectDir }
.plus(implicitPaths)

val projectPaths =
settingsFile
.readText()
Expand All @@ -71,14 +122,14 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
.joinToString("\n")
.removePrefix("include(")
.removeSuffix(")")
.split(",")
.splitToSequence(",")
.associateBy { line -> line.trim().removeSuffix(",").removeSurrounding("\"") }
.plus(implicitPaths.mapValues { "<implicit>" })

val errors = mutableListOf<String>()
@Suppress("LoopWithTooManyJumpStatements")
for (line in projectPaths) {
val path = line.trim().removeSurrounding("\"")
val realPath =
projectDir.resolve(path.removePrefix(":").removeSuffix(":").replace(":", File.separator))
for ((gradlePath, line) in projectPaths) {
val realPath = resolveProjectFromGradlePath(gradlePath)

fun reportError(message: String, column: Int) {
errors += buildString {
Expand All @@ -89,7 +140,7 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
}

when {
path.endsWith(':') -> {
gradlePath.endsWith(':') -> {
reportError("Project paths should not end with ':'", line.lastIndexOf(':') - 1)
}
!realPath.exists() -> {
Expand All @@ -113,6 +164,23 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
}
}

for ((path, buildFile) in projectsViaBuildFiles) {
if (path !in projectPaths) {
val projectPath = buildFile.parent
if (deleteUnIncludedPaths) {
echo("Deleting un-included project '$path' at $projectPath")
projectPath.deleteRecursively()
} else {
errors += buildString {
appendLine("Project '$path' is present in the filesystem but not in the settings file.")
appendLine("Please add it to the settings file or delete it.")
appendLine(" Project dir:\t${projectPath.relativeTo(projectDir)}")
appendLine(" Build file:\t${buildFile.relativeTo(projectDir)}")
}
}
}
}

if (errors.isNotEmpty()) {
echo("Errors found in '${settingsFile.name}'. Please fix or remove these.", err = true)
echo(errors.joinToString(""), err = true)
Expand Down

0 comments on commit ce42036

Please sign in to comment.