# gitctl TODO Planned features. Each note captures the non-obvious bits so the work does not re-discover them. Keep the hard rules from CLAUDE.md (stdlib only, single-file scripts, single-writer repo.desc, idempotent, no em dashes, work on master). ## 1. delete repo -- DONE `gitctl repo delete ` is implemented. It removes a repo from all three places it lives, the inverse of `repo create`: - gitolite stanza -> client `remove_stanza` (inverse of `add_stanza`), commit + push (needs the SSH key / card, like create). PUSHED FIRST so gitolite stops serving the repo before its bytes move. - cgit block -> helper verb `delete-repo`, `remove_repo_block` (inverse of `insert_repo_block`); deletes the repo.url/path/owner block + its spacer blanks, leaves the section header. Backed up by write_cgitrc_lines, sync after. - bare repo -> `trash_repo` MOVES it to `TRASH_DIR` (`/var/lib/gitolite3/trash`, outside REPO_BASE, timestamped name) instead of rm, with a `.trashinfo` breadcrumb. shutil.move, with a realpath check that the source is one level under REPO_BASE (defense in depth on top of validate_url). The helper exposes ONE verb (`delete-repo`) doing cgit-block removal + move + .trashinfo. Always confirms (the global `-y` is deliberately NOT read by cmd_delete). Idempotent: a piece already gone is skipped, not an error. Partial failure (push ok, helper fails, or commit ok but push fails) is resumable by re-running, same as create. Self-tests: remove_repo_block and remove_stanza both pinned by an insert/add-then-remove round-trip plus middle/last/missing cases; trash_repo and do_delete_repo exercised on temp dirs. FUTURE (not built, YAGNI): a `gc-trash --older-than ` prune verb for cron. The timestamped TRASH_DIR layout already supports it. ## 2. list repos -- DONE `gitctl repo list` is implemented. It lists EVERY bare repo on disk (the full set, public and private), not just the cgit-exposed ones, because cgit auto-discovery is off and private repos are not in cgitrc. Source of truth is `REPO_BASE/*.git`, not cgitrc; cgitrc membership only tags a repo PUB vs PRIV and supplies its section. Description comes from each repo's `description` file (truncated 60). Client renders a table, green public / dim private on a TTY. Helper verb `list-repos`; primitive `list_repos()` + `repo_sections_from()` (the latter dedupes the old `find_repo_section`). Self-tests cover both the cgitrc parse and a temp-FS scan. Still open from the original plan: extend bash completion to complete repo NAMES (for `desc` / `delete` / `add-remote`) now that a list verb exists. The `repo list` action itself is already in completion. ## 3. `-y` / `--yes` flag -- DONE `-y` / `--yes` is implemented as a GLOBAL flag (on the top-level parser), so it goes before the subcommand: `gitctl -y repo create ...`. Today the only y/N it skips is the phase-1 push confirmation in `repo create`; the diff is still printed and an "auto-confirmed" note shown. It does NOT bypass SSH key auth (password / smartcard touch), so creation is never fully unattended. Section auto-create was already silent, so behavior stays consistent. Hard wall for delete (item 1): `-y` must NEVER be honored by a destructive delete. The flag help says so, this note records it, and the global -y comment in the client points at item 1. When delete is built, it reads its own confirmation and ignores `a.yes`. Bash completion offers `-y`/`--yes` at the top level and transparently skips a leading `-y` when resolving group/action. ## Cross-cutting Done as part of items 1-3: both SKILL.md files updated (delete + `-y` limit), self-test coverage for every new helper verb, completion actions for `list` and `delete`, README and CLAUDE.md brought current. ## Remaining (not started) These are the leftovers after the three features shipped. None block anything. 1. Repo-name bash completion. Now that `repo list` exists, complete repo NAMES for `desc`, `delete`, and `add-remote` (the way `--section` is completed from the server today). One ssh call (`gitctl repo list`, cut field 1), only when completing the repo-name argument, so a stray Tab does not hit the network. 2. Quiet the stray `No changes.` line. In `repo create` and `repo delete` the `list-sections` / `add-section` helper passthrough prints a `No changes.` line out of order, before the cgit-block message. Cosmetic only. Fix by calling those helper steps with `quiet=True` (the flag already exists) and printing a clean status, or by suppressing that specific echo. 3. FUTURE / YAGNI: `gc-trash --older-than ` helper verb to prune `TRASH_DIR` entries past a retention window, runnable from cron. The timestamped trash layout already supports it; do not build until there is an actual need to reclaim space.