diff --git a/bin/omarchy-install-and-launch b/bin/omarchy-install-and-launch index 53bbfbc9..2a7e547c 100755 --- a/bin/omarchy-install-and-launch +++ b/bin/omarchy-install-and-launch @@ -16,6 +16,12 @@ fi printf -v install_message '%q' "Installing ${name}..." printf -v desktop_id_arg '%q' "$desktop_id" +# The list has to reach omarchy-pkg-add as several words, so each word is quoted +# rather than the whole string; -d '' reads past newlines and always ends at EOF. +read -r -d '' -a package_list <<<"$packages" || true +printf -v packages_arg '%q ' "${package_list[@]}" +packages_arg="${packages_arg% }" + # The subshell keeps & from backgrounding the package installation too. exec omarchy-launch-floating-terminal-with-presentation \ - "echo ${install_message}; omarchy-pkg-add ${packages} && (setsid uwsm-app -- gtk-launch ${desktop_id_arg} >/dev/null 2>&1 &)" + "echo ${install_message}; omarchy-pkg-add ${packages_arg} && (setsid uwsm-app -- gtk-launch ${desktop_id_arg} >/dev/null 2>&1 &)" diff --git a/bin/omarchy-install-app b/bin/omarchy-install-app index bae90897..bee13e61 100755 --- a/bin/omarchy-install-app +++ b/bin/omarchy-install-app @@ -12,4 +12,13 @@ if [[ -z $name || -z $packages ]]; then exit 1 fi -exec omarchy-launch-floating-terminal-with-presentation "echo 'Installing ${name}...'; omarchy-pkg-add ${packages}" +printf -v install_message '%q' "Installing ${name}..." + +# The list has to reach omarchy-pkg-add as several words, so each word is quoted +# rather than the whole string; -d '' reads past newlines and always ends at EOF. +read -r -d '' -a package_list <<<"$packages" || true +printf -v packages_arg '%q ' "${package_list[@]}" +packages_arg="${packages_arg% }" + +exec omarchy-launch-floating-terminal-with-presentation \ + "echo ${install_message}; omarchy-pkg-add ${packages_arg}" diff --git a/bin/omarchy-install-font b/bin/omarchy-install-font index 6f68892e..8811ba48 100755 --- a/bin/omarchy-install-font +++ b/bin/omarchy-install-font @@ -13,5 +13,9 @@ if [[ -z $name || -z $package || -z $family ]]; then exit 1 fi +printf -v install_message '%q' "Installing ${name}..." +printf -v package_arg '%q' "$package" +printf -v family_arg '%q' "$family" + exec omarchy-launch-floating-terminal-with-presentation \ - "echo 'Installing ${name}...'; omarchy-pkg-add ${package} && sleep 2 && omarchy-font-set '${family}'" + "echo ${install_message}; omarchy-pkg-add ${package_arg} && sleep 2 && omarchy-font-set ${family_arg}" diff --git a/test/shell.d/desktop-entry-launch-test.sh b/test/shell.d/desktop-entry-launch-test.sh index 7e6f374f..c6014b10 100644 --- a/test/shell.d/desktop-entry-launch-test.sh +++ b/test/shell.d/desktop-entry-launch-test.sh @@ -17,6 +17,11 @@ printf 'pkg:%s\n' "$*" >>"$OMARCHY_TEST_LOG" exit "${OMARCHY_TEST_PKG_STATUS:-0}" SH +cat >"$mock_bin/omarchy-font-set" <<'SH' +#!/bin/bash +printf 'font:%s\n' "$*" >>"$OMARCHY_TEST_LOG" +SH + for command in omarchy-pkg-aur-add omarchy-install-emacs omazed omarchy-theme-set-vscode omarchy-install-gaming-gpu-lib32; do cat >"$mock_bin/$command" <<'SH' #!/bin/bash @@ -97,3 +102,136 @@ if grep -q '^launch:' "$OMARCHY_TEST_LOG"; then fail "generic installer does not launch after package installation failure" fi pass "generic installer does not launch after package installation failure" + +run_presentation() { + bash -c "sleep() { :; }; $(<"$OMARCHY_TEST_PRESENTATION")" +} + +bash "$ROOT/bin/omarchy-install-app" "LM Studio" "lmstudio-bin" +presentation_command=$(<"$OMARCHY_TEST_PRESENTATION") +[[ $presentation_command == *'echo Installing\ LM\ Studio...;'* ]] || + fail "install-app shell-quotes the display name" "$presentation_command" +[[ $presentation_command == *'omarchy-pkg-add lmstudio-bin'* ]] || + fail "install-app still passes the package list through" "$presentation_command" +pass "install-app shell-quotes the display name" + +bash "$ROOT/bin/omarchy-install-app" "Example App" "alpha beta" +presentation_command=$(<"$OMARCHY_TEST_PRESENTATION") +[[ $presentation_command == 'echo Installing\ Example\ App...; omarchy-pkg-add alpha beta' ]] || + fail "install-app builds the presentation command with no stray argument" "$presentation_command" +: >"$OMARCHY_TEST_LOG" +run_presentation +grep -Fxq 'pkg:alpha beta' "$OMARCHY_TEST_LOG" || + fail "install-app passes every package to the package helper" +pass "install-app passes every package to the package helper" + +bash "$ROOT/bin/omarchy-install-app" "Foo's App" "alpha" +presentation_command=$(<"$OMARCHY_TEST_PRESENTATION") +quoted_app_message="echo $(printf '%q' "Installing Foo's App...");" +[[ $presentation_command == "$quoted_app_message"* ]] || + fail "install-app shell-quotes an apostrophe in the display name" "$presentation_command" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/app-apostrophe.out" +grep -Fxq 'pkg:alpha' "$OMARCHY_TEST_LOG" || + fail "install-app still installs when the display name has an apostrophe" +pass "install-app still installs when the display name has an apostrophe" + +bash "$ROOT/bin/omarchy-install-app" "a'; echo PWNED; echo '" "alpha" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/app-inject.out" +if grep -Fxq 'PWNED' "$test_tmp/app-inject.out"; then + fail "install-app does not run extra commands from a quote in the display name" "$(<"$test_tmp/app-inject.out")" +fi +grep -Fxq 'pkg:alpha' "$OMARCHY_TEST_LOG" || + fail "install-app still installs after quoting a hostile display name" +pass "install-app does not run extra commands from a quote in the display name" + +bash "$ROOT/bin/omarchy-install-font" "Cascadia Mono" "ttf-cascadia-mono-nerd" "CaskaydiaMono Nerd Font" +presentation_command=$(<"$OMARCHY_TEST_PRESENTATION") +[[ $presentation_command == *'echo Installing\ Cascadia\ Mono...;'* ]] || + fail "install-font shell-quotes the display name" "$presentation_command" +[[ $presentation_command == *'omarchy-font-set CaskaydiaMono\ Nerd\ Font'* ]] || + fail "install-font shell-quotes a font family with spaces" "$presentation_command" +: >"$OMARCHY_TEST_LOG" +run_presentation +grep -Fxq 'pkg:ttf-cascadia-mono-nerd' "$OMARCHY_TEST_LOG" || + fail "install-font installs the font package" +grep -Fxq 'font:CaskaydiaMono Nerd Font' "$OMARCHY_TEST_LOG" || + fail "install-font passes the family name through as one argument" +pass "install-font shell-quotes the display name and family" + +bash "$ROOT/bin/omarchy-install-font" "Foo's App" "alpha" "Foo's Font" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/font-apostrophe.out" +grep -Fxq 'pkg:alpha' "$OMARCHY_TEST_LOG" || + fail "install-font still installs when the display name has an apostrophe" +grep -Fxq "font:Foo's Font" "$OMARCHY_TEST_LOG" || + fail "install-font still sets the family when it has an apostrophe" +pass "install-font still installs when the name or family has an apostrophe" + +bash "$ROOT/bin/omarchy-install-font" "a'; echo PWNED; echo '" "alpha" "a'; echo PWNED; echo '" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/font-inject.out" +if grep -Fxq 'PWNED' "$test_tmp/font-inject.out"; then + fail "install-font does not run extra commands from a quote in the name or family" "$(<"$test_tmp/font-inject.out")" +fi +grep -Fxq 'pkg:alpha' "$OMARCHY_TEST_LOG" || + fail "install-font still installs after quoting a hostile display name" +pass "install-font does not run extra commands from a quote in the name or family" + +bash "$ROOT/bin/omarchy-install-app" "Example App" "alpha; echo PWNED" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/app-pkg-inject.out" +if grep -Fxq 'PWNED' "$test_tmp/app-pkg-inject.out"; then + fail "install-app does not run extra commands from a package list" "$(<"$test_tmp/app-pkg-inject.out")" +fi +grep -Fxq 'pkg:alpha; echo PWNED' "$OMARCHY_TEST_LOG" || + fail "install-app hands a hostile package list to the package helper as arguments" "$(<"$OMARCHY_TEST_LOG")" +pass "install-app does not run extra commands from a package list" + +bash "$ROOT/bin/omarchy-install-app" "Example App" "$(printf 'alpha\nbeta')" +: >"$OMARCHY_TEST_LOG" +run_presentation +grep -Fxq 'pkg:alpha beta' "$OMARCHY_TEST_LOG" || + fail "install-app keeps every package when the list is newline-separated" "$(<"$OMARCHY_TEST_LOG")" +pass "install-app keeps every package when the list is newline-separated" + +env SHELLOPTS=errexit bash "$ROOT/bin/omarchy-install-app" "Example App" "alpha beta" || + fail "install-app builds its command under an inherited errexit" +[[ $(<"$OMARCHY_TEST_PRESENTATION") == 'echo Installing\ Example\ App...; omarchy-pkg-add alpha beta' ]] || + fail "install-app builds the same command under an inherited errexit" "$(<"$OMARCHY_TEST_PRESENTATION")" +env SHELLOPTS=errexit bash "$ROOT/bin/omarchy-install-and-launch" "Example App" "alpha beta" "Disk Usage" || + fail "install-and-launch builds its command under an inherited errexit" +grep -Fq 'omarchy-pkg-add alpha beta' "$OMARCHY_TEST_PRESENTATION" || + fail "install-and-launch keeps its package list under an inherited errexit" "$(<"$OMARCHY_TEST_PRESENTATION")" +pass "the installers build their command under an inherited errexit" + +bash "$ROOT/bin/omarchy-install-font" "Example Font" "alpha; echo PWNED" "Example Family" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/font-pkg-inject.out" +if grep -Fxq 'PWNED' "$test_tmp/font-pkg-inject.out"; then + fail "install-font does not run extra commands from its package" "$(<"$test_tmp/font-pkg-inject.out")" +fi +grep -Fxq 'pkg:alpha; echo PWNED' "$OMARCHY_TEST_LOG" || + fail "install-font hands a hostile package to the package helper as one argument" "$(<"$OMARCHY_TEST_LOG")" +pass "install-font does not run extra commands from its package" + +bash "$ROOT/bin/omarchy-install-font" "Example Font" "alpha" "Example Family" +: >"$OMARCHY_TEST_LOG" +if OMARCHY_TEST_PKG_STATUS=1 run_presentation; then + fail "install-font propagates package installation failure" +fi +if grep -q '^font:' "$OMARCHY_TEST_LOG"; then + fail "install-font does not set the family after package installation failure" "$(<"$OMARCHY_TEST_LOG")" +fi +pass "install-font does not set the family after package installation failure" + +bash "$ROOT/bin/omarchy-install-and-launch" "Example App" "alpha; echo PWNED" "Disk Usage" +: >"$OMARCHY_TEST_LOG" +run_presentation >"$test_tmp/launch-pkg-inject.out" +if grep -Fxq 'PWNED' "$test_tmp/launch-pkg-inject.out"; then + fail "install-and-launch does not run extra commands from a package list" "$(<"$test_tmp/launch-pkg-inject.out")" +fi +grep -Fxq 'pkg:alpha; echo PWNED' "$OMARCHY_TEST_LOG" || + fail "install-and-launch hands a hostile package list to the package helper as arguments" "$(<"$OMARCHY_TEST_LOG")" +pass "install-and-launch does not run extra commands from a package list"