docs: bring the readme up to date with the commands that exist

This commit is contained in:
2026-09-08 15:40:00 +00:00
parent b224519952
commit 75f293ce36

View File

@@ -10,16 +10,50 @@ You will need rust installed. Clone repo and run:
cargo install --path . cargo install --path .
``` ```
## what it makes of a project
`ahab status` prints the services it picked, the containers behind them, the
credentials it would use and what the store holds, reporting whatever it cannot
work out rather than stopping at the first thing:
```
$ ahab status
services: db, django
django: django (built from the project)
container: 0a8b19e27634
postgres: db (postgres:18-alpine)
container: 189d4d395d62
user: myproject
database: myproject_db
store: /home/you/.local/share/ahab/git.aflabs.org/urnik/afurnik
linked: 2
`ahab link check` lists what a sandbox can still read
```
## seeing what it runs ## seeing what it runs
`-v` prints each docker command as it runs, and `--dry-run` prints the ones it `-v` prints each docker command as it runs, `--dry-run` prints the ones it would
would run without running them. Both work before or after the subcommand. run without running them, and `-q` prints only what was asked for, dropping the
progress along the way (compose's own progress included). All work before or
after the subcommand.
```bash ```bash
ahab -v django test ahab -v django migrate
ahab --dry-run postgres import ./dump ahab --dry-run postgres import ./dump
ahab -q postgres dump ./dump
``` ```
Nothing is written under `--dry-run`, filesystem included: `link add` and
`django make-command` say what they would do and leave the tree alone.
## exit codes
- `0` — it ran and had nothing to report
- `1` — it could not finish
- `2` — the arguments were wrong
- `4` — it ran fine and found something worth reporting, i.e.
`link check --exit-code` with anything outside the store
## shell completion ## shell completion
`ahab completions <shell>` writes a completion script to stdout, for bash, `ahab completions <shell>` writes a completion script to stdout, for bash,
@@ -80,10 +114,17 @@ ahab django manage <args> # manage.py
ahab django makemigrations ahab django makemigrations
ahab django migrate <args> ahab django migrate <args>
ahab django shell ahab django shell
ahab django test
ahab django make-command <app> <name> ahab django make-command <app> <name>
``` ```
There is no `ahab django test`: which runner a project uses is the project's
choice, and `manage.py test` exits 0 having collected nothing when the tests are
written for pytest, so a wrong guess reads as a pass. Name the runner instead:
```bash
ahab django run pytest -x tests/
```
## postgres ## postgres
```bash ```bash
@@ -94,6 +135,15 @@ ahab postgres dump -F directory <d> # pg_dump, a directory of files
ahab postgres dump -F cluster <path> # pg_dumpall, roles and all databases ahab postgres dump -F cluster <path> # pg_dumpall, roles and all databases
ahab postgres dump -F plain -z <path> # any of them, gzipped ahab postgres dump -F plain -z <path> # any of them, gzipped
ahab postgres import <path> # drop, create, then restore ahab postgres import <path> # drop, create, then restore
ahab postgres psql <args> # psql in the database container
```
`psql` passes its arguments through and only asks docker for a terminal when it
has one to hand over, so both of these work:
```bash
ahab postgres psql # interactive
ahab postgres psql -tAc 'select count(*) from auth_user' | wc -l
``` ```
The format of a dump being imported is read from the file rather than its name. The format of a dump being imported is read from the file rather than its name.
@@ -106,7 +156,8 @@ differently again: it creates its own databases and carries role statements, so
the database is dropped but not recreated, the dump goes to `psql` connected to the database is dropped but not recreated, the dump goes to `psql` connected to
`postgres`, and it runs without `ON_ERROR_STOP` because roles that already exist `postgres`, and it runs without `ON_ERROR_STOP` because roles that already exist
report errors that are expected. Gzipped dumps are decompressed on the way in, report errors that are expected. Gzipped dumps are decompressed on the way in,
whichever of the three they hold. whichever of the three they hold. A cluster that has never held the database
yet is a valid target either way, so importing into a fresh one works.
## link ## link
@@ -117,22 +168,47 @@ dangling symlink instead of the contents, while the host resolves it as before.
```bash ```bash
ahab link add .env secrets/ # move out, leave symlinks behind ahab link add .env secrets/ # move out, leave symlinks behind
ahab link restore .env # move it back into the repository ahab link restore .env # move it back into the repository
ahab link restore --all # everything this repo has in the store ahab link restore --all # everything this repo has linked
ahab link list # what the store holds for this repository
ahab link check # what a sandbox can still read ahab link check # what a sandbox can still read
ahab link check --porcelain # `<code> <path>`, for scripts ahab link check --porcelain # `<code> <path>`, for scripts
ahab link check --exit-code # exit 4 when anything is outside the store
``` ```
`restore` is the inverse of `add`: the file moves out of the store and back to `restore` is the inverse of `add`: the file moves out of the store and back to
where it was, and the store keeps nothing. A second checkout linking the same where it was, and the store keeps nothing. A second checkout linking the same
path is left with a dangling symlink, since there is only ever one stored copy. path is left with a dangling symlink, since there is only ever one stored copy.
`list` says what state each stored path is in, which `check` cannot see because
it asks git about the repository rather than reading the store:
```
$ ahab link list
store: /home/you/.local/share/ahab/git.aflabs.org/urnik/afurnik
linked: .env
shadowed: config.local.py
missing: secrets/token
```
`missing` is a path whose symlink is gone, `shadowed` one that a real file took
back; either way the stored copy is the one nobody reads.
`restore --all` moves back the linked ones and says how many it left, since
there is nothing to undo for a path whose symlink is gone.
`-z` is the porcelain format for scripts that must survive any filename: entries
end with a NUL, and the two paths of a symlink leading elsewhere are separated
by one as well, the way `git status -z` reports a rename.
The store lives under The store lives under
`${XDG_DATA_HOME:-$HOME/.local/share}/ahab/<host>/<owner>/<repo>/`, derived `${XDG_DATA_HOME:-$HOME/.local/share}/ahab/<host>/<owner>/<repo>/`, derived
from the git `origin` remote. from the git `origin` remote, or `_local/<checkout>` when there is no remote to
name it after.
## configuration ## configuration
Currently `ahab` respects the following environment variables. Currently `ahab` respects the following environment variables.
- `AHAB_LINK_ROOT`: where `ahab link` keeps its store - the same as `--store`, - `AHAB_LINK_ROOT`: where `ahab link` keeps its store - the same as `--store`,
which takes precedence, and defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab` which takes precedence, and defaults to `${XDG_DATA_HOME:-$HOME/.local/share}/ahab`.
`ahab status` reads it too, so it reports the store the link commands use