Compare commits
2 Commits
18bda249b5
...
ba1cf1ea25
| Author | SHA1 | Date | |
|---|---|---|---|
| ba1cf1ea25 | |||
| 3ecae321e7 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ dist/
|
||||
build/
|
||||
__pycache__/
|
||||
*.spec
|
||||
*.exe.old
|
||||
_update.bat
|
||||
|
||||
BIN
GitUpdateChecker.exe
Normal file
BIN
GitUpdateChecker.exe
Normal file
Binary file not shown.
@@ -5,6 +5,8 @@ Accès lecture seule uniquement (fetch/pull/checkout, jamais de push).
|
||||
Tous les chemins sont relatifs à l'emplacement de l'exécutable.
|
||||
"""
|
||||
|
||||
VERSION = "0.1"
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
@@ -139,25 +141,80 @@ def check_self_update():
|
||||
|
||||
|
||||
def do_self_update():
|
||||
"""Pull les mises à jour du programme lui-même. Retourne (ok, message)."""
|
||||
"""
|
||||
Met à jour le programme lui-même.
|
||||
Sur Windows, un .exe en cours d'exécution ne peut pas être écrasé.
|
||||
Stratégie : renommer l'exe actuel en .old, puis git pull le nouveau.
|
||||
Retourne (ok, message).
|
||||
"""
|
||||
exe_dir = str(get_exe_dir())
|
||||
is_frozen = getattr(sys, "frozen", False)
|
||||
|
||||
code, branch, _ = run_git(["rev-parse", "--abbrev-ref", "HEAD"], cwd=exe_dir)
|
||||
if code != 0:
|
||||
return False, "Impossible de lire la branche"
|
||||
|
||||
# Restaurer les fichiers locaux modifiés d'abord
|
||||
run_git(["checkout", "--", "."], cwd=exe_dir)
|
||||
# Si on tourne en .exe, renommer l'exe actuel pour libérer le fichier
|
||||
exe_old_path = None
|
||||
if is_frozen:
|
||||
exe_path = Path(sys.executable)
|
||||
exe_old_path = exe_path.with_suffix(".exe.old")
|
||||
try:
|
||||
# Supprimer un ancien .old s'il existe
|
||||
if exe_old_path.exists():
|
||||
exe_old_path.unlink()
|
||||
# Windows permet de renommer un exe en cours d'exécution
|
||||
exe_path.rename(exe_old_path)
|
||||
log.info(f"Auto-update: exe renomme {exe_path.name} -> {exe_old_path.name}")
|
||||
except OSError as e:
|
||||
log.error(f"Auto-update: impossible de renommer l'exe: {e}")
|
||||
return False, f"Impossible de renommer l'exe: {e}"
|
||||
|
||||
# Restaurer les fichiers locaux modifiés puis pull
|
||||
run_git(["checkout", "--", "."], cwd=exe_dir)
|
||||
code, _, err = run_git(["pull", "origin", branch], cwd=exe_dir)
|
||||
|
||||
code, out, err = run_git(["pull", "origin", branch], cwd=exe_dir)
|
||||
if code == 0:
|
||||
log.info(f"Auto-update: pull OK")
|
||||
return True, "Mise a jour du programme reussie !\nRedemarre le programme pour appliquer."
|
||||
log.info("Auto-update: pull OK")
|
||||
return True, "Mise a jour reussie !\nLe programme va redemarrer."
|
||||
else:
|
||||
# En cas d'échec, restaurer l'ancien exe
|
||||
if is_frozen and exe_old_path and exe_old_path.exists():
|
||||
try:
|
||||
exe_old_path.rename(Path(sys.executable))
|
||||
log.info("Auto-update: exe restaure apres echec")
|
||||
except OSError:
|
||||
pass
|
||||
log.error(f"Auto-update: pull echoue: {err}")
|
||||
return False, f"Erreur pull: {err}"
|
||||
|
||||
|
||||
def relaunch_program():
|
||||
"""Relance le programme (nouvel exe) et quitte le processus actuel."""
|
||||
if getattr(sys, "frozen", False):
|
||||
exe_path = str(Path(sys.executable))
|
||||
log.info(f"Auto-update: relance de {exe_path}")
|
||||
# Lancer un batch qui attend 1s puis lance le nouvel exe et supprime l'ancien .old
|
||||
bat_path = str(get_exe_dir() / "_update.bat")
|
||||
bat_content = (
|
||||
f'@echo off\n'
|
||||
f'timeout /t 1 /nobreak >nul\n'
|
||||
f'start "" "{exe_path}"\n'
|
||||
f'del "{exe_path}.old" 2>nul\n'
|
||||
f'del "%~f0"\n'
|
||||
)
|
||||
with open(bat_path, "w") as f:
|
||||
f.write(bat_content)
|
||||
subprocess.Popen(
|
||||
["cmd", "/c", bat_path],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||||
)
|
||||
else:
|
||||
# Mode script : relancer python
|
||||
log.info("Auto-update: relance du script")
|
||||
subprocess.Popen([sys.executable, __file__])
|
||||
|
||||
|
||||
# ── Configuration ────────────────────────────────────────────────────────────
|
||||
|
||||
def get_config_path():
|
||||
@@ -359,7 +416,7 @@ def do_restore(local_path):
|
||||
class App(tk.Tk):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.title("Git Update Checker")
|
||||
self.title(f"Git Update Checker v{VERSION}")
|
||||
self.geometry("820x600")
|
||||
self.minsize(700, 450)
|
||||
self.configure(bg="#1e1e2e")
|
||||
@@ -367,7 +424,7 @@ class App(tk.Tk):
|
||||
self.repos_config = load_repos()
|
||||
self.repo_results = []
|
||||
|
||||
log.info("=== Demarrage Git Update Checker ===")
|
||||
log.info(f"=== Demarrage Git Update Checker v{VERSION} ===")
|
||||
self._build_ui()
|
||||
self.after(100, self._check_self_update_then_repos)
|
||||
|
||||
@@ -395,7 +452,7 @@ class App(tk.Tk):
|
||||
# Header
|
||||
header = ttk.Frame(self)
|
||||
header.pack(fill="x", padx=15, pady=(15, 5))
|
||||
ttk.Label(header, text="Git Update Checker", style="Title.TLabel").pack(side="left")
|
||||
ttk.Label(header, text=f"Git Update Checker v{VERSION}", style="Title.TLabel").pack(side="left")
|
||||
self.status_label = ttk.Label(header, text="Verification en cours...", style="Status.TLabel")
|
||||
self.status_label.pack(side="right")
|
||||
|
||||
@@ -470,7 +527,8 @@ class App(tk.Tk):
|
||||
"""Callback après auto-update."""
|
||||
if ok:
|
||||
messagebox.showinfo("Auto-update", msg)
|
||||
log.info("Auto-update appliquee, fermeture")
|
||||
log.info("Auto-update appliquee, relance...")
|
||||
relaunch_program()
|
||||
self.destroy()
|
||||
return
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user