Archived
Add read-only git provider
Implement submodule.Provider with the git CLI so submarine reads real repositories: `submarine [dir]`, with `--mock` for the built-in data. - Tree reads .gitmodules recursively; Status derives presence, checkout, worktree, staged pin, pushed state and pin -> ref resolution from local git commands only (no network). - Concurrent Status calls are bounded by runtime.NumCPU(). - scripts/make-fixture.sh builds a superproject covering every state; the integration tests run against it. - theme.Ago shows "never" for a zero time. - Docs updated; decisions D14-D16 added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c84f34ee2b
commit
64fe34b5b0
Executable
+126
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds a superproject with submodules in every state submarine shows.
|
||||
# Usage: scripts/make-fixture.sh <dir> (dir must not exist)
|
||||
# The superproject is <dir>/super; bare "remotes" live in <dir>/remotes.
|
||||
set -euo pipefail
|
||||
|
||||
[ $# -eq 1 ] || { echo "usage: $0 <dir>" >&2; exit 2; }
|
||||
[ ! -e "$1" ] || { echo "$1 already exists" >&2; exit 2; }
|
||||
mkdir -p "$1"
|
||||
root=$(cd "$1" && pwd)
|
||||
|
||||
# Reproducible and isolated from the user's git config.
|
||||
export GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_NOSYSTEM=1
|
||||
export GIT_CONFIG_COUNT=2
|
||||
export GIT_CONFIG_KEY_0=protocol.file.allow GIT_CONFIG_VALUE_0=always
|
||||
export GIT_CONFIG_KEY_1=init.defaultBranch GIT_CONFIG_VALUE_1=main
|
||||
export GIT_AUTHOR_NAME="Ada Lovelace" GIT_AUTHOR_EMAIL=ada@example.com
|
||||
export GIT_COMMITTER_NAME="Ada Lovelace" GIT_COMMITTER_EMAIL=ada@example.com
|
||||
|
||||
g() { git -C "$@" >/dev/null 2>&1; }
|
||||
|
||||
# commit <repo> <file> <message>
|
||||
commit() {
|
||||
echo "$3" >>"$1/$2"
|
||||
g "$1" add "$2"
|
||||
g "$1" commit -m "$3"
|
||||
}
|
||||
|
||||
# remote <name>: bare repo with two commits on main, pushed from a work clone
|
||||
remote() {
|
||||
git init -q --bare "$root/remotes/$1.git"
|
||||
git clone -q "$root/remotes/$1.git" "$root/work/$1" 2>/dev/null
|
||||
commit "$root/work/$1" README "Initial $1"
|
||||
commit "$root/work/$1" README "Add docs to $1"
|
||||
g "$root/work/$1" push origin main
|
||||
}
|
||||
|
||||
# upstream <name> <message>: a new commit on the remote's main
|
||||
upstream() {
|
||||
commit "$root/work/$1" README "$2"
|
||||
g "$root/work/$1" push origin main
|
||||
}
|
||||
|
||||
mkdir -p "$root/remotes" "$root/work"
|
||||
for r in core ui net store log feature nested; do remote "$r"; done
|
||||
|
||||
# "feature" has a branch that main doesn't contain
|
||||
g "$root/work/feature" switch -c feat/search
|
||||
commit "$root/work/feature" search "Add search"
|
||||
commit "$root/work/feature" search "Tune search"
|
||||
g "$root/work/feature" push origin feat/search
|
||||
g "$root/work/feature" switch main
|
||||
|
||||
# "store" has a develop branch for the .gitmodules branch rule
|
||||
g "$root/work/store" switch -c develop
|
||||
commit "$root/work/store" dev "Start develop"
|
||||
g "$root/work/store" push origin develop
|
||||
g "$root/work/store" switch main
|
||||
|
||||
# "nested" becomes a submodule of "log"
|
||||
g "$root/work/log" submodule add "$root/remotes/nested.git" modules/nested
|
||||
g "$root/work/log" commit -m "Add nested"
|
||||
g "$root/work/log" push origin main
|
||||
|
||||
super="$root/super"
|
||||
git init -q "$super"
|
||||
commit "$super" README "Initial superproject"
|
||||
add() { g "$super" submodule add "${@:3}" "$root/remotes/$1.git" "$2"; }
|
||||
add core src/core
|
||||
add ui src/ui
|
||||
add net src/net
|
||||
add store libs/store -b develop
|
||||
add log libs/log
|
||||
add feature libs/feature
|
||||
add core libs/conflict
|
||||
add ui libs/staged
|
||||
add net libs/missing
|
||||
add ui vendor
|
||||
g "$super" submodule update --init --recursive
|
||||
g "$super" commit -m "Add submodules"
|
||||
|
||||
# src/ui: remote moved on, fetched -> pin behind (↓2)
|
||||
upstream ui "Fix layout"
|
||||
upstream ui "Add theme"
|
||||
g "$super/src/ui" fetch
|
||||
g "$super/vendor" fetch
|
||||
g "$super/libs/staged" fetch
|
||||
|
||||
# src/net: local commit pinned but never pushed -> unpushed
|
||||
commit "$super/src/net" NOTES "Local experiment"
|
||||
g "$super" add src/net
|
||||
g "$super" commit -m "Pin net experiment"
|
||||
|
||||
# libs/feature: pinned inside feat/search only -> ref from contains (↓1)
|
||||
g "$super/libs/feature" fetch
|
||||
g "$super/libs/feature" checkout origin/feat/search~1
|
||||
g "$super" add libs/feature
|
||||
g "$super" commit -m "Pin feature search"
|
||||
|
||||
# src/core: checkout moved away from the pin -> off pin
|
||||
g "$super/src/core" checkout HEAD~1
|
||||
|
||||
# libs/log/modules/nested: uncommitted change, hidden under a collapsed parent
|
||||
echo dirty >>"$super/libs/log/modules/nested/README"
|
||||
|
||||
# vendor: untracked file
|
||||
echo scratch >"$super/vendor/scratch.txt"
|
||||
|
||||
# libs/staged: new pin staged in the superproject, not committed
|
||||
g "$super/libs/staged" merge --ff-only origin/main
|
||||
g "$super" add libs/staged
|
||||
|
||||
# libs/conflict: merge conflict in the worktree
|
||||
g "$super/libs/conflict" switch -c left
|
||||
commit "$super/libs/conflict" README "Left change"
|
||||
g "$super/libs/conflict" switch main
|
||||
commit "$super/libs/conflict" README "Right change"
|
||||
g "$super/libs/conflict" push origin main
|
||||
git -C "$super/libs/conflict" merge left >/dev/null 2>&1 || true
|
||||
# keep the pin on the checkout so only the conflict shows
|
||||
g "$super" add libs/conflict
|
||||
|
||||
# libs/missing: deinitialized -> missing
|
||||
g "$super" submodule deinit -f libs/missing
|
||||
|
||||
echo "$super"
|
||||
Reference in New Issue
Block a user