diff --git a/.github/workflows/workstation-scripts.yml b/.github/workflows/workstation-scripts.yml index 2f3969d..7cdf80a 100644 --- a/.github/workflows/workstation-scripts.yml +++ b/.github/workflows/workstation-scripts.yml @@ -57,7 +57,7 @@ jobs: bash -n "$f" done <<<"$files" - - name: Smoke: patch-shell idempotent + - name: Smoke: patch-shell apply is idempotent run: | set -euo pipefail p='profiles/linux-dev/workstation-v0/bin/patch-shell.sh' @@ -73,6 +73,34 @@ jobs: test "$(grep -cF '# <<< sourceos workstation-v0 <<<' "$tmp")" -eq 1 grep -F 'export PATH="$HOME/.local/bin:$PATH"' "$tmp" >/dev/null + - name: Smoke: patch-shell revert removes marker block + run: | + set -euo pipefail + p='profiles/linux-dev/workstation-v0/bin/patch-shell.sh' + tmp=$(mktemp) + printf '# rc\n' > "$tmp" + + SOURCEOS_RC_FILES="$tmp" bash "$p" apply + SOURCEOS_RC_FILES="$tmp" bash "$p" revert + + ! grep -qF '# >>> sourceos workstation-v0 >>>' "$tmp" + ! grep -qF '# <<< sourceos workstation-v0 <<<' "$tmp" + + - name: Smoke: patch-fish apply/revert + run: | + set -euo pipefail + p='profiles/linux-dev/workstation-v0/bin/patch-fish.sh' + bash -n "$p" + + tmp=$(mktemp) + printf '# fish\n' > "$tmp" + + SOURCEOS_FISH_CONFIG="$tmp" bash "$p" apply + SOURCEOS_FISH_CONFIG="$tmp" bash "$p" revert + + ! grep -qF '# >>> sourceos workstation-v0 (fish) >>>' "$tmp" + ! grep -qF '# <<< sourceos workstation-v0 (fish) <<<' "$tmp" + - name: Smoke: sourceos help exits cleanly run: | set -euo pipefail diff --git a/docs/workstation/RUNBOOK.md b/docs/workstation/RUNBOOK.md index b0ba126..0cfa033 100644 --- a/docs/workstation/RUNBOOK.md +++ b/docs/workstation/RUNBOOK.md @@ -64,18 +64,20 @@ Run: SOURCEOS_AUTOPATCH_SHELL=1 ./profiles/linux-dev/workstation-v0/install.sh ``` -Or via the palette: +Bash/Zsh helper: ```bash -sourceos fix shell dry-run -sourceos fix shell apply +./profiles/linux-dev/workstation-v0/bin/patch-shell.sh dry-run +./profiles/linux-dev/workstation-v0/bin/patch-shell.sh apply +./profiles/linux-dev/workstation-v0/bin/patch-shell.sh revert ``` -For fish: +Fish helper: ```bash ./profiles/linux-dev/workstation-v0/bin/patch-fish.sh dry-run ./profiles/linux-dev/workstation-v0/bin/patch-fish.sh apply +./profiles/linux-dev/workstation-v0/bin/patch-fish.sh revert ``` --- diff --git a/profiles/linux-dev/workstation-v0/bin/patch-fish.sh b/profiles/linux-dev/workstation-v0/bin/patch-fish.sh index 4835a2d..fc750c2 100644 --- a/profiles/linux-dev/workstation-v0/bin/patch-fish.sh +++ b/profiles/linux-dev/workstation-v0/bin/patch-fish.sh @@ -3,8 +3,15 @@ set -euo pipefail # Patch fish config to source SourceOS fish spine. # Idempotent marker block. +# Modes: +# - apply (default) +# - dry-run +# - revert (remove the marker block) +# +# CI/test hook: +# - SOURCEOS_FISH_CONFIG may override the fish config path. -MODE="${1:-apply}" # apply|dry-run +MODE="${1:-apply}" # apply|dry-run|revert info(){ printf "INFO: %s\n" "$*" >&2; } warn(){ printf "WARN: %s\n" "$*" >&2; } @@ -14,7 +21,11 @@ marker_start="# >>> sourceos workstation-v0 (fish) >>>" marker_end="# <<< sourceos workstation-v0 (fish) <<<" fish_cfg(){ - echo "${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" + if [[ -n "${SOURCEOS_FISH_CONFIG:-}" ]]; then + printf '%s\n' "$SOURCEOS_FISH_CONFIG" + else + printf '%s\n' "${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" + fi } has_block(){ @@ -23,20 +34,19 @@ has_block(){ } block(){ - cat <<'EOF' -# >>> sourceos workstation-v0 (fish) >>> + cat < "$tmp" + + mv "$tmp" "$f" + info "reverted: $f" +} + main(){ case "$MODE" in - apply|dry-run) ;; + apply|dry-run|revert) ;; *) - err "unknown mode: $MODE (use apply|dry-run)" + err "unknown mode: $MODE (use apply|dry-run|revert)" exit 2 ;; esac - apply + local f + f="$(fish_cfg)" + + if [[ "$MODE" == "revert" ]]; then + revert_from_file "$f" + else + apply_to_file "$f" + fi + info "done" } diff --git a/profiles/linux-dev/workstation-v0/bin/patch-shell.sh b/profiles/linux-dev/workstation-v0/bin/patch-shell.sh index 2f15248..db07448 100644 --- a/profiles/linux-dev/workstation-v0/bin/patch-shell.sh +++ b/profiles/linux-dev/workstation-v0/bin/patch-shell.sh @@ -6,9 +6,15 @@ set -euo pipefail # - source the SourceOS shell spine (`$XDG_CONFIG_HOME/sourceos/shell/common.sh`) # # Idempotent: uses a marker block. -# CI/test hook: SOURCEOS_RC_FILES may be set to a colon-separated list of rc files. +# Modes: +# - apply (default) +# - dry-run (for apply) +# - revert (remove the marker block) +# +# CI/test hook: +# - SOURCEOS_RC_FILES may be set to a colon-separated list of rc files. -MODE="${1:-apply}" # apply|dry-run +MODE="${1:-apply}" # apply|dry-run|revert info(){ printf "INFO: %s\n" "$*" >&2; } warn(){ printf "WARN: %s\n" "$*" >&2; } @@ -77,17 +83,48 @@ apply_to_file() { info "patched: $f" } +revert_from_file() { + local f=$1 + + if [[ ! -e "$f" ]]; then + warn "rc file not found (skipping): $f" + return 0 + fi + + if ! has_block "$f"; then + info "no patch block present: $f" + return 0 + fi + + local tmp + tmp="$(mktemp)" + + awk -v s="$marker_start" -v e="$marker_end" ' + $0 == s {skip=1; next} + $0 == e {skip=0; next} + skip {next} + {print} + ' "$f" > "$tmp" + + mv "$tmp" "$f" + info "reverted: $f" +} + main(){ case "$MODE" in - apply|dry-run) ;; + apply|dry-run|revert) ;; *) - err "unknown mode: $MODE (use apply|dry-run)" + err "unknown mode: $MODE (use apply|dry-run|revert)" exit 2 ;; esac while IFS= read -r rc; do - apply_to_file "$rc" + if [[ "$MODE" == "revert" ]]; then + revert_from_file "$rc" + else + apply_to_file "$rc" + fi done < <(rc_candidates) info "done"