aboutsummaryrefslogtreecommitdiffstats
path: root/TODO.md
blob: 9bb4ad8bc43e4681fd27627f37148465bcc589cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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 <name>` 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 <days>` 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 <days>` 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.