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"
|
applicationId = "solutions.tretter.githugandroid"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 119
|
versionCode = 120
|
||||||
versionName = "0.1.118"
|
versionName = "0.1.119"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class GitRepositoryRuntime private constructor(
|
|||||||
runGit(nativeGit, sandbox, listOf("checkout", "-B", desired.headBranch))
|
runGit(nativeGit, sandbox, listOf("checkout", "-B", desired.headBranch))
|
||||||
}
|
}
|
||||||
|
|
||||||
materializeNativeGitState(nativeGit, sandbox, desired)
|
materializeNativeGitState(nativeGit, sandbox, desired, level.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return inspectSandbox(level)
|
return inspectSandbox(level)
|
||||||
@@ -385,7 +385,12 @@ class GitRepositoryRuntime private constructor(
|
|||||||
return body
|
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) ->
|
desired.config.forEach { (key, value) ->
|
||||||
runGit(nativeGit, sandbox, listOf("config", 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> {
|
private fun filesForSetupCommit(files: List<GitFile>, index: Int, commitCount: Int): List<GitFile> {
|
||||||
if (files.isEmpty()) return emptyList()
|
if (files.isEmpty()) return emptyList()
|
||||||
if (commitCount <= 1) return files
|
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.",
|
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`."),
|
hints = listOf("Take a look at `git fetch`, `git pull`, and `git push`."),
|
||||||
commandSuggestions = listOf("git pull --rebase origin master", "git push origin master"),
|
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")) },
|
setup = {
|
||||||
validator = repoPredicate { repo -> "origin/master" in repo.pushedBranches },
|
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(
|
testCases = listOf(
|
||||||
levelTestCase("pull rebase then push", "git pull --rebase origin master", "git push origin master"),
|
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"),
|
levelTestCase("fetch rebase push", "git fetch origin", "git rebase origin/master", "git push origin master"),
|
||||||
|
|||||||
Reference in New Issue
Block a user