Files
Githug-Android/README.md
2026-05-18 20:19:34 -05:00

164 lines
10 KiB
Markdown

# GitHug Android
Native Android adaptation of the Ruby [Githug](https://github.com/Gazler/githug) learning game, built with **Kotlin + Jetpack Compose**. The product goal is a shippable mobile implementation that preserves GitHug's CLI-first learning style while making repository state easier to inspect on a phone.
## Implementation Strategy
The app is organized around GitHug parity rather than simplified command quizzes:
- The level catalog follows the upstream Ruby Githug order from `Githug::Level::LEVELS`.
- Each exercise lives in its own Kotlin source file under `app/src/main/java/solutions/tretter/githugandroid/levels/`.
- Each level file documents the intended repository setup, evaluation strategy, hints, command suggestions, and embedded solution scenarios.
- Validators prefer repository state and Git objects over raw command text. Direct command-answer validation is reserved for upstream answer-style levels such as identifying a hash, filename, remote URL, author, or count.
- Shared tests execute the embedded solution scenarios for every level and assert that the Android catalog still matches the upstream level order.
- The runtime prepares an isolated sandbox per level and requires a bundled native Git binary for the device ABI. If no native Git binary is available, the app shows an unavailable-build message instead of starting a playable session.
The UI supports a terminal-centered workflow with optional inspection panes:
- **CLI ONLY**: hide visualization and play with terminal-style input.
- **HYBRID**: command line with optional repository panels.
- **VISUAL**: repository panels visible by default, still backed by the same command engine.
## Development Workflow
Development tasks should be run through the project tooling script. It provisions the local toolchain, keeps paths project-relative, and runs Gradle with the project configuration expected by this repository.
While implementing changes, keep `commit-summary.txt` updated as you go. This file is intentionally ignored by git and excluded from automatic commits so it can be edited manually too; the build tooling uses it as the commit message when it exists and is non-empty.
## Android project tooling
This repo includes a root-level tooling script:
```bash
bash ./AndroidProjectTooling.sh
```
It is designed to be idempotent and uses project-relative paths to:
- install a project-local JDK into `./jdk`
- install Android command-line tools into `./android-sdk`
- restore `gradle/wrapper/gradle-wrapper.jar` if missing
- install required Android SDK packages
- write `local.properties`
Available commands:
| Command | Purpose | Output |
| --- | --- | --- |
| `bash ./AndroidProjectTooling.sh` | Provision or refresh the local Android/JDK toolchain only. | Toolchain under `./jdk` and `./android-sdk` |
| `bash ./AndroidProjectTooling.sh --test` | Compile host Git, set `GITHUG_TEST_GIT_BINARY`, and run JVM unit tests. | Test reports under `app/build/reports/` |
| `bash ./AndroidProjectTooling.sh --build` | Build the debug APK. | `app/build/outputs/apk/debug/githug-android-debug-v<versionCode>.apk` |
| `bash ./AndroidProjectTooling.sh --build-release-aab` | Build the release Android App Bundle. | `app/build/outputs/bundle/release/githug-android-release-v<versionCode>.aab` |
| `bash ./AndroidProjectTooling.sh --compile-git` | Compile Git for the development host and all Android target ABIs. | Host and Android `libgit.so` binaries |
To run the JVM unit test suite after ensuring the local toolchain is ready:
```bash
bash ./AndroidProjectTooling.sh --test
```
To build installable/debuggable artifacts:
```bash
bash ./AndroidProjectTooling.sh --build
```
To build the release AAB intended for Play Store style distribution work:
```bash
bash ./AndroidProjectTooling.sh --build-release-aab
```
The script avoids depending on the system Java version by provisioning a project-local **JDK 17**, which is required by current Android SDK command-line tools.
To avoid repeated expensive SDK verification, the script writes a small state file named:
`./.android-project-tooling.state`
If all required components were verified successfully, the script will skip SDK verification/reinstallation for the next **24 hours** unless required directories are missing.
When `--build` or `--build-release-aab` is used, the script also:
- increments `versionCode` by 1
- increments the patch component of `versionName`, for example `0.1.0` to `0.1.1`
- bundles full Git manpage source files from Git's `Documentation/` directory into app assets
- renames the generated artifact to a `githug-android-*` filename that includes the post-bump `versionCode`
- attempts to create a git commit after a successful build if there are source changes
The build commands currently run these Gradle tasks:
- `--build`: `assembleDebug`
- `--build-release-aab`: `bundleRelease`
## Git Binary Compilation
Native Git compilation is integrated into the root tooling script:
```bash
bash ./AndroidProjectTooling.sh --compile-git
```
Options:
| Command | Purpose | Output |
| --- | --- | --- |
| `bash ./AndroidProjectTooling.sh --test` | Ensure the host Git binary is current, then run tests with it. | `build/host-git/libgit.so` and test reports |
| `bash ./AndroidProjectTooling.sh --compile-git` | Ensure host Git and Android ABI Git binaries are current. | Host and Android outputs |
Android ABI outputs:
- `app/src/main/jniLibs/arm64-v8a/libgit.so`
- `app/src/main/jniLibs/armeabi-v7a/libgit.so`
- `app/src/main/jniLibs/x86/libgit.so`
- `app/src/main/jniLibs/x86_64/libgit.so`
The `--test` tooling command automatically builds host Git only when the Git source checkout has changed, then exports `GITHUG_TEST_GIT_BINARY=build/host-git/libgit.so`. This keeps JVM tests on the same `GitRepositoryRuntime` path as the app, including the packaged-runtime helper resolution behavior.
Git build outputs are stamped with a Git source fingerprint. Re-running `--test` or `--compile-git` reuses existing `libgit.so` binaries when the checked-out Git sources and target build flavor are unchanged.
Git manpage assets are also refreshed from the checked-out Git source whenever Git is compiled or an app artifact is built.
## Runtime Architecture
The command engine has one app-facing runtime:
- **Native Git path**: the packaged executable for the device ABI runs Git commands in a real per-level repository sandbox in app-private storage.
The runtime exposes a `RepoState` surface to validators. In addition to files, commits, branches, tags, remotes, and config, the model tracks learning-relevant effects such as stashes, fetched remote refs, pushed branches/tags, submodules, and repository maintenance actions.
Helper shell-like commands (`ls`, `pwd`, `cat`, `sh <script>`, `./<script>`, `touch`, `mkdir`, `rm`, `echo`, `cd`) remain implemented in Kotlin so the mobile terminal behaves consistently across devices.
## Known Level Differences From Upstream
The Android port keeps the upstream GitHug level order, but some upstream fixtures assume desktop tools, network access, Ruby, Perl/Python helpers, or direct filesystem behavior that should not be required in a mobile learning sandbox. Differences must be documented here when they are intentional.
| Level | Upstream behavior | Android behavior | Why it differs |
| --- | --- | --- | --- |
| `bisect` | Copies the upstream Ruby fixture. The learner tests each checked-out commit with `ruby prog.rb 5` or `make test`, then answers the abbreviated hash `18ed2ac`. | Creates a native Git history with `balance.txt` and `test-balance.sh`. The learner can run `./test-balance.sh` or `sh test-balance.sh`, mark `HEAD` bad and `known-good` good, then use `git bisect run ./test-balance.sh`. The level accepts only the abbreviated hash of the last good commit before the break. | Android does not bundle Ruby or `make`. The replacement still demonstrates the real `git bisect` workflow: identify known good/bad endpoints, run a test at each checked-out commit, and use the discovered first bad commit to identify the last good commit. |
| `clone` / `clone_to_folder` | Clones `https://github.com/Gazler/cloneme` and checks the cloned repository content. | Accepts the intended clone command and models the resulting folder. | The app must remain playable offline and avoid relying on GitHub network access from a phone. |
| `pull`, `fetch`, `push`, `push_branch`, `push_tags` | Use remote-style workflows from upstream fixtures. | Use local synthetic remotes created inside the sandbox and validate fetched/pushed refs through `RepoState`. | This preserves Git behavior without external network dependencies. |
| `contribute` | Expects cloning upstream and finding a commit authored by the configured user. | Treated as a mobile/offline final prompt with a nonblank response. | The original workflow leaves the sandbox and depends on external contribution infrastructure. |
| `stage_lines` | Requires partial hunk staging: one feature line staged and another left unstaged. | Currently validates that `feature.rb` is staged. | Android does not yet expose enough index-vs-working-tree hunk detail in `RepoState` to validate partial staging precisely. |
| `rebase_onto`, `merge_squash`, `conflict`, `repack` | Upstream validates detailed object graph, file content, merge-parent, or object database details. | Android validates the relevant user-facing action or resulting state, but with less object-level detail in some cases. | The current `RepoState` projection does not expose every low-level Git object fact. These should be tightened when the state surface grows. |
## Level Authoring
When adding or changing a level:
- Keep one source file per exercise.
- Keep `allGithugLevels()` in upstream Ruby Githug order.
- Document the setup and validation intent in the level file.
- Update `LevelsCompare.md` whenever level setup, validation, hints, or accepted solution behavior changes.
- Prefer validators that inspect `RepoState` over validators that match command strings.
- Add multiple `LevelTestCase` scenarios when more than one solution path should be accepted.
- Update this README's known-differences table if the Android level intentionally differs from upstream Ruby GitHug.
- Run `bash ./AndroidProjectTooling.sh --test` before building.
## Production Focus
Current work is focused on:
- improving parity with upstream Ruby Githug setup and validation semantics
- expanding native-Git-backed behavior across complex repository workflows
- improving onboarding, accessibility, UI polish, icons, and Play Store readiness