21 KiB
21 KiB
LevelsCompare
Comparison source: https://github.com/Gazler/githug/ at a613718 (release: 0.5.1, 2024-08-11).
Android source compared from app/src/main/java/solutions/tretter/githugandroid/levels/.
This file records the upstream Ruby setup and validation intent beside the Android Kotlin setup and validation. The Android port uses a real native Git sandbox for runtime state, but it exposes validation through RepoState, so some checks are expressed as equivalent state predicates rather than direct Ruby/Grit calls.
Setup Summary
| Level | Upstream setup intent | Android setup intent | Parity / reason for difference |
|---|---|---|---|
init |
Starts outside a Git repository. | Starts with empty RepoState. |
Equivalent. |
config |
Initializes a repository. | Initializes a repository. | Equivalent. |
add |
Initializes repo, creates untracked README, renames branch to master. |
Initializes repo with untracked README on master. |
Equivalent. |
commit |
Initializes repo, creates and stages README. |
Initializes repo with staged README. |
Equivalent. |
clone |
No local repo setup. | Empty state. | Equivalent; validation is command/network simplified. |
clone_to_folder |
No local repo setup. | Empty state. | Equivalent; validation is command/network simplified. |
ignore |
Initializes repo, creates README.swp, clears global excludes in .git/config. |
Initializes repo with .gitignore available for editing. |
Differs slightly: Android does not need a swap file fixture because validation checks .gitignore content directly. |
include |
Initializes repo, creates first.a, second.a, lib.a, and clears excludes. |
Initializes repo with .gitignore, lib.a, and main.a. |
Same ignore-pattern lesson; Android uses a smaller fixture. |
status |
Initializes repo; stages config.rb, README, setup.rb, deploy.rb, Guardfile; leaves database.yml untracked. |
Native setup now creates/stages the same five files and leaves database.yml untracked. |
Equivalent. |
number_of_files_committed |
Initializes repo with committed modified files plus staged/untracked files, leaving exactly two files staged for commit. | Initializes equivalent file states with two staged files. | Equivalent. |
rm |
Initializes repo, commits deleteme.rb, then deletes it from the working tree. |
Initializes repo with tracked deleted deleteme.rb. |
Equivalent. |
rm_cached |
Initializes repo, stages .gitignore and deleteme.rb. |
Initializes repo with both files staged. | Equivalent. |
stash |
Copies upstream fixture containing committed lyrics.txt plus local modifications. |
Native setup creates the same committed lyrics text and the same trailing Hey! working-tree modification. |
Equivalent. |
rename |
Initializes repo, commits oldfile.txt. |
Initializes repo with tracked oldfile.txt and commit. |
Equivalent. |
restructure |
Initializes repo with tracked about.html, contact.html, index.html. |
Same tracked HTML files. | Equivalent. |
log |
Initializes repo with one commit whose message identifies the target. | Same one modeled commit. | Equivalent. |
tag |
Initializes repo with one commit. | Initializes repo with one tracked file and commit. | Equivalent. |
push_tags |
Creates local and remote repos, tag tag_to_be_pushed, and origin remote. |
Native setup creates local/remote repo and tag; model records tag and remote. | Equivalent state projection. |
commit_amend |
Commits README, then creates untracked forgotten_file.rb. |
Same committed README plus untracked forgotten_file.rb. |
Equivalent. |
commit_in_future |
Initializes repo with staged README. |
Initializes repo with staged README. |
Equivalent setup. |
reset |
Commits README; stages to_commit_first.rb and to_commit_second.rb. |
Same committed README plus both staged files. |
Equivalent. |
reset_soft |
Commits README, then commits newfile.rb. |
Same two commits and tracked files. | Equivalent. |
checkout_file |
Commits initial config.rb, then modifies it. |
Same tracked modified config.rb. |
Equivalent. |
remote |
Initializes repo and adds my_remote_repo remote. |
Same remote in initialized repo. | Equivalent. |
remote_url |
Initializes repo and adds my_remote_repo and remote_location. |
Same two remotes. | Equivalent. |
pull |
Initializes repo and adds remote URL https://github.com/pull-this/thing-to-pull. |
Native setup creates local synthetic remote with a remote commit. | Deliberate offline equivalent to upstream network remote. |
remote_add |
Initializes repo with no origin remote. | Same. | Equivalent. |
push |
Creates divergent local and remote master histories: local has file3, remote has file4. |
Native setup creates synthetic divergent origin with the same file/commit shape. | Equivalent. |
diff |
Copies upstream fixture with committed app.rb and one changed line. |
Native setup creates the same committed app.rb and the same line 26 working-tree modification. |
Equivalent. |
blame |
Copies upstream fixture where password line is authored by Spider Man. | Native setup creates the same config.rb content with the password line authored by Spider Man. |
Equivalent. |
branch |
Initializes repo with one README commit. |
Same. | Equivalent. |
checkout |
Initializes repo with one README commit. |
Same. | Equivalent. |
checkout_tag |
Creates five commits and tags v1.0, v1.2, v1.5. |
Same commit/tag shape. | Equivalent. |
checkout_tag_over_branch |
Creates same tags and also a branch named v1.2. |
Same tag-plus-branch ambiguity. | Equivalent. |
branch_at |
Creates three commits on file1. |
Same three modeled commits and native setup. | Equivalent. |
delete_branch |
Copies fixture with committed readme and delete_me branch at the same commit as master. |
Native setup creates committed readme with master and delete_me pointing at it. |
Equivalent. |
push_branch |
Creates local and remote repos with multiple branches and target test_branch. |
Native setup creates synthetic remote and same branch intent. | Equivalent state projection. |
merge |
Copies fixture with file1 on master and file2 on feature. |
Native setup creates master file1 and feature file2. |
Equivalent. |
fetch |
Creates local master tracking origin/master; remote later gains new_branch with file1. |
Native setup creates the same synthetic remote branch scenario; model starts with one fetched head. | Equivalent after latest update. |
rebase |
Copies fixture with divergent master and feature. |
Native setup creates matching divergent master and feature. |
Equivalent. |
rebase_onto |
Creates authors.md, bad wrong_branch, and readme-update branch needing --onto. |
Native setup creates the same branch graph and files. | Equivalent setup. |
repack |
Initializes repo with one committed foo. |
Same. | Equivalent. |
cherry-pick |
Copies fixture with master and new-feature; the desired README commit is not the branch tip. |
Native setup creates the same branch shape: learner must cherry-pick the earlier README commit from new-feature. |
Equivalent. |
grep |
Copies fixture with four TODO entries across app.rb and config.rb. |
Native setup creates both source files with the same four TODO entries. | Equivalent. |
rename_commit |
Creates commits Initial commit, First coommit, Second commit. |
Same typo commit sequence. | Equivalent. |
squash |
Creates initial hidden commit plus README and three squash-target README updates. | Same commit sequence. | Equivalent. |
merge_squash |
Creates master and long-feature-branch with multiple feature changes. |
Native setup creates the same branch and file3 feature effect. |
Mostly equivalent; Android currently validates less detail. |
reorder |
Creates commits Initial Setup, First commit, Third commit, Second commit. |
Same order. | Equivalent. |
bisect |
Copies upstream Ruby fixture where ruby prog.rb 5 or make test identifies bad hash 18ed2ac. |
Creates a native Git history with balance.txt, test-balance.sh, and known-good tag. |
Intentional Android adaptation: no Ruby or make dependency, but real git bisect remains playable. |
stage_lines |
Commits initial feature.rb, then leaves two unstaged feature lines. |
Initializes tracked feature.rb containing both feature lines. |
Setup is close, but Android does not yet model partial staged vs unstaged hunks. |
find_old_branch |
Copies fixture whose active distractor branch is renamed to master, with other distractor branches and recoverable solve_world_hunger. |
Native setup creates master, solve_world_hunger, cure_common_cold, and blowup_sun_for_ransom branches with matching working-tree files. |
Equivalent. |
revert |
Creates commits First commit, Bad commit, Second commit. |
Same commit messages. | Equivalent. |
restore |
Creates file1, file2, then creates and removes file3 so it is recoverable from reflog/history. |
Native setup creates matching history and removes file3; model starts without file3. |
Equivalent. |
conflict |
Copies fixture with master and mybranch conflict in non-empty poem.txt. |
Native setup creates the conflicting poem history, leaving master with Categorized shoes by color and mybranch with the correct Sat on a wall line. |
Equivalent setup. |
submodule |
Initializes empty repo. | Same. | Equivalent; network submodule operation is modeled. |
contribute |
No local setup; solution clones upstream externally. | Empty state. | Deliberate simplification for mobile/offline final prompt. |
Validation Summary
| Level | Upstream validation intent | Android validation intent | Parity / reason for difference |
|---|---|---|---|
init |
repo.valid? |
RepoState.initialized |
Equivalent. |
config |
Prompted name/email must match user.name and user.email. |
Validates nonblank user.name and user.email. |
Deliberate UI difference: Android validates repository config state, not repeated prompt text. |
add |
README exists in index and is not untracked. |
README is staged. |
Equivalent. |
commit |
Repository has at least one commit. | Commit exists and README became tracked/unstaged. |
Stricter but same lesson outcome. |
clone |
cloneme repo contains known commit 157b2b6.... |
Accepts exact clone command. | Deliberate mobile/network simplification; no external GitHub clone is performed in-game. |
clone_to_folder |
my_cloned_repo contains known commit. |
Accepts exact clone-to-folder command. | Deliberate mobile/network simplification. |
ignore |
.gitignore contains *.swp. |
.gitignore has a line equal to *.swp. |
Equivalent. |
include |
.gitignore contains *.a and !lib.a. |
Same two entries are present. | Equivalent. |
status |
User answers database.yml; setup has five staged files and one untracked file. |
User answers database.yml; setup now mirrors staged files plus untracked database.yml. |
Updated for parity. |
number_of_files_committed |
Prompt answer is integer 2. |
Answer is 2. |
Equivalent. |
rm |
deleteme.rb no longer has an unstaged deletion. |
File removed from model or deletion staged. | Equivalent. |
rm_cached |
deleteme.rb is not staged and still exists. |
deleteme.rb is unstaged, untracked, and not deleted. |
Equivalent. |
stash |
stash@{0} exists and lyrics.txt has no working-tree changes. |
At least one stash and no staged files. | Slightly looser; Android does not model unstaged tracked dirt separately after stash. |
rename |
oldfile.txt deleted unstaged and newfile.txt added. |
newfile.txt exists and live oldfile.txt is gone. |
Equivalent for accepted solutions. |
restructure |
HTML files are deleted at root and added under src/. |
All three src/*.html files exist and no live root HTML files remain. |
Equivalent. |
log |
Prompt answer matches latest commit hash prefix. | Answer matches the modeled commit hash. | Equivalent within Android's deterministic commit model. |
tag |
First tag is new_tag. |
new_tag exists. |
Equivalent. |
push_tags |
Remote tag list contains tag_to_be_pushed. |
tag_to_be_pushed is in pushedTags. |
Equivalent state projection. |
commit_amend |
One commit and amended commit contains two files. | One commit and forgotten_file.rb is tracked. |
Equivalent. |
commit_in_future |
Commit authored date is in the future. | At least one commit has an author timestamp later than the current system clock. | Equivalent. |
reset |
to_commit_second.rb exists but is unstaged; to_commit_first.rb remains staged. |
Same staged/unstaged split with one commit. | Equivalent. |
reset_soft |
newfile.rb exists, is staged, and commit count is one. |
Same. | Equivalent. |
checkout_file |
config.rb no longer modified and commit count remains one. |
config.rb content equals initial content. |
Equivalent. |
remote |
User answers my_remote_repo. |
Answer is my_remote_repo. |
Equivalent. |
remote_url |
User answers URL matching https://github.com/githug/not_a_repo/?. |
Answer is exact URL without trailing slash. | Slightly stricter; can be relaxed if trailing slash should be accepted. |
pull |
Latest commit hash is 1797a7c. |
Remote file is present, origin/master fetched, and commits advanced. |
Equivalent local synthetic remote outcome. |
remote_add |
git remote -v contains https://github.com/githug/githug. |
origin remote equals that URL. |
Equivalent and slightly stricter on remote name. |
push |
Local master and origin/master have four identical commits. |
origin/master was pushed, four files are present, and commit count is at least four. |
Equivalent user outcome; Android tracks pushed ref instead of comparing remote commit IDs. |
diff |
Answer is changed line number 26. |
Answer is 26. |
Equivalent. |
blame |
Answer equals author of known password commit (Spider Man). |
Answer is Spider Man. |
Equivalent with deterministic Android fixture. |
branch |
Branch test_code exists. |
test_code exists and current branch remains master. |
Slightly stricter to prevent solving by checkout side effects. |
checkout |
Current branch is my_branch. |
Current branch is my_branch and branch exists. |
Equivalent. |
checkout_tag |
HEAD subject is "Some more changes" with five commits. | HEAD is at tag v1.2. |
Equivalent in Android tag model. |
checkout_tag_over_branch |
Same as checkout_tag; must choose tag, not branch. |
HEAD is at tag v1.2. |
Equivalent in Android tag model. |
branch_at |
test_branch exists and excludes "Updating file1 again". |
test_branch points at commit index 2. |
Equivalent. |
delete_branch |
delete_me branch no longer exists. |
Same. | Equivalent. |
push_branch |
Remote has pushed test_branch but not all branches. |
origin/test_branch pushed and master/other not pushed. |
Equivalent. |
merge |
file1 and file2 exist. |
Current branch is master, a merge action occurred, and file2 is tracked. |
Deliberately stricter than upstream to avoid git switch feature falsely solving on Android. |
fetch |
Local branch count is one and .git/FETCH_HEAD has two entries. |
branches.size == 1, fetchHeadCount == 2, and no recorded pull action. |
Mostly parity; Android adds the pull guard because real Git can leave two FETCH_HEAD lines after git pull, while the exercise wording explicitly says fetch without merging. |
rebase |
feature commit messages are add feature, add content, init commit, and old hash changed. |
Current branch is feature and modeled commit messages match. |
Equivalent, except Android does not compare the old hash. |
rebase_onto |
readme-update has four commits, excludes "Wrong changes", and preserves authors. |
Current branch is readme-update and rebase-onto action occurred. |
Known gap: Android validation is looser than upstream content/commit checks. |
repack |
git count-objects -v includes packed/pruned object evidence. |
repack action recorded. |
Equivalent action-level validation; Android does not model object database packing stats. |
cherry-pick |
Top commits are "Filled in README..." then "Added fancy branded output". | Same commit message order plus README.md tracked. |
Equivalent. |
grep |
Answer is TODO count 4. |
Answer is 4. |
Equivalent. |
rename_commit |
Parent commit message is corrected to First commit. |
No coommit remains and First commit exists. |
Equivalent for intended reword. |
squash |
Commit count is two. | Commit count at most two and "Adding README" remains. | Slightly stricter on preserving the base README commit. |
merge_squash |
Commit count is three and all long-feature changes are included. | Squash action recorded and a commit exists. | Known gap: Android does not yet verify all squash file/content effects. |
reorder |
git log subject order matches Third.*Second.*First.*Initial. |
Modeled commit order becomes First, Second, Third. | Equivalent relative to Android's oldest-first commit list. |
bisect |
Answer is hash prefix 18ed2ac after using Ruby/make fixture. |
Learner can run git bisect start, mark HEAD bad and known-good good, run git bisect run ./test-balance.sh, then answer the last good commit hash. |
Same bisect lesson, different fixture and final answer target to keep the Android flow clear without Ruby/make. |
stage_lines |
Staged diff contains first feature line; unstaged diff contains second feature line. | feature.rb is staged. |
Known gap: Android does not yet model partial hunk staging. |
find_old_branch |
Current branch is solve_world_hunger. |
Same. | Equivalent. |
revert |
More than three commits and a revert of "Bad commit" exists. | A commit message starts with Revert. |
Slightly looser; sufficient for current fixture. |
restore |
file3 exists. |
file3 is tracked. |
Equivalent. |
conflict |
On master, merge commit has two parents, conflict markers removed, both poem lines preserved. |
Requires a merge action on master, conflict markers removed, and the correct Sat on a wall poem line preserved. |
Known gap: Android does not expose merge-parent count in RepoState, so it tracks the merge command instead. |
submodule |
githug-include-me directory exists, has README, and is a gitlink/submodule. |
submodules contains githug-include-me URL. |
Equivalent state projection. |
contribute |
Clones upstream and checks for a commit authored by configured user. | Any nonblank command. | Deliberate mobile/offline simplification for the final contribution prompt. |
Focused Source-To-Android Checks
fetch
Upstream Ruby (levels/fetch.rb) |
Android Kotlin (FetchLevel.kt) |
|---|---|
Counts local branches with repo.branches.size. |
Uses repo.branches.size. |
Counts .git/FETCH_HEAD lines after fetch; success requires num_remote == 2. |
GitRuntime now reads .git/FETCH_HEAD into RepoState.fetchHeadCount; success requires fetchHeadCount == 2. |
| Success requires exactly one local branch and two fetched heads. | Success requires exactly one local branch and two fetched heads. Android also rejects a recorded pull action to preserve the exercise instruction "without merging" under native Git behavior. |
status
Upstream Ruby (levels/status.rb) |
Android Kotlin (StatusLevel.kt) |
|---|---|
Stages config.rb, README, setup.rb, deploy.rb, and Guardfile. |
Native setup now creates and stages those same five files. |
Leaves database.yml untracked. |
Leaves database.yml untracked. |
Validates answer database.yml. |
Validates answer database.yml. |
merge
Upstream Ruby (levels/merge.rb) |
Android Kotlin (MergeLevel.kt) |
|---|---|
Validates File.exists?("file1") && File.exists?("file2"). |
Validates master, a recorded merge action, and tracked file2. |
| Upstream is filesystem-only and loose. | Android is intentionally stricter because git switch feature otherwise produces the same visible file state and falsely solves the level. |
Follow-Up Gaps
These are the remaining known non-parity items that need additional model support if exact upstream validation is required:
stage_lines: model partial staged vs unstaged hunks.merge_squash: verify the exact squashed file/content effects.conflict: expose merge parent count inRepoStateinstead of relying on tracked merge-command evidence.rebase_onto: verify final commit count/content and removal of "Wrong changes".contribute,clone,clone_to_folder: current Android behavior intentionally avoids real network-dependent validation.