--force reparieren, Tests ergänzen, Aufräumen

- --force erlaubt jetzt tatsächlich das Downgrade auf Stable/Beta
  (der Downgrade-Block war vorher unerreichbar)
- test.sh: Tests für cmp_versions und die Update-Entscheidung
  (gefakete curl/ollama, kein Netz nötig)
- --help: stdout + Exit 0; unbekannte Argumente werden benannt
- tote Zeilen entfernt (nullglob, basename-Zeremonie)
- README: Nummerierung und nullglob-Erwähnung korrigiert
This commit is contained in:
Tim committed 2026-10-18 00:06:38 +02:00
1 parent bca72afbe8
commit 2aa9b70b29
4 files changed
+124 -14

No files matched your search

+9 -3
View File
@@ -37,7 +37,8 @@ bash -euo pipefail ollama-update --help
## Structure ## Structure
- `ollama-update` — main script (executable, bash, ~240 lines) - `ollama-update` — main script (executable, bash, ~270 lines)
- `test.sh` — self-test for version compare and update decision (no network, no install)
- `README.md` — usage docs - `README.md` — usage docs
## Key behaviors ## Key behaviors
@@ -50,7 +51,12 @@ bash -euo pipefail ollama-update --help
## Testing ## Testing
No formal test suite. Manual verification: ```bash
# Unit + integration tests (fake curl/ollama, no network, no install)
./test.sh
```
Manual verification:
```bash ```bash
# Dry-run version checks (no install) # Dry-run version checks (no install)
@@ -60,7 +66,7 @@ No formal test suite. Manual verification:
## Gotchas ## Gotchas
- Script uses `set -euo pipefail` and `nullglob` — preserve these - Script uses `set -euo pipefail` — preserve this
- GitHub API rate limits: unauthenticated = 60 req/hr - GitHub API rate limits: unauthenticated = 60 req/hr
- Beta channel compares against stable; only updates if beta > stable AND beta > local - Beta channel compares against stable; only updates if beta > stable AND beta > local
- Temp install script cleaned via `trap` on EXIT - Temp install script cleaned via `trap` on EXIT
+2 -2
View File
@@ -51,7 +51,7 @@ selbst durchgeführt und kann Root-Rechte erfordern (z. B. wenn per
7. **Downgrade-Schutz** – Ist die bereits installierte Version neuer als 7. **Downgrade-Schutz** – Ist die bereits installierte Version neuer als
die Zielversion, bricht das Skript standardmäßig ab. Mit `--force`/`-f` die Zielversion, bricht das Skript standardmäßig ab. Mit `--force`/`-f`
lässt sich ein solches Downgrade dennoch erzwingen. lässt sich ein solches Downgrade dennoch erzwingen.
7. **Ausgabe** – Vor jeder Aktion werden die ermittelten Versionen 8. **Ausgabe** – Vor jeder Aktion werden die ermittelten Versionen
(lokal, stable, beta) sowie die Entscheidung (Update/Installation/ (lokal, stable, beta) sowie die Entscheidung (Update/Installation/
kein Update) ausgegeben. kein Update) ausgegeben.
@@ -75,7 +75,7 @@ Kein Update erforderlich.
| Ausgabe vor der Installation | Nur Statusmeldungen des Installers | Zeigt lokal/stable/beta-Versionen und die getroffene Entscheidung | | Ausgabe vor der Installation | Nur Statusmeldungen des Installers | Zeigt lokal/stable/beta-Versionen und die getroffene Entscheidung |
| Versions-Pinning | Nicht vorgesehen | Übergibt `OLLAMA_VERSION` an den Installer, wenn eine konkrete Version gewünscht ist | | Versions-Pinning | Nicht vorgesehen | Übergibt `OLLAMA_VERSION` an den Installer, wenn eine konkrete Version gewünscht ist |
| Abhängigkeitsprüfung | Fehlt | Prüft benötigte Kommandos (`curl`, `grep`, `sed`, …) vorab | | Abhängigkeitsprüfung | Fehlt | Prüft benötigte Kommandos (`curl`, `grep`, `sed`, …) vorab |
| Robustheit | Standard-Bash | `set -euo pipefail`, `nullglob`, leere API-Antworten und Downloads werden abgefangen, temporäre Datei wird per `trap` aufgeräumt | | Robustheit | Standard-Bash | `set -euo pipefail`, leere API-Antworten und Downloads werden abgefangen, temporäre Datei wird per `trap` aufgeräumt |
| Hilfe / Argumente | Nicht vorhanden | `--help`/`-h` und klare Fehlerausgaben | | Hilfe / Argumente | Nicht vorhanden | `--help`/`-h` und klare Fehlerausgaben |
## Voraussetzungen ## Voraussetzungen
+22 -9
View File
@@ -3,16 +3,14 @@
# updateOllama: Lädt und installiert die aktuelle Ollama-Version (stable oder beta). # updateOllama: Lädt und installiert die aktuelle Ollama-Version (stable oder beta).
set -euo pipefail set -euo pipefail
shopt -s nullglob
readonly GITHUB_API="https://api.github.com/repos/ollama/ollama" readonly GITHUB_API="https://api.github.com/repos/ollama/ollama"
readonly INSTALL_URL="https://ollama.com/install.sh" readonly INSTALL_URL="https://ollama.com/install.sh"
PROG_NAME=$(basename "$0") || { printf 'Fehler: basename fehlgeschlagen\n' >&2; exit 1; } PROG_NAME=$(basename "$0")
readonly PROG_NAME readonly PROG_NAME
usage() { print_usage() {
printf 'Verwendung: %s [--beta|-b] [--force|-f]\n' "$PROG_NAME" >&2 printf 'Verwendung: %s [--beta|-b] [--force|-f]\n' "$PROG_NAME"
exit 2
} }
check_dependencies() { check_dependencies() {
@@ -40,8 +38,12 @@ parse_args() {
case "$1" in case "$1" in
--beta|-b) use_beta_value=true ;; --beta|-b) use_beta_value=true ;;
--force|-f) force_value=true ;; --force|-f) force_value=true ;;
-h|--help) usage ;; -h|--help) print_usage; exit 0 ;;
*) usage ;; *)
printf 'Unbekanntes Argument: %s\n' "$1" >&2
print_usage >&2
exit 2
;;
esac esac
shift shift
done done
@@ -85,7 +87,7 @@ get_latest_version() {
printf '%s\n' "$json" | sed -nE 's/.*"tag_name": *"v?([^"]+)".*/\1/p' | head -n1 printf '%s\n' "$json" | sed -nE 's/.*"tag_name": *"v?([^"]+)".*/\1/p' | head -n1
} }
# Vergleicht zwei Versionsstrings (SemVer-ähnlich, Suffixe alphabetisch). # Vergleicht zwei Versionsstrings (SemVer-ähnlich, Suffixe per 'sort -V').
# Gibt -1, 0 oder 1 aus. # Gibt -1, 0 oder 1 aus.
cmp_versions() { cmp_versions() {
local a=${1#v} b=${2#v} local a=${1#v} b=${2#v}
@@ -223,6 +225,11 @@ main() {
elif [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then elif [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then
target_ver="$stable_ver" target_ver="$stable_ver"
printf 'Stable-Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver" printf 'Stable-Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver"
elif [[ "$force_downgrade" == true && "$(cmp_versions "$beta_ver" "$local_ver")" == -1 ]]; then
# Kein neueres Release; --force erlaubt das Downgrade auf die Beta.
target_ver="$beta_ver"
elif [[ "$force_downgrade" == true && "$(cmp_versions "$stable_ver" "$local_ver")" == -1 ]]; then
target_ver="$stable_ver"
else else
printf 'Kein Update erforderlich.\n' printf 'Kein Update erforderlich.\n'
return 0 return 0
@@ -231,6 +238,9 @@ main() {
if [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then if [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then
target_ver="$stable_ver" target_ver="$stable_ver"
printf 'Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver" printf 'Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver"
elif [[ "$force_downgrade" == true && "$(cmp_versions "$stable_ver" "$local_ver")" == -1 ]]; then
# Kein neueres Release; --force erlaubt das Downgrade auf Stable.
target_ver="$stable_ver"
else else
printf 'Kein Update erforderlich.\n' printf 'Kein Update erforderlich.\n'
return 0 return 0
@@ -256,4 +266,7 @@ main() {
fi fi
} }
main "$@" # Nur ausführen, wenn direkt aufgerufen — beim Sourcing (test.sh) nicht starten.
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "$@"
fi
Executable
+91
View File
@@ -0,0 +1,91 @@
#!/bin/bash
# Selbst-Test für ollama-update: Versionsvergleich und Update-Entscheidung.
# Benötigt keine Netzverbindung und installiert nichts (curl/ollama werden gefälscht).
set -euo pipefail
cd "$(dirname "$0")"
fails=0
check() { # check <Beschreibung> <erwartet> <bekommen>
if [[ "$2" == "$3" ]]; then
printf 'ok: %s\n' "$1"
else
printf 'FEHLER: %s — erwartet %q, bekommen %q\n' "$1" "$2" "$3" >&2
fails=$((fails + 1))
fi
}
# --- cmp_versions ---
source ./ollama-update
check "gleich" "0" "$(cmp_versions 0.5.7 0.5.7)"
check "neuer" "1" "$(cmp_versions 0.5.8 0.5.7)"
check "aelter" "-1" "$(cmp_versions 0.5.7 0.5.8)"
check "fehlende Stelle = 0" "0" "$(cmp_versions 0.5 0.5.0)"
check "zweistellig" "1" "$(cmp_versions 0.10.0 0.9.9)"
check "stable ueber rc" "1" "$(cmp_versions 0.5.7 0.5.7-rc1)"
check "rc unter stable" "-1" "$(cmp_versions 0.5.7-rc1 0.5.7)"
check "rc2 ueber rc1" "1" "$(cmp_versions 0.5.7-rc2 0.5.7-rc1)"
check "rc10 ueber rc2" "1" "$(cmp_versions 0.5.7-rc10 0.5.7-rc2)"
check "v-Praefix ignoriert" "0" "$(cmp_versions v0.5.7 0.5.7)"
# --- Entscheidungs-Matrix mit gefälschten curl/ollama ---
# GitHub liefert stable=v0.5.7 und beta=v0.6.0-rc1; install.sh ist ein Stub.
tmpbin=$(mktemp -d)
trap 'rm -rf "$tmpbin"' EXIT
cat > "$tmpbin/curl" <<'EOF'
#!/bin/bash
url=""; out=""
while [[ $# -gt 0 ]]; do
case "$1" in
-o) out=$2; shift 2 ;;
-*) shift ;;
*) url=$1; shift ;;
esac
done
if [[ "$url" == *install.sh ]]; then
printf '#!/bin/bash\nexit 0\n' > "$out"
elif [[ "$url" == *releases/latest ]]; then
printf '{\n "tag_name": "v0.5.7"\n}\n'
else
printf '[\n {\n "tag_name": "v0.6.0-rc1"\n }\n]\n'
fi
EOF
cat > "$tmpbin/ollama" <<'EOF'
#!/bin/bash
if [[ "${FAKE_LOCAL_VERSION:-}" == "none" ]]; then
exit 1
fi
printf 'ollama version is %s\n' "${FAKE_LOCAL_VERSION:-0.5.7}"
EOF
chmod +x "$tmpbin/curl" "$tmpbin/ollama"
expect() { # expect <Beschreibung> <erwarteter Text> <lokale Version> [Argumente...]
local desc=$1 pattern=$2 ver=$3
shift 3
local out
out=$(PATH="$tmpbin:$PATH" FAKE_LOCAL_VERSION="$ver" ./ollama-update "$@" 2>&1 || true)
if grep -qF -- "$pattern" <<< "$out"; then
printf 'ok: %s\n' "$desc"
else
printf 'FEHLER: %s — erwartet %q, bekommen:\n%s\n' "$desc" "$pattern" "$out" >&2
fails=$((fails + 1))
fi
}
expect "aktuell: kein Update" "Kein Update erforderlich." 0.5.7
expect "stable-Update" "Update verfuegbar: 0.5.6 -> 0.5.7" 0.5.6
expect "beta-Update" "Beta-Update verfuegbar: 0.5.7 -> 0.6.0-rc1" 0.5.7 --beta
expect "downgrade ohne --force blockiert" "Kein Update erforderlich." 0.9.9
expect "downgrade mit --force" "Downgrade wird erzwungen: 0.9.9 -> 0.5.7" 0.9.9 --force
expect "beta-downgrade mit --force" "Downgrade wird erzwungen: 0.9.9 -> 0.6.0-rc1" 0.9.9 --beta --force
expect "nicht installiert: stable" "Installation der Stable 0.5.7" none
expect "nicht installiert: beta" "Installation der Beta 0.6.0-rc1" none --beta
if [[ "$fails" -gt 0 ]]; then
printf '%d Test(s) fehlgeschlagen\n' "$fails" >&2
exit 1
fi
printf 'Alle Tests bestanden.\n'