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/docs/requirements.md
T
2026-10-21 20:21:00 +02:00

141 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Requirements
## Problem
In repositories with many submodules, `git submodule status` shows pinned
commit hashes. It doesn't answer the questions users actually have:
- Which branch is this submodule on, and is the pin current?
- Which submodules need my attention, and which are fine?
- Is anything dangerous, e.g. a pin that other people can't fetch?
## Goals
- Show **only submodules** (not files), recursively nested, as a tree.
- Describe pins as **ref + distance** instead of a commit hash.
- Let **problems stand out** and keep healthy submodules quiet.
- Work comfortably with **dozens to hundreds** of submodules.
## Functional requirements
### Tree
- **F1** Show all submodules of the superproject, including nested submodules
of submodules, at any depth.
- **F2** Group submodules by the directory of their path relative to the
parent repository. A directory with submodules is shown as a non-selectable
header line (e.g. `src/`, `modules/`). Submodules at the repository root
have no header.
- **F3** Nested submodules are shown under their parent submodule. A
directory header inside a submodule (e.g. `modules/`) means the nested
submodule lives in that subdirectory of the parent.
- **F4** On startup only the first level is shown; every submodule with
nested submodules is **collapsed**.
- **F5** A collapsed submodule shows the number of its **direct** children,
e.g. `[2]`.
- **F6** A collapsed submodule shows the number of issues **hidden** in all
its descendants (`·1 ·2`), one count per level: errors in red, then
warnings in yellow.
- **F7** Expansion state of descendants is remembered when a parent is
collapsed and restored when it is expanded again (except after
"collapse all", which resets it).
### State per submodule
- **F10** Each submodule shows at most **one** state word: the most severe
issue, plus `+n` if there are more. Submodules without issues show a
muted `in sync`.
See [state-model.md](state-model.md) for the full rules.
- **F11** Each submodule shows its pin as a ref (`origin/main`, a tag, or a
short SHA as a fallback) and the distance to that ref (`↑n`, `↓n`, `↑n↓m`).
- **F12** A pin that is not reachable from any remote ref ("unpushed") is
the most prominent state.
- **F13** States load asynchronously per submodule; a submodule shows a
spinner until its state is known. Loading errors are shown as `error`.
### Detail pane
- **F20** Shows the selected submodule: full path, name, all issues in
words, staged-pin and detached-HEAD notes.
- **F21** Shows the resolved ref, how it was resolved, and three commits:
**Pinned**, **Checkout** and **Tip** (SHA + subject). A checkout that
differs from the pin is highlighted.
- **F22** Lists the commits between pin and tip (SHA, subject, author, age)
with a title stating ahead/behind/diverged.
- **F23** Shows child count, issues below, and the remote URL.
- **F24** For a submodule with uncommitted changes, previews the changed
files so the user can remember what they were doing: a flat list with a
colored letter per file (`M` modified, `A` added, `D` removed, `R`
renamed, `?` untracked, `!` conflict), line counts (`+n −m`) per file and
in total, and how long ago each file was edited. Only a handful of files are
shown; the rest is summarized as "n more" with their kinds. Staged and
unstaged changes are combined.
### Header and footer
- **F30** The header shows the superproject path, its branch and
ahead/behind, the number of submodules, a count per issue kind (most
severe first), staged pins, how many are still loading, and the time since
the last fetch.
- **F31** The footer shows key hints; `?` toggles the full help. It
temporarily shows short messages (e.g. "not implemented").
### Navigation
- **F40** Keyboard navigation as specified in
[ux-guide.md](ux-guide.md#navigation).
- **F41** Mouse: click a row to select it, click `▸`/`▾` to toggle, scroll
wheel moves the selection.
### Fetch and refresh
- **F50** On startup, after the local state is shown, the superproject and
every initialized submodule are fetched in the background (all remotes,
with prune). `--no-fetch` turns this off.
- **F51** While fetching, the header shows progress (`fetching 12/174`)
instead of the fetch age; afterwards the age and the number of failed
fetches. The detail pane shows each submodule's last fetch and, if it
failed, git's message.
- **F52** The view follows changes in the repositories, no matter who made
them: a fetch, commit, checkout or `git add` in another shell shows up
within about two seconds. Refreshing is driven by the repositories, not by
the application's own fetch.
- **F53** `f` fetches again; `r` reloads everything (e.g. after editing
files, which is not watched).
### Actions (planned, not implemented)
| Key | Action |
|---|---|
| `u` | Check out the pinned commit (`git submodule update`) |
| `b` | Bump the pin to the tip of its ref |
| `/` | Filter by name/path |
| `!` | Show only submodules with issues |
## Usage
```sh
submarine [dir] # the repository containing dir (default: current directory)
submarine --mock # built-in mock data
submarine --no-fetch [dir] # no background fetch on startup
```
## Non-functional requirements
- **N1** Startup must not block on the network. The tool shows the local
state at once and fetches in the background (F50).
- **N2** Loading many submodules must not freeze the UI (async, per
submodule).
- **N3** Colors follow the user's terminal theme (ANSI 16 colors); the UI
works on dark and light backgrounds.
- **N4** Meaning never depends on color alone: every state has a word.
- **N5** Works without a Nerd Font. `SUBMARINE_ASCII=1` replaces the few
remaining Unicode symbols with ASCII.
- **N6** Works in narrow terminals (detail pane hides below 90 columns).
- **N7** The UI is independent of the data source: the mock and the git
provider are interchangeable without UI changes.
- **N8** The git provider only uses the network in `Fetch`, and never
prompts (no password, passphrase or host-key questions; those fetches
fail with git's message). It uses the `git` command line, so the user's
git configuration applies. Apart from fetching, it is read-only.