diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c74d131..cb18f6b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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 diff --git a/app/src/main/java/solutions/tretter/githugandroid/GitRuntime.kt b/app/src/main/java/solutions/tretter/githugandroid/GitRuntime.kt index a9e4cb7..8ba42e3 100644 --- a/app/src/main/java/solutions/tretter/githugandroid/GitRuntime.kt +++ b/app/src/main/java/solutions/tretter/githugandroid/GitRuntime.kt @@ -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, index: Int, commitCount: Int): List { if (files.isEmpty()) return emptyList() if (commitCount <= 1) return files diff --git a/app/src/main/java/solutions/tretter/githugandroid/levels/PushLevel.kt b/app/src/main/java/solutions/tretter/githugandroid/levels/PushLevel.kt index 5f6be0d..89a693e 100644 --- a/app/src/main/java/solutions/tretter/githugandroid/levels/PushLevel.kt +++ b/app/src/main/java/solutions/tretter/githugandroid/levels/PushLevel.kt @@ -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"),