valise-sh 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +320 -9
- package/README.md +104 -127
- package/bin/valise +67 -3266
- package/docs/architecture.md +76 -51
- package/docs/contrib-modules.md +180 -173
- package/docs/installation.md +210 -69
- package/docs/module-abi.md +211 -148
- package/docs/projects.md +249 -0
- package/docs/release-policy.md +90 -11
- package/docs/shared-modules.md +149 -26
- package/examples/README.md +20 -8
- package/examples/e2e/README.md +61 -68
- package/examples/e2e/bundles.tsv +6 -0
- package/examples/e2e/module.d/e2e_aliases.meta +1 -2
- package/examples/e2e/module.d/e2e_completions_bash.meta +0 -1
- package/examples/e2e/module.d/e2e_completions_zsh.meta +0 -1
- package/examples/e2e/module.d/e2e_env_setup.meta +2 -3
- package/examples/e2e/module.d/e2e_fish_features.meta +0 -1
- package/examples/e2e/module.d/e2e_generated_config.meta +1 -2
- package/examples/e2e/module.d/e2e_ksh_features.meta +0 -1
- package/examples/e2e/module.d/e2e_layer_probe.meta +1 -2
- package/examples/e2e/module.d/e2e_optional_network.meta +1 -2
- package/examples/e2e/module.d/e2e_platform_tools.meta +8 -0
- package/examples/e2e/module.d/e2e_platform_tools_bsd.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_darwin.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_linux.meta +2 -3
- package/examples/e2e/valise.conf +4 -0
- package/examples/e2e/variants.tsv +3 -0
- package/examples/local/module.d/hello_valise.meta +1 -2
- package/examples/profile-project/README.md +151 -0
- package/examples/profile-project/bundles.tsv +8 -0
- package/examples/profile-project/layers/demo/module.d/contrib_demo_greeting.meta +9 -0
- package/examples/profile-project/layers/demo/modules/shared/contrib_demo_greeting.sh +4 -0
- package/examples/profile-project/module.d/greeting.meta +9 -0
- package/examples/profile-project/module.d/profile_main.meta +8 -0
- package/examples/profile-project/modules/greeting.sh +5 -0
- package/examples/profile-project/valise.conf +4 -0
- package/examples/profile-project/variants.tsv +3 -0
- package/examples/shared/README.md +13 -34
- package/examples/shared/module.d/contrib_shared_paths.meta +2 -3
- package/examples/shared/module.d/contrib_shared_umask.meta +1 -2
- package/examples/shared/modules/shared/contrib_shared_paths.sh +2 -2
- package/lib/capabilities.sh +40 -13
- package/lib/cli/commands.sh +278 -0
- package/lib/cli/common.sh +326 -0
- package/lib/cli/devtools.sh +539 -0
- package/lib/cli/fish-hook.sh +986 -0
- package/lib/cli/integration.sh +337 -0
- package/lib/cli/lifecycle.sh +578 -0
- package/lib/cli/project.sh +1807 -0
- package/lib/cli/store.sh +1023 -0
- package/lib/cli/usage.sh +308 -0
- package/lib/compiler.awk +352 -24
- package/lib/fish/loader.fish +163 -28
- package/lib/fish/metadata.fish +62 -19
- package/lib/fish/profile.fish +170 -0
- package/lib/loader.sh +736 -158
- package/lib/metadata.sh +137 -55
- package/manifests/parser-support.tsv +2 -2
- package/module.d/valise_editor.meta +9 -0
- package/module.d/valise_history.meta +9 -0
- package/module.d/valise_pager.meta +9 -0
- package/module.d/valise_path.meta +9 -0
- package/module.d/{platform_bsd.meta → valise_platform_bsd.meta} +3 -4
- package/module.d/{platform_linux.meta → valise_platform_linux.meta} +3 -4
- package/module.d/{platform_macos.meta → valise_platform_macos.meta} +3 -4
- package/module.d/{platform_posix.meta → valise_platform_posix.meta} +2 -3
- package/module.d/valise_xdg.meta +9 -0
- package/modules/system/{contrib_editor.sh → valise_editor.sh} +2 -2
- package/modules/system/{contrib_history.sh → valise_history.sh} +2 -2
- package/modules/system/{contrib_pager.sh → valise_pager.sh} +2 -2
- package/modules/system/{contrib_path.sh → valise_path.sh} +3 -3
- package/modules/system/{contrib_xdg.sh → valise_xdg.sh} +2 -2
- package/package.json +91 -9
- package/docs/variants.md +0 -63
- package/entrypoints/.gitkeep +0 -0
- package/entrypoints/fish/profile.fish +0 -99
- package/examples/e2e/build-manifest.sh +0 -250
- package/examples/local/.gitkeep +0 -0
- package/lib/.gitkeep +0 -0
- package/manifests/.gitkeep +0 -0
- package/module.d/.gitkeep +0 -0
- package/module.d/contrib_editor.meta +0 -10
- package/module.d/contrib_history.meta +0 -10
- package/module.d/contrib_pager.meta +0 -10
- package/module.d/contrib_path.meta +0 -10
- package/module.d/contrib_xdg.meta +0 -10
- package/modules/.gitkeep +0 -0
package/docs/installation.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Installation and releases
|
|
2
2
|
|
|
3
|
-
`bin/valise` is a `/bin/sh` CLI.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`explain-variant`, `explain-bundles`, and `layer-lint` also require Python 3.
|
|
3
|
+
`bin/valise` is a `/bin/sh` CLI. It needs the standard POSIX utilities and a
|
|
4
|
+
SHA-256 utility (`sha256sum`, `shasum`, or `sha256`); no command needs
|
|
5
|
+
Python, Perl, or another runtime.
|
|
7
6
|
|
|
8
7
|
## Install the CLI
|
|
9
8
|
|
|
@@ -38,38 +37,122 @@ packed CLI without a registry, and loads a module from the extracted package.
|
|
|
38
37
|
## Shell integration
|
|
39
38
|
|
|
40
39
|
`valise install` installs the release described by the manifest in the
|
|
41
|
-
current
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
current directory and writes shell integration by default. It always writes
|
|
41
|
+
`~/.profile`, which login `sh`, `ksh`, and bash sessions read when no other
|
|
42
|
+
file shadows it. It then adds the files each shell reads instead:
|
|
43
|
+
|
|
44
|
+
- `~/.bash_profile` or `~/.bash_login` when one exists, because login bash
|
|
45
|
+
reads the first of those instead of `~/.profile`. valise never creates
|
|
46
|
+
either file.
|
|
47
|
+
- `~/.bashrc` when bash is `$SHELL` or the file already exists.
|
|
48
|
+
- `~/.zprofile` when zsh is on `PATH` or the file already exists. It is the
|
|
49
|
+
login file zsh reads instead of `~/.profile`.
|
|
50
|
+
- `~/.zshrc` when zsh is `$SHELL` or the file already exists.
|
|
51
|
+
- `${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/valise.fish` when valise
|
|
52
|
+
finds a Fish executable in a trusted location.
|
|
53
|
+
|
|
54
|
+
`--no-integration` writes no startup file, no Fish hook, and no command
|
|
55
|
+
stubs. `valise apply`
|
|
56
|
+
builds, installs, and then uses the same writer.
|
|
57
|
+
|
|
58
|
+
Each POSIX file receives a managed block between `# BEGIN valise managed
|
|
59
|
+
block` and `# END valise managed block`. Existing content is preserved, and
|
|
60
|
+
a repeat install replaces the block in place. A new block is appended with
|
|
61
|
+
nothing added around it, so removing the block restores the file. When the
|
|
62
|
+
file's last line has no newline, install adds one before the block and a note
|
|
63
|
+
line inside it, and uninstall removes both. Rows or lines after the block
|
|
64
|
+
keep the file's own ending, newline or not, and a repeat install leaves them
|
|
65
|
+
alone. A symlinked POSIX startup file is reported and left untouched.
|
|
66
|
+
|
|
67
|
+
Install checks every startup file, the Fish hook path, and the command
|
|
68
|
+
directory before it changes the active release. The command directory is
|
|
69
|
+
checked only when the release publishes commands or a command ledger exists.
|
|
70
|
+
An unpaired marker, a startup path that is not a regular file, a directory
|
|
71
|
+
install cannot write, a command directory it cannot write, or a Fish hook
|
|
72
|
+
path that is a symlink or a directory stops the install with nothing changed. If a later step fails
|
|
73
|
+
anyway, install puts the previous active release back (or removes the active
|
|
74
|
+
link when there was none) and names the files it had already written. Those
|
|
75
|
+
files load whichever release is active, so they need no repair.
|
|
76
|
+
|
|
77
|
+
Install also warns about lines outside a managed block that load valise by
|
|
78
|
+
hand: a reference to `valise/active`, a 0.1 `installed-modules.` list, or a
|
|
79
|
+
line that sources a compiled plan. Such a line loads the profile a second
|
|
80
|
+
time; remove it. `valise doctor` reports the same lines as a failure.
|
|
81
|
+
|
|
82
|
+
The block detects the running shell class, `ksh`, `zsh`, `bash`, or `sh` for
|
|
83
|
+
any other POSIX shell, and sources `plans/<class>.sh` from the active
|
|
84
|
+
release. It sets `_valise_profile_loaded` only when the plan succeeds, so a
|
|
85
|
+
later startup file in the same session retries after a failure.
|
|
86
|
+
`VALISE_RELOAD=1` makes a later block load the profile again.
|
|
87
|
+
|
|
88
|
+
`valise install` writes `~/.profile`, which ksh reads at login. A non-login
|
|
89
|
+
interactive ksh reads the file named by `$ENV` when that variable is set.
|
|
90
|
+
valise does not choose or edit that file; to cover non-login ksh, put the
|
|
91
|
+
POSIX block in the file `$ENV` names.
|
|
92
|
+
|
|
93
|
+
Zsh does not read `~/.profile` on its own: zsh login shells read
|
|
94
|
+
`.zprofile`, not `~/.profile`. Install writes the same managed block to
|
|
95
|
+
`~/.zprofile`, so zsh needs no separate pointer.
|
|
96
|
+
|
|
97
|
+
When the bundle has `fish` rows, the release carries `runtime/fish/`: the
|
|
98
|
+
native Fish metadata reader and loader and `runtime/fish/profile.fish`, which
|
|
99
|
+
loads the bundle's Fish roots recorded in `valise-release.conf`. A release
|
|
100
|
+
whose bundle has no Fish rows has no `runtime/fish/`; the Fish hook then loads
|
|
101
|
+
nothing and prints nothing.
|
|
102
|
+
|
|
103
|
+
The Fish hook verifies the active release before loading it. The check
|
|
104
|
+
validates the active pointer, the release manifest, and every listed file.
|
|
105
|
+
If verification fails, the hook loads no release code and reports
|
|
106
|
+
`active release authentication failed`. Fish continues starting even if a
|
|
107
|
+
`conf.d` hook fails, so this does not abort the interactive shell.
|
|
108
|
+
|
|
109
|
+
The Fish hook is several hundred lines while the POSIX block is about twenty.
|
|
110
|
+
The difference is deliberate. The POSIX block sources a plan and trusts the
|
|
111
|
+
release on disk, as any startup file does. The Fish hook does more because
|
|
112
|
+
it must not trust release code before that code is verified, and Fish gives a
|
|
113
|
+
sourced file the caller's global functions and variables. The hook therefore
|
|
114
|
+
carries its own verification and cleanup, written before any release file
|
|
115
|
+
runs: it authenticates the release through `valise release verify`, saves the
|
|
116
|
+
caller's `SHELL_PROJECT_ROOT` and `VALISE_MODULE_ROOT` in every scope, records
|
|
117
|
+
every caller function so a release cannot silently replace one, sources
|
|
118
|
+
`runtime/fish/profile.fish` inside that transaction, and on any failure
|
|
119
|
+
removes what the release defined and restores the saved state. None of this
|
|
120
|
+
can live in the release, because a tampered release would carry tampered
|
|
121
|
+
checks. `valise apply` compares the generated hook with the installed one
|
|
122
|
+
byte for byte and reports `Fish hook current` without rewriting an identical
|
|
123
|
+
hook.
|
|
124
|
+
|
|
125
|
+
To write integration by hand, print it once and paste or save it:
|
|
51
126
|
|
|
52
127
|
```sh
|
|
53
|
-
|
|
128
|
+
valise init # POSIX block, or the Fish hook when $SHELL is fish
|
|
129
|
+
valise init posix # POSIX managed block
|
|
130
|
+
valise init fish # Fish conf.d hook; save it as fish/conf.d/valise.fish
|
|
54
131
|
```
|
|
55
132
|
|
|
56
|
-
|
|
133
|
+
Evaluating `valise init` output at every prompt, as in
|
|
134
|
+
`eval "$(valise init)"`, re-runs CLI startup code in every shell and is
|
|
135
|
+
not the routine path; prefer `valise install` or `valise apply`, which
|
|
136
|
+
write the files once.
|
|
57
137
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
138
|
+
`valise doctor` verifies the active release against its own manifest, checks
|
|
139
|
+
the startup files the running shell actually reads for valise integration,
|
|
140
|
+
including the `.bash_profile` or `.bash_login` that bash reads instead of
|
|
141
|
+
`~/.profile`. It exits nonzero when the active release is missing or fails
|
|
142
|
+
verification, and when no startup file carries the integration.
|
|
143
|
+
|
|
144
|
+
Two options adjust its scope:
|
|
61
145
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
shell.
|
|
146
|
+
- `--pre-install` skips the active-release and startup-file checks, so doctor
|
|
147
|
+
can run before the first install.
|
|
148
|
+
- `--no-integration` skips the startup-file check and reports only the
|
|
149
|
+
release.
|
|
67
150
|
|
|
68
|
-
`valise verify
|
|
151
|
+
`valise release verify` runs the release verification without sourcing shell
|
|
69
152
|
code:
|
|
70
153
|
|
|
71
154
|
```sh
|
|
72
|
-
valise verify
|
|
155
|
+
valise release verify
|
|
73
156
|
```
|
|
74
157
|
|
|
75
158
|
The development-only `valise init fish --source-tree` mode skips installed
|
|
@@ -78,39 +161,55 @@ as an installed shell hook.
|
|
|
78
161
|
|
|
79
162
|
## Build a release
|
|
80
163
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
tree
|
|
164
|
+
`valise build` turns a project into a release tree (see
|
|
165
|
+
[projects.md](projects.md#valise-build)), and `valise apply` builds and
|
|
166
|
+
installs it in one step. `valise install` installs the tree in the current
|
|
167
|
+
directory, so a tree built elsewhere installs the same way:
|
|
84
168
|
|
|
85
169
|
```sh
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
By default this creates
|
|
90
|
-
`./mytree/shell/install/profile-release.manifest`. Use `--output <file>` to
|
|
91
|
-
choose another manifest path. The manifest records each regular file's size
|
|
92
|
-
and SHA-256 digest; source and destination paths are the same. The tree must
|
|
93
|
-
contain files with mode `0644` or `0755`. Symlinks, unsupported path
|
|
94
|
-
characters, and other file modes are rejected. Rebuilding an unchanged tree
|
|
95
|
-
produces the same manifest.
|
|
96
|
-
|
|
97
|
-
Install and verify from the tree root:
|
|
98
|
-
|
|
99
|
-
```sh
|
|
100
|
-
cd mytree
|
|
170
|
+
cd build/release
|
|
101
171
|
valise install
|
|
102
|
-
valise verify
|
|
172
|
+
valise release verify
|
|
103
173
|
```
|
|
104
174
|
|
|
105
|
-
Install
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
175
|
+
Install requires `manifest.tsv`, which lists every regular file with its
|
|
176
|
+
size and SHA-256 digest, and a `valise-release.conf` declaring `format=2`;
|
|
177
|
+
a tree from an older valise must be rebuilt. It copies the tree into
|
|
178
|
+
the release store under the manifest's SHA-256, makes the copy read-only,
|
|
179
|
+
verifies it, and switches the active link. `release verify` checks the
|
|
180
|
+
installed bytes against their manifest again. Fish repeats that check at
|
|
181
|
+
every startup; the POSIX block does not, so run `release verify` when you
|
|
182
|
+
want a check before a POSIX shell sources the release.
|
|
183
|
+
|
|
184
|
+
`valise make-manifest <tree> [--output <file>]` writes the manifest for a
|
|
185
|
+
tree; `valise build` uses it. Files must have mode `0644` or `0755`;
|
|
186
|
+
symlinks, unsupported path characters, and other modes are rejected. An
|
|
187
|
+
unchanged tree always produces the same manifest.
|
|
188
|
+
|
|
189
|
+
## Published commands
|
|
190
|
+
|
|
191
|
+
A release whose modules declare `commands=` or `executables=` carries a
|
|
192
|
+
`bin/` directory (see [the module ABI](module-abi.md#published-commands)).
|
|
193
|
+
`valise install` writes a stub for each name into the command directory,
|
|
194
|
+
`${VALISE_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}`. A stub is a short
|
|
195
|
+
`sh` script that runs the same name under the active release link, so
|
|
196
|
+
switching releases never rewrites a stub; install and `valise release use`
|
|
197
|
+
add the stubs the new release needs and remove the ones it no longer has.
|
|
198
|
+
|
|
199
|
+
valise records each stub it writes, with its SHA-256, in
|
|
200
|
+
`$XDG_STATE_HOME/valise/commands.tsv` before writing the stub, so an
|
|
201
|
+
interrupted install never leaves a stub valise does not know about. It only
|
|
202
|
+
touches files listed there, and it refuses a release whose `commands=` holds
|
|
203
|
+
a name the build would have rejected:
|
|
204
|
+
|
|
205
|
+
- A file valise did not write is never replaced. Install reports the
|
|
206
|
+
command as not published, and `valise doctor` reports the collision.
|
|
207
|
+
- A stub that was edited after valise wrote it is left in place and
|
|
208
|
+
dropped from the ledger.
|
|
209
|
+
|
|
210
|
+
`valise install --no-integration` writes no stubs and no ledger, and a later
|
|
211
|
+
`valise release use` leaves the command directory alone. Install and
|
|
212
|
+
`valise doctor` warn when the command directory is not on PATH.
|
|
114
213
|
|
|
115
214
|
## Integrity and provenance
|
|
116
215
|
|
|
@@ -132,30 +231,72 @@ controls.
|
|
|
132
231
|
| Releases | `~/.local/share/valise/releases/` | `$XDG_DATA_HOME/valise/releases/` |
|
|
133
232
|
| Active release | `~/.config/valise/active` | `$XDG_CONFIG_HOME/valise/active` |
|
|
134
233
|
| Lock and state | `~/.local/state/valise/` | `$XDG_STATE_HOME/valise/` |
|
|
234
|
+
| Command stubs | `~/.local/bin/` | `$VALISE_BIN_DIR`, then `$XDG_BIN_HOME` |
|
|
235
|
+
|
|
236
|
+
The active path is a symlink to the selected release. The state directory
|
|
237
|
+
holds the lock, the previous-release record (`previous`), the command-stub
|
|
238
|
+
ledger (`commands.tsv`), and the list of startup files install created
|
|
239
|
+
(`startup-created`). Uninstall uses the same locations, including any XDG
|
|
240
|
+
overrides.
|
|
241
|
+
|
|
242
|
+
## Managing installed releases
|
|
135
243
|
|
|
136
|
-
|
|
244
|
+
`valise release list` shows the installed releases and marks the active one.
|
|
245
|
+
`valise release use <release-id>` verifies an installed release and points
|
|
246
|
+
the active symlink at it. Each time the active release changes, valise
|
|
247
|
+
records the one it replaced in `$XDG_STATE_HOME/valise/previous`;
|
|
248
|
+
`valise release rollback` verifies that release and makes it active again, so
|
|
249
|
+
two rollbacks in a row return to where they started. Both move the command
|
|
250
|
+
stubs to the new active release when install published them.
|
|
251
|
+
|
|
252
|
+
`valise apply --dry-run` builds the project and prints what install would
|
|
253
|
+
do: whether the release is installed or active already, and for each startup
|
|
254
|
+
file, the Fish hook, and each command stub whether it is current or would be
|
|
255
|
+
created, updated, published, skipped, or removed. It writes nothing outside
|
|
256
|
+
`build/`.
|
|
257
|
+
|
|
258
|
+
`valise release prune --keep=<n>` removes old releases. It always keeps the
|
|
259
|
+
active release and the `n` newest others, and it never removes a release that
|
|
260
|
+
fails verification against its own manifest. A release that cannot be
|
|
261
|
+
verified is reported and kept, so a damaged tree is not silently discarded.
|
|
262
|
+
The default is `--keep=3`.
|
|
263
|
+
|
|
264
|
+
## Command usage
|
|
265
|
+
|
|
266
|
+
Every command prints its own contract:
|
|
267
|
+
|
|
268
|
+
```sh
|
|
269
|
+
valise compile --help
|
|
270
|
+
valise build --help
|
|
271
|
+
valise install --help
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`valise help` prints the global command list.
|
|
137
275
|
|
|
138
276
|
## Updating and removing
|
|
139
277
|
|
|
140
|
-
Update a source checkout with Git. To update
|
|
141
|
-
reinstall the tarball. `valise install` updates the active profile release;
|
|
278
|
+
Update a source checkout with Git. To update a package installation, repack
|
|
279
|
+
and reinstall the tarball. `valise install` updates the active profile release;
|
|
142
280
|
it does not update the CLI itself.
|
|
143
281
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
the block
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
282
|
+
`valise uninstall` removes what install wrote:
|
|
283
|
+
|
|
284
|
+
- the managed block from `~/.profile`, `~/.bash_profile`, `~/.bash_login`,
|
|
285
|
+
`~/.bashrc`, `~/.zprofile`, and `~/.zshrc`, keeping every other byte and
|
|
286
|
+
the file mode; a file install created is deleted when nothing else is left
|
|
287
|
+
in it
|
|
288
|
+
- the Fish hook, when its first line is the valise header
|
|
289
|
+
- the command stubs valise owns, except a stub that was edited after valise
|
|
290
|
+
wrote it
|
|
291
|
+
- the active link, the previous-release record, and the installed releases
|
|
292
|
+
|
|
293
|
+
It checks every startup file for paired markers before it changes anything.
|
|
294
|
+
A symlinked startup file and lines that load valise outside a managed block
|
|
295
|
+
are reported for you to edit. `--keep-releases` keeps the installed releases.
|
|
296
|
+
Then remove the CLI:
|
|
151
297
|
|
|
152
298
|
```sh
|
|
153
|
-
chmod -R u+w "$HOME/.local/share/valise" 2>/dev/null || :
|
|
154
|
-
rm -rf "$HOME/.local/share/valise" "$HOME/.config/valise" "$HOME/.local/state/valise"
|
|
155
299
|
# Run only if installed from npm:
|
|
156
300
|
npm uninstall -g valise-sh
|
|
157
301
|
# For a source install, remove bin/ from PATH and delete any symlink you created.
|
|
158
302
|
```
|
|
159
|
-
|
|
160
|
-
If you use non-default XDG directories, remove the corresponding `valise/`
|
|
161
|
-
subdirectories there instead.
|