Auto-commit after successful build: update app gameplay/UI, improve build setup

Changed files:\napp/build.gradle.kts
app/src/main/java/solutions/tretter/githugandroid/GameModels.kt
app/src/main/java/solutions/tretter/githugandroid/GitHelpCommands.kt
app/src/main/java/solutions/tretter/githugandroid/GitHugApp.kt
app/src/main/java/solutions/tretter/githugandroid/GitRuntime.kt
app/src/main/java/solutions/tretter/githugandroid/Visual.kt
app/src/main/java/solutions/tretter/githugandroid/levels/AdvancedLevels.kt
app/src/main/java/solutions/tretter/githugandroid/levels/LevelCatalog.kt
app/src/test/java/solutions/tretter/githugandroid/GitHelpCommandsTest.kt
app/src/test/java/solutions/tretter/githugandroid/GitSandboxEngineTest.kt
This commit is contained in:
Joe Tretter
2026-05-05 19:27:33 -05:00
parent 6200fdc912
commit 16d7809150
10 changed files with 322 additions and 46 deletions

View File

@@ -67,11 +67,12 @@ class GitRepositoryRuntime(private val context: Context) {
val tokens = GitSandboxEngine.tokenizeCommand(command)
if (tokens.isEmpty()) return inspectSandbox(level).copy(currentDir = currentRepo.currentDir) to emptyList()
val expandedTokens = expandShellPathspecs(currentRepo, tokens)
val result = when (tokens.first()) {
"git" -> currentRepo to runGit(nativeGit, workingDir, tokens.drop(1)).outputLines
val result = when (expandedTokens.first()) {
"git" -> currentRepo to runGit(nativeGit, workingDir, expandedTokens.drop(1)).outputLines
"help", "?" -> currentRepo to commandReferenceLines()
else -> executeHelperCommand(sandboxRoot, workingDir, currentRepo, tokens)
else -> executeHelperCommand(sandboxRoot, workingDir, currentRepo, expandedTokens)
}
return inspectSandbox(level).copy(currentDir = result.first.currentDir) to result.second
@@ -239,12 +240,18 @@ class GitRepositoryRuntime(private val context: Context) {
}
}
"rm" -> {
val target = tokens.getOrNull(1) ?: return currentRepo to listOf("usage: rm <path>")
val file = File(workingDir, target)
if (!file.exists()) currentRepo to listOf("rm: $target: No such file or directory") else {
file.deleteRecursively()
currentRepo to emptyList()
val targets = tokens.drop(1)
if (targets.isEmpty()) return currentRepo to listOf("usage: rm <path>")
val errors = targets.mapNotNull { target ->
val file = File(workingDir, target)
if (!file.exists()) {
"rm: $target: No such file or directory"
} else {
file.deleteRecursively()
null
}
}
currentRepo to errors
}
"echo" -> executeEcho(workingDir, currentRepo, tokens)
else -> currentRepo to listOf("Command not supported in prototype runtime. Try a git command or helper command.")
@@ -389,6 +396,9 @@ class GitRepositoryRuntime(private val context: Context) {
if (stagedTargets.isNotEmpty()) {
runGit(nativeGit, sandbox, listOf("add") + stagedTargets)
}
desired.files.filter { it.deleted }.forEach { file ->
File(sandbox, file.name).delete()
}
}
private fun filesForSetupCommit(files: List<GitFile>, index: Int, commitCount: Int): List<GitFile> {
@@ -437,6 +447,7 @@ class GitRepositoryRuntime(private val context: Context) {
val statusResult = runGit(nativeGit, sandbox, listOf("status", "--porcelain"))
val statusMap = mutableMapOf<String, Pair<Boolean, Boolean>>()
val deletedStatusPaths = mutableSetOf<String>()
statusResult.outputLines.forEach { line ->
if (line.length < 4) return@forEach
val x = line[0]
@@ -445,6 +456,9 @@ class GitRepositoryRuntime(private val context: Context) {
val staged = x != ' ' && x != '?'
val tracked = x != '?' || y != '?'
statusMap[path] = staged to tracked
if (x == 'D' || y == 'D') {
deletedStatusPaths += path
}
}
val logResult = runGit(nativeGit, sandbox, listOf("log", "--pretty=format:%h\t%s"))
@@ -486,7 +500,17 @@ class GitRepositoryRuntime(private val context: Context) {
staged = staged,
tracked = tracked,
)
},
} + deletedStatusPaths
.filterNot { deletedPath -> filesOnDisk.any { it.relativeTo(sandbox).path == deletedPath } }
.map { deletedPath ->
val (staged, tracked) = statusMap[deletedPath] ?: (false to true)
GitFile(
name = deletedPath,
staged = staged,
tracked = tracked,
deleted = true,
)
},
commits = commits,
headBranch = headResult.outputLines.firstOrNull()?.ifBlank { null } ?: "master",
branches = branchResult.outputLines.map { it.removePrefix("*").trim() }.filter { it.isNotBlank() }.associateWith { 0 },
@@ -511,6 +535,11 @@ class GitRepositoryRuntime(private val context: Context) {
private fun sandboxDir(level: Level): File = File(sandboxesRoot, level.id)
private fun expandShellPathspecs(repo: RepoState, tokens: List<String>): List<String> {
if (tokens.size <= 1) return tokens
return listOf(tokens.first()) + GitSandboxEngine.expandPathspecs(repo, tokens.drop(1))
}
private fun runGit(binary: File, workingDir: File, arguments: List<String>): ProcessExecutionResult {
return runProcess(binary, workingDir, arguments)
}