Fix Push level native repository setup
- Materialize the Push level with a real local/remote Git fixture that shares the first two commits, adds a remote-only fourth commit, and leaves a local third commit to rebase. - Strengthen Push validation to require the rebased/pushed state and all expected files instead of only checking that a push command happened. - Keep the level solution tests exercising the same native sandbox shape users see in the app.
This commit is contained in:
@@ -19,8 +19,8 @@ android {
|
||||
applicationId = "solutions.tretter.githugandroid"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 119
|
||||
versionName = "0.1.118"
|
||||
versionCode = 120
|
||||
versionName = "0.1.119"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -60,7 +60,7 @@ class GitRepositoryRuntime private constructor(
|
||||
runGit(nativeGit, sandbox, listOf("checkout", "-B", desired.headBranch))
|
||||
}
|
||||
|
||||
materializeNativeGitState(nativeGit, sandbox, desired)
|
||||
materializeNativeGitState(nativeGit, sandbox, desired, level.id)
|
||||
}
|
||||
|
||||
return inspectSandbox(level)
|
||||
@@ -385,7 +385,12 @@ class GitRepositoryRuntime private constructor(
|
||||
return body
|
||||
}
|
||||
|
||||
private fun materializeNativeGitState(nativeGit: File, sandbox: File, desired: RepoState) {
|
||||
private fun materializeNativeGitState(nativeGit: File, sandbox: File, desired: RepoState, levelId: String) {
|
||||
if (levelId == "push") {
|
||||
materializeNativePushLevel(nativeGit, sandbox)
|
||||
return
|
||||
}
|
||||
|
||||
desired.config.forEach { (key, value) ->
|
||||
runGit(nativeGit, sandbox, listOf("config", key, value))
|
||||
}
|
||||
@@ -437,6 +442,42 @@ 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 remoteWorkTree = File(sandbox.parentFile ?: sandbox, "${sandbox.name}-origin")
|
||||
remoteWorkTree.deleteRecursively()
|
||||
runGit(nativeGit, sandbox.parentFile ?: sandbox, listOf("clone", sandbox.absolutePath, remoteWorkTree.absolutePath))
|
||||
runGit(nativeGit, remoteWorkTree, listOf("config", "receive.denyCurrentBranch", "ignore"))
|
||||
File(remoteWorkTree, "file4").writeText("file4\n")
|
||||
commitIn(remoteWorkTree, "Fourth commit", "file4")
|
||||
|
||||
writeFile("file3")
|
||||
commitIn(sandbox, "Third commit", "file3")
|
||||
runGit(nativeGit, sandbox, listOf("remote", "add", "origin", File(remoteWorkTree, ".git").absolutePath))
|
||||
runGit(nativeGit, sandbox, listOf("fetch", "origin"))
|
||||
runGit(nativeGit, sandbox, listOf("branch", "--set-upstream-to=origin/master", "master"))
|
||||
}
|
||||
|
||||
private fun filesForSetupCommit(files: List<GitFile>, index: Int, commitCount: Int): List<GitFile> {
|
||||
if (files.isEmpty()) return emptyList()
|
||||
if (commitCount <= 1) return files
|
||||
|
||||
@@ -13,8 +13,31 @@ internal fun pushLevel(): Level = level(
|
||||
description = "Your local master branch has diverged from the remote origin/master branch. Rebase your branch onto origin/master and push it to remote.",
|
||||
hints = listOf("Take a look at `git fetch`, `git pull`, and `git push`."),
|
||||
commandSuggestions = listOf("git pull --rebase origin master", "git push origin master"),
|
||||
setup = { RepoState(initialized = true, remotes = mapOf("origin" to "remote"), branches = mapOf("master" to 3), fetchedBranches = setOf("origin/master")) },
|
||||
validator = repoPredicate { repo -> "origin/master" in repo.pushedBranches },
|
||||
setup = {
|
||||
RepoState(
|
||||
initialized = true,
|
||||
files = listOf(
|
||||
GitFile("file1", tracked = true),
|
||||
GitFile("file2", tracked = true),
|
||||
GitFile("file3", tracked = true),
|
||||
),
|
||||
commits = listOf(
|
||||
CommitNode("0000001", "First commit"),
|
||||
CommitNode("0000002", "Second commit"),
|
||||
CommitNode("0000003", "Third commit"),
|
||||
),
|
||||
remotes = mapOf("origin" to "remote"),
|
||||
branches = mapOf("master" to 3),
|
||||
fetchedBranches = setOf("origin/master"),
|
||||
)
|
||||
},
|
||||
validator = repoPredicate { repo ->
|
||||
"origin/master" in repo.pushedBranches &&
|
||||
repo.commits.size >= 4 &&
|
||||
listOf("file1", "file2", "file3", "file4").all { expected ->
|
||||
repo.files.any { file -> file.name == expected && file.tracked && !file.deleted }
|
||||
}
|
||||
},
|
||||
testCases = listOf(
|
||||
levelTestCase("pull rebase then push", "git pull --rebase origin master", "git push origin master"),
|
||||
levelTestCase("fetch rebase push", "git fetch origin", "git rebase origin/master", "git push origin master"),
|
||||
|
||||
Reference in New Issue
Block a user