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

@@ -90,7 +90,7 @@ class GitRepositoryRuntime private constructor(
runGit(nativeGit, sandbox, listOf("checkout", "-B", desired.headBranch))
}
materializeNativeGitState(nativeGit, sandbox, desired, level.id)
materializeNativeGitState(nativeGit, sandbox, desired, level)
}
return inspectSandbox(level)
@@ -443,16 +443,14 @@ class GitRepositoryRuntime private constructor(
return body
}
private fun materializeNativeGitState(nativeGit: File, sandbox: File, desired: RepoState, levelId: String) {
if (levelId == "push") {
materializeNativePushLevel(nativeGit, sandbox)
return
}
if (materializeNativeLevelFixture(levelId, sandbox) { directory, arguments ->
private fun materializeNativeGitState(nativeGit: File, sandbox: File, desired: RepoState, level: Level) {
level.nativeSetup?.let { setup ->
val nativeSetup = NativeLevelSetup(sandbox) { directory, arguments ->
runGit(nativeGit, directory, arguments).exitCode
}
) {
return
if (nativeSetup.setup()) {
return
}
}
desired.config.forEach { (key, value) ->
@@ -506,62 +504,6 @@ class GitRepositoryRuntime private constructor(
}
}
private fun materializeNativePushLevel(nativeGit: File, sandbox: File) {
sandbox.listFiles()
?.filterNot { it.name == ".git" }
?.forEach { it.deleteRecursively() }
fun writeFile(name: String, content: String = "$name\n") {
File(sandbox, name).apply {
parentFile?.mkdirs()
writeText(content)
}
}
fun commitIn(directory: File, message: String, vararg paths: String) {
runGit(nativeGit, directory, listOf("add") + paths)
runGit(nativeGit, directory, listOf("commit", "-m", message))
}
writeFile("file1")
commitIn(sandbox, "First commit", "file1")
writeFile("file2")
commitIn(sandbox, "Second commit", "file2")
val parent = sandbox.parentFile ?: sandbox
val remoteDir = File(parent, "${sandbox.name}-origin.git")
val remoteWorkTree = File(parent, "${sandbox.name}-origin-work")
remoteDir.deleteRecursively()
remoteWorkTree.deleteRecursively()
remoteDir.mkdirs()
remoteWorkTree.mkdirs()
runGit(nativeGit, remoteDir, listOf("init", "--bare", "-b", "master"))
runGit(nativeGit, sandbox, listOf("remote", "add", "push-setup-origin", remoteDir.absolutePath))
runGit(nativeGit, sandbox, listOf("push", "push-setup-origin", "master"))
runGit(nativeGit, sandbox, listOf("remote", "remove", "push-setup-origin"))
fun runRemoteGit(arguments: List<String>): ProcessExecutionResult {
return runGit(
nativeGit,
sandbox,
listOf("--git-dir", remoteDir.absolutePath, "--work-tree", remoteWorkTree.absolutePath) + arguments,
)
}
runRemoteGit(listOf("checkout", "-f", "master"))
File(remoteWorkTree, "file4").writeText("file4\n")
runRemoteGit(listOf("add", "file4"))
runRemoteGit(listOf("commit", "-m", "Fourth commit"))
writeFile("file3")
commitIn(sandbox, "Third commit", "file3")
runGit(nativeGit, sandbox, listOf("remote", "add", "origin", remoteDir.absolutePath))
runGit(nativeGit, sandbox, listOf("fetch", "origin"))
runGit(nativeGit, sandbox, listOf("branch", "--set-upstream-to=origin/master", "master"))
runGit(nativeGit, sandbox, listOf("config", "rebase.autoStash", "true"))
File(sandbox, "file3").appendText("local worktree change\n")
}
private fun filesForSetupCommit(files: List<GitFile>, index: Int, commitCount: Int): List<GitFile> {
if (files.isEmpty()) return emptyList()
if (commitCount <= 1) return files