Canonical repo resolution: every review repo maps to exactly one canonical local repo, which
sync never deletes - only the worktrees/workspaces created from it. A canonical repo
is either discovered (an existing checkout found by scanning Config::workdir, see
crate::workdir) or tool-managed (cloned once under Paths::repo_dir() and recorded
in repos.json).
The ReviewSource abstraction: sources say what to check out, the vcs module decides
how. See the design plan for the GitHub/moz-phab implementations; this module currently
only has the shared types and trait.
Groups tracked reviews into stacks, derived from each review’s ancestors on every call
rather than stored: membership changes as revisions land or get reordered, so a stored copy
would just go stale.
rq show’s interactive TUI: a cursive (crossterm backend) SelectView of tracked reviews.
Up/down and j/k move the cursor between reviews, skipping over an expanded review’s
diffstat lines rather than stepping into them (see move_selection) - arrow keys are
intercepted via an OnEventView since SelectView’s own built-in handling would otherwise
land on those lines like any other row. Left/right (and h/l) expand/collapse the selected
review’s diffstat (fetched by rq sync and read straight out of state.json - no network
calls here). o opens the review in a browser. Enter opens it locally: fetching it on demand
if needed (the same sync::fetch_local a plain rq fetch <id> runs), then suspending the TUI
to drop the user into a subshell in its worktree (or run the configured open_command), resuming once they exit it - see
run_event_loop for why that means tearing down and recreating the whole backend rather than
just toggling raw mode. See crate::sync’s module docs for why rq sync itself never creates
workspaces. d deletes the selected review’s workspace (sync::remove_workspace), confirming
first and always discarding any local changes. Once confirmed the
dialog closes and the deletion runs on a background thread (begin_delete) with the same row
spinner as a fetch.
VCS backends (milestone 2): everything shells out to the git/jj CLIs, since jj has no
stable library API and git worktree/git apply support in gix/git2 is incomplete.