Misc Changes
This commit is contained in:
@@ -92,6 +92,11 @@ val RepoStateSaver = listSaver<RepoState, Any>(
|
||||
)
|
||||
|
||||
object GitSandboxEngine {
|
||||
data class ShellToken(
|
||||
val value: String,
|
||||
val quoted: Boolean = false,
|
||||
)
|
||||
|
||||
fun commandReferenceLines(): List<String> = listOf(
|
||||
"Available sandbox commands:",
|
||||
" git ",
|
||||
@@ -109,7 +114,8 @@ object GitSandboxEngine {
|
||||
)
|
||||
|
||||
fun execute(repo: RepoState, command: String): Pair<RepoState, List<String>> {
|
||||
val parts = tokenizeCommand(command)
|
||||
val shellParts = tokenizeShellCommand(command)
|
||||
val parts = shellParts.map { it.value }
|
||||
if (parts.isEmpty()) return repo to emptyList()
|
||||
return when {
|
||||
parts[0] == "help" || parts[0] == "?" -> repo to commandReferenceLines()
|
||||
@@ -129,7 +135,7 @@ object GitSandboxEngine {
|
||||
}
|
||||
}) to emptyList()
|
||||
}
|
||||
parts[0] == "echo" -> writeEcho(repo, parts)
|
||||
parts[0] == "echo" -> writeEcho(repo, shellParts)
|
||||
parts[0] == "ls" || parts[0] == "dir" -> repo to repo.files.filterNot { it.deleted }.map { it.name }.ifEmpty { listOf() }
|
||||
parts[0] == "cd.." -> repo.copy(currentDir = parentDirectory(repo.currentDir)) to emptyList()
|
||||
parts[0] != "git" -> repo to listOf("Command not supported in sandbox. Try a git command or 'touch'.")
|
||||
@@ -157,7 +163,7 @@ object GitSandboxEngine {
|
||||
}
|
||||
}
|
||||
parts.size >= 3 && parts[1] == "rm" -> removeGitPath(repo, parts.drop(2))
|
||||
parts.size >= 4 && parts[1] == "mv" -> moveGitPath(repo, expandPathspecs(repo, parts.drop(2)))
|
||||
parts.size >= 4 && parts[1] == "mv" -> moveGitPath(repo, expandPathspecTokens(repo, shellParts.drop(2)))
|
||||
parts.size >= 2 && parts[1] == "commit" -> commit(repo, parts.drop(2))
|
||||
parts.size >= 2 && parts[1] == "log" -> {
|
||||
repo to if (repo.commits.isEmpty()) listOf("fatal: your current branch '${repo.headBranch}' does not have any commits yet")
|
||||
@@ -194,12 +200,30 @@ object GitSandboxEngine {
|
||||
}
|
||||
|
||||
fun tokenizeCommand(command: String): List<String> {
|
||||
val result = mutableListOf<String>()
|
||||
return tokenizeShellCommand(command).map { it.value }
|
||||
}
|
||||
|
||||
fun tokenizeShellCommand(command: String): List<ShellToken> {
|
||||
val result = mutableListOf<ShellToken>()
|
||||
val current = StringBuilder()
|
||||
var quoteChar: Char? = null
|
||||
var escaping = false
|
||||
var currentQuoted = false
|
||||
var skipNext = false
|
||||
|
||||
command.forEach { char ->
|
||||
fun emitCurrent(force: Boolean = false) {
|
||||
if (current.isNotEmpty() || force && currentQuoted) {
|
||||
result += ShellToken(value = current.toString(), quoted = currentQuoted)
|
||||
current.clear()
|
||||
currentQuoted = false
|
||||
}
|
||||
}
|
||||
|
||||
command.forEachIndexed { index, char ->
|
||||
if (skipNext) {
|
||||
skipNext = false
|
||||
return@forEachIndexed
|
||||
}
|
||||
when {
|
||||
escaping -> {
|
||||
current.append(char)
|
||||
@@ -217,11 +241,18 @@ object GitSandboxEngine {
|
||||
}
|
||||
char == '"' || char == '\'' -> {
|
||||
quoteChar = char
|
||||
currentQuoted = true
|
||||
}
|
||||
char.isWhitespace() -> {
|
||||
if (current.isNotEmpty()) {
|
||||
result += current.toString()
|
||||
current.clear()
|
||||
emitCurrent()
|
||||
}
|
||||
char == '>' -> {
|
||||
emitCurrent()
|
||||
if (command.getOrNull(index + 1) == '>') {
|
||||
result += ShellToken(">>")
|
||||
skipNext = true
|
||||
} else if (command.getOrNull(index - 1) != '>') {
|
||||
result += ShellToken(">")
|
||||
}
|
||||
}
|
||||
else -> current.append(char)
|
||||
@@ -231,14 +262,13 @@ object GitSandboxEngine {
|
||||
if (escaping) {
|
||||
current.append('\\')
|
||||
}
|
||||
if (current.isNotEmpty()) {
|
||||
result += current.toString()
|
||||
}
|
||||
emitCurrent()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun writeEcho(repo: RepoState, parts: List<String>): Pair<RepoState, List<String>> {
|
||||
private fun writeEcho(repo: RepoState, shellParts: List<ShellToken>): Pair<RepoState, List<String>> {
|
||||
val parts = shellParts.map { it.value }
|
||||
val redirectIndex = parts.indexOfFirst { it == ">" || it == ">>" }
|
||||
if (redirectIndex == -1 || redirectIndex == parts.lastIndex) {
|
||||
return repo to listOf(parts.drop(1).joinToString(" "))
|
||||
@@ -266,8 +296,13 @@ object GitSandboxEngine {
|
||||
}
|
||||
|
||||
fun expandPathspecs(repo: RepoState, arguments: List<String>): List<String> {
|
||||
return arguments.flatMap { argument ->
|
||||
if (!argument.hasGlob()) {
|
||||
return expandPathspecTokens(repo, arguments.map { ShellToken(it) })
|
||||
}
|
||||
|
||||
fun expandPathspecTokens(repo: RepoState, arguments: List<ShellToken>): List<String> {
|
||||
return arguments.flatMap { token ->
|
||||
val argument = token.value
|
||||
if (token.quoted || !argument.hasGlob()) {
|
||||
listOf(argument)
|
||||
} else {
|
||||
val regex = argument.globToRegex()
|
||||
|
||||
Reference in New Issue
Block a user