175 lines
6.2 KiB
Bash
Executable file
175 lines
6.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# apk_retention.sh — Build-Historie-Bereinigung für Timetrack APKs
|
|
#
|
|
# Retention-Strategie:
|
|
# Aktuelle Minor-Version → letzte 15 APKs nach Build-Nummer behalten
|
|
# Ältere Minor-Versionen → je eine APK behalten (höchste Build-Nummer = Release-Marker)
|
|
#
|
|
# Verwendung:
|
|
# bash scripts/apk_retention.sh [--dir build/apk] [--keep 15] [--dry-run]
|
|
#
|
|
# Dateiname-Format: timetrack-{VERSION}+{BUILD}.apk
|
|
# Beispiele: timetrack-0.1.0+1.apk timetrack-0.2.0+3.apk
|
|
|
|
set -euo pipefail
|
|
|
|
# ── Defaults ──────────────────────────────────────────────────────────────────
|
|
APK_DIR="build/apk"
|
|
KEEP=15
|
|
DRY_RUN=false
|
|
|
|
# ── Argument-Parsing ──────────────────────────────────────────────────────────
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--dir) APK_DIR="$2"; shift 2 ;;
|
|
--keep) KEEP="$2"; shift 2 ;;
|
|
--dry-run) DRY_RUN=true; shift ;;
|
|
*) echo "Unbekanntes Argument: $1" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── Verzeichnis prüfen ────────────────────────────────────────────────────────
|
|
if [[ ! -d "$APK_DIR" ]]; then
|
|
echo "apk_retention: Verzeichnis '$APK_DIR' nicht gefunden — übersprungen."
|
|
exit 0
|
|
fi
|
|
|
|
# ── Hilfsfunktionen ───────────────────────────────────────────────────────────
|
|
|
|
# Extrahiert "MAJOR.MINOR" aus "timetrack-0.1.0+5.apk" → "0.1"
|
|
minor_version() {
|
|
local name="$1"
|
|
# Dateiname: timetrack-0.1.0+5.apk → Extrahiere "0.1.0" → nehme "0.1"
|
|
local ver
|
|
ver=$(echo "$name" | grep -oP '(?<=timetrack-)\d+\.\d+\.\d+(?=\+)') || true
|
|
if [[ -z "$ver" ]]; then echo ""; return; fi
|
|
# Nur Major.Minor
|
|
echo "$ver" | cut -d. -f1-2
|
|
}
|
|
|
|
# Extrahiert Build-Nummer aus "timetrack-0.1.0+5.apk" → 5
|
|
build_number() {
|
|
local name="$1"
|
|
echo "$name" | grep -oP '(?<=\+)\d+(?=\.apk)' || echo "0"
|
|
}
|
|
|
|
# Löscht eine APK + zugehörige .sha256-Datei
|
|
delete_apk() {
|
|
local path="$1"
|
|
local sha="${path}.sha256"
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo " [DRY-RUN] würde löschen: $(basename "$path")"
|
|
[[ -f "$sha" ]] && echo " [DRY-RUN] würde löschen: $(basename "$sha")"
|
|
else
|
|
rm -f "$path"
|
|
[[ -f "$sha" ]] && rm -f "$sha"
|
|
echo " gelöscht: $(basename "$path")"
|
|
fi
|
|
}
|
|
|
|
# ── APKs einlesen (ohne Symlinks) ─────────────────────────────────────────────
|
|
declare -a all_apks=()
|
|
while IFS= read -r -d '' f; do
|
|
name=$(basename "$f")
|
|
# Nur versionierte APKs — kein "timetrack.apk"-Symlink
|
|
if [[ "$name" == timetrack-*.apk ]]; then
|
|
all_apks+=("$name")
|
|
fi
|
|
done < <(find "$APK_DIR" -maxdepth 1 -name "timetrack-*.apk" -not -type l -print0 2>/dev/null)
|
|
|
|
total=${#all_apks[@]}
|
|
if [[ $total -eq 0 ]]; then
|
|
echo "apk_retention: Keine APKs gefunden in '$APK_DIR' — nichts zu tun."
|
|
exit 0
|
|
fi
|
|
|
|
echo "apk_retention: $total APKs gefunden in '$APK_DIR'"
|
|
echo "apk_retention: Retention: letzte $KEEP in aktueller Minor-Version, je 1 pro älterer"
|
|
echo ""
|
|
|
|
# ── Minor-Versionen ermitteln ─────────────────────────────────────────────────
|
|
declare -A minor_map # minor → kommaseparierte Liste von Dateinamen
|
|
for name in "${all_apks[@]}"; do
|
|
mv=$(minor_version "$name")
|
|
if [[ -z "$mv" ]]; then continue; fi
|
|
if [[ -v minor_map["$mv"] ]]; then
|
|
minor_map["$mv"]="${minor_map[$mv]} $name"
|
|
else
|
|
minor_map["$mv"]="$name"
|
|
fi
|
|
done
|
|
|
|
# Sortierte Liste der Minor-Versionen (höchste = aktuell)
|
|
declare -a sorted_minors=()
|
|
while IFS= read -r mv; do
|
|
sorted_minors+=("$mv")
|
|
done < <(printf '%s\n' "${!minor_map[@]}" | sort -t. -k1,1n -k2,2n)
|
|
|
|
current_minor="${sorted_minors[-1]}"
|
|
echo " Aktuelle Minor-Version : $current_minor"
|
|
echo " Ältere Minor-Versionen : ${sorted_minors[*]::${#sorted_minors[@]}-1}"
|
|
echo ""
|
|
|
|
# ── Bereinigung: Ältere Minor-Versionen ──────────────────────────────────────
|
|
for mv in "${sorted_minors[@]}"; do
|
|
[[ "$mv" == "$current_minor" ]] && continue
|
|
|
|
# Alle APKs dieser Minor-Version nach Build-Nummer sortieren
|
|
declare -a mv_apks=()
|
|
for name in ${minor_map[$mv]}; do
|
|
mv_apks+=("$name")
|
|
done
|
|
|
|
# Sortieren nach Build-Nummer (numerisch)
|
|
declare -a sorted_mv=()
|
|
while IFS= read -r line; do
|
|
sorted_mv+=("$line")
|
|
done < <(printf '%s\n' "${mv_apks[@]}" | sort -t+ -k2,2n)
|
|
|
|
keeper="${sorted_mv[-1]}"
|
|
echo " Minor $mv: behalte $keeper (Release-Marker)"
|
|
|
|
for name in "${sorted_mv[@]}"; do
|
|
[[ "$name" == "$keeper" ]] && continue
|
|
delete_apk "$APK_DIR/$name"
|
|
done
|
|
|
|
unset mv_apks sorted_mv
|
|
done
|
|
|
|
# ── Bereinigung: Aktuelle Minor-Version ──────────────────────────────────────
|
|
declare -a cur_apks=()
|
|
for name in ${minor_map[$current_minor]}; do
|
|
cur_apks+=("$name")
|
|
done
|
|
|
|
# Sortieren nach Build-Nummer (numerisch)
|
|
declare -a sorted_cur=()
|
|
while IFS= read -r line; do
|
|
sorted_cur+=("$line")
|
|
done < <(printf '%s\n' "${cur_apks[@]}" | sort -t+ -k2,2n)
|
|
|
|
cur_count=${#sorted_cur[@]}
|
|
echo " Aktuelle Minor $current_minor: $cur_count APKs, behalte letzte $KEEP"
|
|
|
|
if [[ $cur_count -gt $KEEP ]]; then
|
|
to_delete=$(( cur_count - KEEP ))
|
|
for (( i=0; i<to_delete; i++ )); do
|
|
delete_apk "$APK_DIR/${sorted_cur[$i]}"
|
|
done
|
|
fi
|
|
|
|
# ── Zusammenfassung ───────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "apk_retention: Verbleibende APKs:"
|
|
find "$APK_DIR" -maxdepth 1 -name "timetrack-*.apk" -not -type l \
|
|
| sort | while read -r f; do
|
|
echo " $(basename "$f")"
|
|
done
|
|
|
|
echo ""
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo "apk_retention: [DRY-RUN] Keine Dateien wurden gelöscht."
|
|
else
|
|
echo "apk_retention: Bereinigung abgeschlossen."
|
|
fi
|