diff --git a/README.md b/README.md index feea069..21aa507 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,50 @@ You will need rust installed. Clone repo and run: 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 -`-v` prints each docker command as it runs, and `--dry-run` prints the ones it -would run without running them. Both work before or after the subcommand. +`-v` prints each docker command as it runs, `--dry-run` prints the ones it would +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 -ahab -v django test +ahab -v django migrate 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 `ahab completions ` writes a completion script to stdout, for bash, @@ -80,10 +114,17 @@ ahab django manage # manage.py ahab django makemigrations ahab django migrate ahab django shell -ahab django test ahab django make-command ``` +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 ```bash @@ -94,6 +135,15 @@ ahab postgres dump -F directory # pg_dump, a directory of files ahab postgres dump -F cluster # pg_dumpall, roles and all databases ahab postgres dump -F plain -z # any of them, gzipped ahab postgres import # drop, create, then restore +ahab postgres psql # 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. @@ -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 `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, -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 @@ -117,22 +168,47 @@ dangling symlink instead of the contents, while the host resolves it as before. ```bash ahab link add .env secrets/ # move out, leave symlinks behind 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 --porcelain # ` `, 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 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. +`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 `${XDG_DATA_HOME:-$HOME/.local/share}/ahab////`, derived -from the git `origin` remote. +from the git `origin` remote, or `_local/` when there is no remote to +name it after. ## configuration Currently `ahab` respects the following environment variables. - `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