|
bashdeps
Exact dependency materialization and manifest maintenance tools
|
Accepted
This ADR defines the version 1 command surface, output channels, stable executable name, and exit status categories for bashdeps.
bashdeps is intended for direct human use and for Make/CI automation. Those callers need to distinguish invalid input, unsatisfied local state, missing runtime capabilities, network failure, integrity failure, and filesystem failure without scraping prose diagnostics.
ADR-003 defines install, sync, and verify. The CLI also needs ordinary help and version behavior. ADR-009 defines the distributed executable artifact as bashdeps.bash, and ADR-013 adds the optional destination-root policy.
The version 1 public executable name SHALL be:
The version 1 public commands SHALL be:
The option aliases -h and --help SHALL be equivalent to help. The option --version SHALL be equivalent to version.
sync and verify SHALL use dependencies.txt when MANIFEST is omitted.
install SHALL accept one declaration expressed with the same named fields used by a manifest record. It SHALL require exactly one each of id, url, dest, and digest, subject to ADR-002 validation.
install, sync, and verify MAY receive --dest-root PATH in the position and with the semantics defined by ADR-013. An invalid destination-root value or a declaration outside the selected root is invalid CLI/declaration policy.
Normal successful install, sync, and verify operations SHOULD produce no standard output unless a later documented feature explicitly defines output. Diagnostics SHALL be written to standard error and SHALL identify the program as bashdeps.bash.
Explicit help and version requests SHALL write to standard output. Version output SHALL identify the program as bashdeps.bash.
Version 1 SHALL use these public status categories:
Status 1 is intentionally specific to verification of existing state. A missing or mismatched destination is not itself an error for install or sync; those operations attempt convergence. If convergence subsequently fails, they return the status corresponding to the actual failure.
A malformed digest declaration is status 2. A syntactically valid digest whose downloaded candidate does not match is status 5.
Failure to locate either supported downloader is status 3. A selected downloader that attempts retrieval and encounters DNS, TLS, HTTP, timeout, or transfer failure returns status 4 through the public command layer.
Unsafe destination paths, rejected symbolic-link traversal, inability to create a staging path, or inability to publish verified bytes return status 6.
The implementation MAY use more detailed private return codes internally, but the public dispatcher SHALL map them into the documented categories above.
Diagnostics SHOULD identify:
Diagnostics SHALL NOT print downloaded artifact contents, execute manifest text, or expose secret-bearing configuration that version 1 does not otherwise support.
Usage errors SHOULD include concise usage guidance. Operational failures SHOULD not dump the complete help text by default.
An extensionless command resembles a conventionally installed system utility, but the project distributes a standalone Bash artifact named bashdeps.bash for vendoring and bootstrap use. Using the actual artifact filename in the public contract avoids requiring consumers to create an undocumented wrapper or rename the file before following examples.
This is conventional for small shell tools but would force Makefiles and CI systems to parse diagnostics when they need to distinguish malformed input from network or integrity failures.
sysexits.h provides established categories, but its meanings do not map cleanly to dependency convergence and it is not a Bash-specific portability convention. A compact project-specific contract is clearer.
Progress output is useful interactively but makes command composition noisier. Version 1 keeps successful data channels quiet; future optional verbosity can be added without changing failure semantics.
Make and CI integrations can branch on broad failure class while remaining independent of diagnostic wording.
The executable filename and exit status mapping become public API and should change only through a future architectural decision.
A future --quiet, --verbose, or machine-readable reporting mode can build on this contract without redefining success and failure.
Human-friendly verbosity and structured reporting are deliberately deferred until a demonstrated consumer needs them.