Task 5: Bedienoberfläche zum Festnageln einer Release-Version, in der
bestehenden Update-Handlungsleiste statt einer zweiten daneben.
Bestätigt im Modal (R23), Auswahlfeld selbst ohne Modal (R20).
Zwei Important-Befunde aus dem Code-Review zu Task 3:
- writeAtomic() ignorierte den Rueckgabewert von File::put()/File::move()
und meldete setCeiling() als "true", selbst wenn ein I/O-Fehler (volle
Platte, Rechteproblem) nichts geschrieben oder eine .tmp liegen gelassen
hatte. Beide Rueckgabewerte werden jetzt geprueft, eine liegen gebliebene
.tmp wird im Fehlerfall aufgeraeumt, und der Fehlschlag wird bis zu
setCeiling() durchgereicht (Rueckgabe false).
- ceiling() konnte state() doch werfen lassen: zwischen File::exists() und
File::get() liegt ein Zeitfenster, und File::get() wirft eine
FileNotFoundException, wenn die Datei dazwischen verschwindet. readJson()
und lastLog() kapseln genau dieses Muster schon in try/catch(Throwable);
ceiling() zieht jetzt nach.
Beide Befunde tragen einen eigenen Test: ein Verzeichnis an der Ceiling-
Datei-Stelle (exists() wahr, get() wirft) fuer den zweiten, eine echte
Rechteverweigerung (chmod 0500 als nicht-root Testbenutzer) fuer den
ersten -- kein Facade-Mock noetig.