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

Commit ce42036

Browse files
authored
Update project verifier to ensure that all build file projects are also present in settings includes (#81)
* Spotless * Detekt
1 parent 840f4b1 commit ce42036

File tree

1 file changed

+74
-6
lines changed

1 file changed

+74
-6
lines changed

src/main/kotlin/slack/cli/gradle/GradleSettingsVerifierCli.kt

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616
package slack.cli.gradle
1717

1818
import com.github.ajalt.clikt.core.CliktCommand
19+
import com.github.ajalt.clikt.parameters.options.flag
20+
import com.github.ajalt.clikt.parameters.options.multiple
1921
import com.github.ajalt.clikt.parameters.options.option
2022
import com.github.ajalt.clikt.parameters.options.required
2123
import com.github.ajalt.clikt.parameters.types.path
2224
import com.google.auto.service.AutoService
2325
import java.io.File
26+
import java.nio.file.Path
2427
import kotlin.io.path.ExperimentalPathApi
28+
import kotlin.io.path.absolute
29+
import kotlin.io.path.deleteRecursively
2530
import kotlin.io.path.exists
2631
import kotlin.io.path.isDirectory
2732
import kotlin.io.path.name
@@ -30,6 +35,7 @@ import kotlin.io.path.relativeTo
3035
import kotlin.system.exitProcess
3136
import slack.cli.CommandFactory
3237
import slack.cli.projectDirOption
38+
import slack.cli.skipBuildAndCacheDirs
3339

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

68+
private val implicitPaths by
69+
option(
70+
"--implicit-path",
71+
"-i",
72+
help =
73+
"Implicit project names that may not be present in the settings file but should be assumed present."
74+
)
75+
.multiple()
76+
77+
private val deleteUnIncludedPaths by
78+
option(
79+
"--delete-un-included-paths",
80+
"-d",
81+
help = "Delete any paths that are not included in the settings file."
82+
)
83+
.flag()
84+
85+
private fun resolveProjectFromGradlePath(relativePath: String): Path {
86+
val gradlePath = relativePath.removePrefix(":").removeSuffix(":").replace(":", File.separator)
87+
return projectDir.resolve(gradlePath)
88+
}
89+
90+
@Suppress("LongMethod")
6291
@ExperimentalPathApi
6392
override fun run() {
93+
val implicitPaths = implicitPaths.associateWith { resolveProjectFromGradlePath(it) }
94+
val projectsViaBuildFiles =
95+
projectDir
96+
.absolute()
97+
.toFile()
98+
.walkTopDown()
99+
.skipBuildAndCacheDirs()
100+
.filter { it.name == "build.gradle.kts" }
101+
.associate {
102+
val path = it.toPath()
103+
// Get the gradle path relative to the root project dir as the key
104+
val gradlePath =
105+
":" +
106+
path.parent // project dir
107+
.relativeTo(projectDir)
108+
.toString()
109+
.replace(File.separator, ":")
110+
gradlePath to path
111+
}
112+
.filterValues { it.parent != projectDir }
113+
.plus(implicitPaths)
114+
64115
val projectPaths =
65116
settingsFile
66117
.readText()
@@ -71,14 +122,14 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
71122
.joinToString("\n")
72123
.removePrefix("include(")
73124
.removeSuffix(")")
74-
.split(",")
125+
.splitToSequence(",")
126+
.associateBy { line -> line.trim().removeSuffix(",").removeSurrounding("\"") }
127+
.plus(implicitPaths.mapValues { "<implicit>" })
75128

76129
val errors = mutableListOf<String>()
77130
@Suppress("LoopWithTooManyJumpStatements")
78-
for (line in projectPaths) {
79-
val path = line.trim().removeSurrounding("\"")
80-
val realPath =
81-
projectDir.resolve(path.removePrefix(":").removeSuffix(":").replace(":", File.separator))
131+
for ((gradlePath, line) in projectPaths) {
132+
val realPath = resolveProjectFromGradlePath(gradlePath)
82133

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

91142
when {
92-
path.endsWith(':') -> {
143+
gradlePath.endsWith(':') -> {
93144
reportError("Project paths should not end with ':'", line.lastIndexOf(':') - 1)
94145
}
95146
!realPath.exists() -> {
@@ -113,6 +164,23 @@ public class GradleSettingsVerifierCli : CliktCommand(help = DESCRIPTION) {
113164
}
114165
}
115166

167+
for ((path, buildFile) in projectsViaBuildFiles) {
168+
if (path !in projectPaths) {
169+
val projectPath = buildFile.parent
170+
if (deleteUnIncludedPaths) {
171+
echo("Deleting un-included project '$path' at $projectPath")
172+
projectPath.deleteRecursively()
173+
} else {
174+
errors += buildString {
175+
appendLine("Project '$path' is present in the filesystem but not in the settings file.")
176+
appendLine("Please add it to the settings file or delete it.")
177+
appendLine(" Project dir:\t${projectPath.relativeTo(projectDir)}")
178+
appendLine(" Build file:\t${buildFile.relativeTo(projectDir)}")
179+
}
180+
}
181+
}
182+
}
183+
116184
if (errors.isNotEmpty()) {
117185
echo("Errors found in '${settingsFile.name}'. Please fix or remove these.", err = true)
118186
echo(errors.joinToString(""), err = true)

0 commit comments

Comments
 (0)