package solutions.tretter.githugandroid import java.io.File internal class GitHelperCommands( private val processRunner: GitProcessRunner, ) { fun executeExecutableShortcut( sandboxRoot: File, workingDir: File, currentRepo: RepoState, tokens: List, ): Pair>? { val executable = tokens.firstOrNull() ?: return null if (!executable.startsWith("./") || executable.length <= 2) return null return executeShellScript(sandboxRoot, workingDir, currentRepo, listOf("sh", executable) + tokens.drop(1)) } fun execute( sandboxRoot: File, workingDir: File, currentRepo: RepoState, tokens: List, ): Pair> { return when (tokens.first()) { "ls", "dir" -> currentRepo to workingDir.listFiles() ?.sortedBy { it.name } ?.map { it.name } .orEmpty() "pwd" -> currentRepo to listOf( "/sandbox" + if (workingDir == sandboxRoot) "" else "/${workingDir.relativeTo(sandboxRoot).path}" ) "cat" -> { val target = tokens.getOrNull(1) ?: return currentRepo to listOf("usage: cat ") val file = File(workingDir, target) if (!file.exists() || file.isDirectory) currentRepo to listOf("cat: $target: No such file") else currentRepo to file.readLines().ifEmpty { listOf("") } } "sh" -> executeShellScript(sandboxRoot, workingDir, currentRepo, tokens) "touch" -> { val target = tokens.getOrNull(1) ?: return currentRepo to listOf("usage: touch ") val file = File(workingDir, target) if (file.exists()) { currentRepo to listOf("$target already exists") } else { file.parentFile?.mkdirs() file.writeText("") currentRepo to emptyList() } } "mkdir", "md" -> { val target = tokens.getOrNull(1) ?: return currentRepo to listOf("usage: mkdir ") val dir = File(workingDir, target) if (dir.exists()) currentRepo to listOf("mkdir: $target: File exists") else { dir.mkdirs() currentRepo to emptyList() } } "cd", "cd.." -> { val target = if (tokens.first() == "cd..") ".." else tokens.getOrNull(1) ?: return currentRepo to listOf("usage: cd ") val dir = File(workingDir, target).canonicalFile when { !dir.exists() -> currentRepo to listOf("cd: $target: does not exist") !dir.isDirectory -> currentRepo to listOf("cd: $target: Not a directory") !dir.path.startsWith(sandboxRoot.path) -> currentRepo to listOf("cd: $target: Permission denied") else -> { val relativeDir = sandboxRoot.toPath().relativize(dir.toPath()).toString().ifEmpty { "." } currentRepo.copy(currentDir = relativeDir) to emptyList() } } } "rm", "del" -> { val targets = tokens.drop(1) if (targets.isEmpty()) return currentRepo to listOf("usage: rm ") val errors = targets.mapNotNull { target -> val file = File(workingDir, target) if (!file.exists()) { "${tokens.first()}: $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.") } } private fun executeShellScript( sandboxRoot: File, workingDir: File, currentRepo: RepoState, tokens: List, ): Pair> { val script = tokens.getOrNull(1) ?: return currentRepo to listOf("usage: sh