mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 23:18:13 +02:00
Rebaptise AJEAN en Loki (fork, lignée conservée)
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki) - LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ; units loki-engine / loki-ui ; binaire et aide CLI - updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les binaires AJEAN amont) Conservé à l'identique : le domaine ajean.link (service de tunnel amont), les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et LICENSE (historique et licence de l'amont). go build/vet/test : verts.
This commit is contained in:
157 files changed
+928
-928
No files matched your search
@@ -0,0 +1,86 @@
|
||||
//go:build windows
|
||||
|
||||
package loki
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Redémarrage propre de l'application après une mise à jour, sous Windows.
|
||||
//
|
||||
// Un process ne peut pas se relancer lui-même : tant qu'il tourne, le nouveau
|
||||
// binaire ne peut pas prendre sa place sur le port, et le dossier de données
|
||||
// reste tenu. On délègue donc à un ACCOMPAGNATEUR détaché — une copie de nous
|
||||
// lancée avec une sous-commande interne — qui attend notre disparition, profite
|
||||
// de cette fenêtre pour terminer la migration, puis relance l'application.
|
||||
//
|
||||
// C'est cette fenêtre qui manquait. Une mise à jour en place laisse Loki
|
||||
// tourner, et donc le dossier tenu : le renommage échouait avec « Accès refusé »,
|
||||
// qui sous Windows ne distingue pas un verrou d'un manque de droits. D'où des
|
||||
// postes qui restaient indéfiniment sur l'ancien nom.
|
||||
|
||||
const restartArg = "restart-after-update"
|
||||
|
||||
// scheduleAppRestart lance l'accompagnateur et annonce que le redémarrage est
|
||||
// pris en charge. L'appelant doit ensuite rendre la main puis quitter, pour que
|
||||
// la réponse HTTP parte AVANT que le process ne disparaisse.
|
||||
func scheduleAppRestart() (bool, string) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
cmd := spawnDetached(exe, restartArg, strconv.Itoa(os.Getpid()))
|
||||
if err := cmd.Start(); err != nil {
|
||||
return false, ""
|
||||
}
|
||||
// L'accompagnateur ne doit pas mourir avec nous : spawnDetached l'a déjà
|
||||
// sorti de notre groupe de processus, on se contente de l'oublier.
|
||||
_ = cmd.Process.Release()
|
||||
|
||||
go func() {
|
||||
time.Sleep(1500 * time.Millisecond) // laisser la réponse atteindre le navigateur
|
||||
os.Exit(0)
|
||||
}()
|
||||
return true, "Loki redémarre — la page se reconnectera toute seule dans quelques secondes."
|
||||
}
|
||||
|
||||
// cmdRestartAfterUpdate est exécuté par l'accompagnateur détaché.
|
||||
//
|
||||
// Il n'écrit rien à l'écran : personne ne le regarde, il n'a pas de console, et
|
||||
// son seul travail visible est de faire réapparaître l'application.
|
||||
func cmdRestartAfterUpdate(args []string) error {
|
||||
if len(args) > 0 {
|
||||
if pid, err := strconv.Atoi(args[0]); err == nil {
|
||||
waitForExit(pid, 30*time.Second)
|
||||
}
|
||||
}
|
||||
target := installedExePath()
|
||||
if _, err := os.Stat(target); err != nil {
|
||||
// La cible a disparu : mieux vaut relancer ce qu'on a que rien du tout.
|
||||
if self, e := os.Executable(); e == nil {
|
||||
target = self
|
||||
}
|
||||
}
|
||||
if !launch(target) {
|
||||
return fmt.Errorf("relance de %s impossible", target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// waitForExit attend la fin du process pid, sans dépasser le délai imparti.
|
||||
// Un dépassement n'est pas bloquant : on poursuit quand même, quitte à ce que
|
||||
// la migration échoue et soit retentée plus tard. Rester coincé ici serait pire
|
||||
// — l'utilisateur se retrouverait sans application du tout.
|
||||
func waitForExit(pid int, timeout time.Duration) {
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
if !pidAlive(pid) {
|
||||
time.Sleep(500 * time.Millisecond) // laisser les handles se fermer
|
||||
return
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user