Fix bisect script run and level validators
This commit is contained in:
@@ -20,8 +20,8 @@ android {
|
||||
applicationId = "solutions.tretter.githugandroid"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 182
|
||||
versionName = "0.1.181"
|
||||
versionCode = 183
|
||||
versionName = "0.1.182"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -24,6 +24,27 @@ internal fun directoryCompletionCandidates(repo: RepoState): List<String> {
|
||||
.distinct()
|
||||
}
|
||||
|
||||
internal fun contextualCompletionCandidates(
|
||||
candidates: List<String>,
|
||||
commandBeforeToken: String,
|
||||
token: String,
|
||||
directoriesOnly: Boolean,
|
||||
): List<String> {
|
||||
val matches = candidates.sorted().filter { it.startsWith(token) }
|
||||
if (directoriesOnly) return matches
|
||||
|
||||
val commandTokens = GitSandboxEngine.tokenizeCommand(commandBeforeToken.trim())
|
||||
if (commandTokens == listOf("git", "bisect", "run")) {
|
||||
val scriptMatches = matches.filter { candidate ->
|
||||
val normalized = candidate.removePrefix("./")
|
||||
normalized.endsWith(".sh") && '/' !in normalized && !normalized.startsWith(".")
|
||||
}
|
||||
if (scriptMatches.isNotEmpty()) return scriptMatches
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
private fun RepoState.currentDirPrefix(): String {
|
||||
return if (currentDir == ".") "" else currentDir.trimEnd('/') + "/"
|
||||
}
|
||||
|
||||
@@ -369,7 +369,12 @@ fun GitHugApp() {
|
||||
if (token.isBlank() && !isCdCompletion) return
|
||||
|
||||
val candidates = runtime.completionCandidates(currentLevel, repo, directoriesOnly = isCdCompletion)
|
||||
val matches = candidates.sorted().filter { it.startsWith(token) }
|
||||
val matches = contextualCompletionCandidates(
|
||||
candidates = candidates,
|
||||
commandBeforeToken = beforeCursor.substring(0, tokenStart),
|
||||
token = token,
|
||||
directoriesOnly = isCdCompletion,
|
||||
)
|
||||
if (matches.isEmpty()) return
|
||||
|
||||
val replacement = if (matches.size == 1) matches.first() else commonPrefix(matches)
|
||||
|
||||
@@ -144,7 +144,12 @@ class GitRepositoryRuntime private constructor(
|
||||
|
||||
val result = when (expandedTokens.first()) {
|
||||
"git" -> {
|
||||
val gitResult = runGit(nativeGit, workingDir, expandedTokens.drop(1), invocation.environment)
|
||||
val gitResult = runGit(
|
||||
nativeGit,
|
||||
workingDir,
|
||||
normalizeGitArgumentsForAndroid(expandedTokens.drop(1)),
|
||||
invocation.environment,
|
||||
)
|
||||
AppLog.d(
|
||||
"GitRuntime",
|
||||
"Git command result level=${level.id} exit=${gitResult.exitCode} output=${gitResult.outputLines}",
|
||||
@@ -167,6 +172,19 @@ class GitRepositoryRuntime private constructor(
|
||||
return refreshedRepo to result.second
|
||||
}
|
||||
|
||||
private fun normalizeGitArgumentsForAndroid(arguments: List<String>): List<String> {
|
||||
if (
|
||||
arguments.size >= 3 &&
|
||||
arguments[0] == "bisect" &&
|
||||
arguments[1] == "run" &&
|
||||
arguments[2].startsWith("./") &&
|
||||
arguments[2].endsWith(".sh")
|
||||
) {
|
||||
return arguments.take(2) + listOf("sh", arguments[2]) + arguments.drop(3)
|
||||
}
|
||||
return arguments
|
||||
}
|
||||
|
||||
fun completionCandidates(level: Level, currentRepo: RepoState, directoriesOnly: Boolean): List<String> {
|
||||
requireNativeGit()
|
||||
val sandbox = sandboxDir(level)
|
||||
|
||||
@@ -504,6 +504,37 @@ class GitSandboxEngineTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nativeBisectRunScriptShortcutRunsThroughShell() {
|
||||
val git = testGitBinary()
|
||||
assumeTrue(git.exists() && git.canExecute())
|
||||
val root = Files.createTempDirectory("githug-bisect-run-script").toFile()
|
||||
try {
|
||||
val runtime = GitRepositoryRuntime(root, git)
|
||||
val level = bisectLevel()
|
||||
var repo = runtime.prepareLevel(level)
|
||||
|
||||
listOf(
|
||||
"git bisect start",
|
||||
"git bisect bad HEAD",
|
||||
"git bisect good known-good",
|
||||
).forEach { command ->
|
||||
val (nextRepo, _) = runtime.execute(level, repo, command)
|
||||
repo = nextRepo
|
||||
}
|
||||
|
||||
val (_, output) = runtime.execute(level, repo, "git bisect run ./test-balance.sh")
|
||||
val text = output.joinToString("\n")
|
||||
|
||||
assertFalse(text, text.contains("Permission denied", ignoreCase = true))
|
||||
assertFalse(text, text.contains("can't execute", ignoreCase = true))
|
||||
assertFalse(text, text.contains("bogus exit code", ignoreCase = true))
|
||||
assertTrue(text, text.contains("first bad commit", ignoreCase = true))
|
||||
} finally {
|
||||
root.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
private fun testGitBinary(): File {
|
||||
System.getenv("GITHUG_TEST_GIT_BINARY")
|
||||
?.takeIf { it.isNotBlank() }
|
||||
|
||||
Reference in New Issue
Block a user