refactor(packages): one manifest parser, so a name means one thing to both tools
install.sh and pkg-inventory.sh carried byte-identical copies of read_manifest. That is the duplicated-code half of the problem; the worse half is untested — neither script had any test for the grammar that decides what gets installed. - scripts/lib/manifest.sh is the parser; both scripts source it - tests/manifest-parser.bats writes the contract first (comments, CRLF, first field only, unreadable file fails loudly instead of yielding "nothing desired") - an unreadable manifest now fails inside the helper rather than depending on whichever `set` options the caller happens to run under - install.sh check mode verified end to end against a stubbed pacman: a CRLF manifest with trailing comments resolves to bare names, installed names drop Refs #60
This commit is contained in:
1 parent
40b9725433
commit
06f45e83c1
4 files changed
+86
-8
No files matched your search
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bats
|
||||
# tests/manifest-parser.bats — the one manifest parser, shared by install.sh and pkg-inventory.sh
|
||||
#
|
||||
# `packages/*.pkgs` is hand-written, so the parser's whole job is to forgive the ways a hand-edited
|
||||
# list is wrong. The same function decides what install.sh tries to install and what pkg-inventory
|
||||
# calls drift, so a manifest line must mean the same thing to both — which is why it lives in one
|
||||
# file instead of being pasted into each caller (Refs #60: it was pasted twice).
|
||||
#
|
||||
# Observed through the function's exit status and stdout only:
|
||||
# names first field of a line, one bare token; `#` and everything after it is a comment
|
||||
# CRLF tolerated (the manifests get edited on more than one box)
|
||||
# blank lines vanish
|
||||
# unreadable non-zero with no names — an empty desired list must never be a silent success,
|
||||
# because "nothing desired" is exactly what a rebuild would install
|
||||
|
||||
setup() {
|
||||
TEST_TMP="$(mktemp -d)"
|
||||
LIB="$BATS_TEST_DIRNAME/../scripts/lib/manifest.sh"
|
||||
}
|
||||
|
||||
teardown() { rm -rf "$TEST_TMP"; }
|
||||
|
||||
parse() { # $1 = manifest contents, verbatim
|
||||
printf '%s' "$1" > "$TEST_TMP/m.pkgs"
|
||||
run bash -c 'source "$1"; read_manifest "$2"' _ "$LIB" "$TEST_TMP/m.pkgs"
|
||||
}
|
||||
|
||||
@test "inline notes, full-line comments, blank rows and CRLF come out as bare names" {
|
||||
parse $'# desired state\r\nghostty # terminal\r\n\r\n \r\nzoxide\r\n'
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(printf '%s\n' "$output" | tr '\n' ' ')" = "ghostty zoxide " ]
|
||||
}
|
||||
|
||||
@test "only the first field of a line is a package" {
|
||||
# install.sh hands every emitted token straight to pacman, so a stray second token on a line
|
||||
# must never become an install target; whatever it is, the manifest did not declare it.
|
||||
parse $'neovim extra tokens here\n'
|
||||
[ "$output" = "neovim" ]
|
||||
}
|
||||
|
||||
@test "a comment that names a package is not a package" {
|
||||
parse $'# vlc\n#typora\nbun\n'
|
||||
[ "$output" = "bun" ]
|
||||
}
|
||||
|
||||
@test "an unreadable manifest fails loudly instead of yielding an empty desired list" {
|
||||
run --separate-stderr bash -c 'source "$1"; read_manifest "$2"' _ "$LIB" "$TEST_TMP/nope.pkgs"
|
||||
[ "$status" -ne 0 ]
|
||||
[ -z "$output" ]
|
||||
[[ "$stderr" == *nope.pkgs* ]]
|
||||
}
|
||||
Reference in new issue
Block a user