This repository has been archived on 2026-10-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
submarine/scripts/make-fixture.sh
T
Simon FrankenandClaude Opus 5.5 19c6f17eb2 Preview uncommitted changes in the detail pane
For a dirty submodule, list the changed files so the user can remember
what they were doing there:

  Changes   5 files · 2M 1A 1D 1R · +37 −12
            ──────────────────────────────────
            M  render.go  src/render/  +20 −4  3d ago
            ?  scratch.txt                     5m ago

- Status.Changes: files changed against HEAD (staged and unstaged
  combined) with kind, line counts and modification time; sorted by kind,
  then by size; capped at 200 with totals over all files.
- Git provider: parse `status --porcelain=v2 -z` and one
  `diff HEAD --numstat -z -M`, only for dirty submodules.
- Detail pane: flat list with a colored status letter per file, like IDE
  source-control views; counts and age in compact columns; up to 10 files,
  every kind keeps a line, the rest is summarized as "n more".
- Fixture gains libs/work with every kind of change; mock data extended.
- Docs: F24, change preview in the UX guide, D17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 15:55:46 +02:00

149 lines
5.2 KiB
Bash
Executable File

#!/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 work; 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
# "work" has several tracked files, to show every kind of change
w="$root/work/work"
seq 1 20 | sed 's/^/line /' >"$w/main.go"
seq 1 3 | sed 's/^/util /' >"$w/util.go"
seq 1 8 | sed 's/^/old /' >"$w/old.go"
seq 1 5 | sed 's/^/lib /' >"$w/lib.go"
printf '\000\001\002\003' >"$w/logo.png"
g "$w" add .
g "$w" commit -m "Add sources"
g "$w" push origin 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
add work libs/work
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/work: one of every kind of change
wk="$super/libs/work"
{ seq 3 20 | sed 's/^/line /'; seq 1 6 | sed 's/^/new /'; } >"$wk/main.go" # modified +6 -2
echo "util 4" >>"$wk/util.go" # modified +1
printf '\000\001\002\003\004' >"$wk/logo.png" # modified, binary
echo "package work" >"$wk/notes_new.go"; g "$wk" add notes_new.go # added (staged)
rm "$wk/old.go" # removed
g "$wk" mv lib.go lib2.go # renamed (staged)
echo scratch >"$wk/scratch.txt"; mkdir "$wk/tmp"; echo x >"$wk/tmp/a.txt" # untracked
# 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"