Move native level setups into level files

- Delete NativeLevelFixtures.kt and make native repository setup an optional property of each Level.
- Move every existing native setup into its corresponding level file so setup, validation, and tests stay together.
- Add the missing Blame native setup with config.rb history and a Spider Man password commit.
- Add a native runtime regression that verifies `git blame config.rb` identifies Spider Man on the password line.
- Verify the full JVM test suite using the compiled host Git runtime.
This commit is contained in:
Joe Tretter
2026-05-07 18:53:18 -05:00
parent 7bfb761068
commit 64743ff4a9
30 changed files with 580 additions and 505 deletions

View File

@@ -1,6 +1,7 @@
package solutions.tretter.githugandroid
import androidx.compose.runtime.saveable.listSaver
import java.io.File
enum class PlayMode(val label: String) {
CLI_ONLY("CLI ONLY"),
@@ -46,6 +47,7 @@ data class Level(
val commandSuggestions: List<String>,
val validator: (RepoState, String) -> Boolean,
val setup: () -> RepoState,
val nativeSetup: (NativeLevelSetup.() -> Boolean)? = null,
val testCases: List<LevelTestCase> = emptyList(),
)
@@ -54,6 +56,91 @@ data class LevelTestCase(
val commands: List<String>,
)
class NativeLevelSetup internal constructor(
internal val sandbox: File,
private val runGit: (File, List<String>) -> Int,
) {
fun resetFiles() {
sandbox.listFiles()
?.filterNot { it.name == ".git" }
?.forEach { it.deleteRecursively() }
git("checkout", "-B", "master")
}
fun git(vararg arguments: String): Int = runGit(sandbox, arguments.toList())
fun git(directory: File, vararg arguments: String): Int = runGit(directory, arguments.toList())
fun initRepo(directory: File) {
directory.mkdirs()
val initResult = git(directory, "init", "-b", "master")
if (initResult != 0) {
git(directory, "init")
git(directory, "checkout", "-B", "master")
}
git(directory, "config", "receive.denyCurrentBranch", "ignore")
}
fun write(path: String, content: String = "") {
File(sandbox, path).apply {
parentFile?.mkdirs()
writeText(content)
}
}
fun append(path: String, content: String) {
File(sandbox, path).appendText(content)
}
fun add(vararg paths: String) {
git("add", *paths)
}
fun commit(message: String, author: String? = null) {
if (author == null) {
git("commit", "-m", message)
} else {
git("commit", "--author", author, "-m", message)
}
}
fun addCommit(message: String, vararg paths: String, author: String? = null) {
add(*paths)
commit(message, author)
}
fun writeIn(directory: File, path: String, content: String = "") {
File(directory, path).apply {
parentFile?.mkdirs()
writeText(content)
}
}
fun addCommitIn(directory: File, message: String, vararg paths: String) {
git(directory, "add", *paths)
git(directory, "commit", "-m", message)
}
fun siblingRepo(name: String): File {
val directory = File(sandbox.parentFile ?: sandbox, "${sandbox.name}-$name")
directory.deleteRecursively()
initRepo(directory)
return directory
}
fun checkoutNew(branch: String) {
git("checkout", "-b", branch)
}
fun checkout(branch: String) {
git("checkout", branch)
}
fun tag(name: String) {
git("tag", "-f", name)
}
}
fun sampleLevels(): List<Level> = allGithugLevels()
val RepoStateSaver = listSaver<RepoState, Any>(