v0.5.4 - Ameliorations de fond

Changements :
- Verification des depots en parallele (ThreadPoolExecutor, max 4) avec progression en temps reel dans le log GUI
- Branche self-update configurable via cle 'branch' dans [self-update] du config.ini (defaut: master)
- Telechargement du nouvel exe en streaming par blocs de 64 Ko au lieu de tout charger en RAM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 19:19:53 +01:00
parent b5068b3a97
commit 6438605d7c
3 changed files with 40 additions and 22 deletions

Binary file not shown.

View File

@@ -5,7 +5,7 @@ Accès lecture seule uniquement (fetch/pull/checkout, jamais de push).
Tous les chemins sont relatifs à l'emplacement de l'exécutable.
"""
VERSION = "0.5.3"
VERSION = "0.5.4"
import subprocess
import sys
@@ -13,6 +13,7 @@ import os
import configparser
import logging
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
import tkinter as tk
from tkinter import ttk, messagebox
from pathlib import Path
@@ -108,19 +109,20 @@ def _version_tuple(v):
def _get_self_update_config():
"""Lit la config [self-update] depuis config.ini. Retourne (url, exe_name) ou (None, None)."""
"""Lit la config [self-update] depuis config.ini. Retourne (url, exe_name, branch) ou (None, None, None)."""
config_path = get_config_path()
if not config_path.exists():
return None, None
return None, None, None
config = configparser.ConfigParser()
config.read(config_path, encoding="utf-8")
if not config.has_section("self-update"):
return None, None
return None, None, None
url = config.get("self-update", "url", fallback="").strip().rstrip("/")
exe_name = config.get("self-update", "exe_name", fallback="GitUpdateChecker.exe").strip()
branch = config.get("self-update", "branch", fallback="master").strip()
if not url:
return None, None
return url, exe_name
return None, None, None
return url, exe_name, branch
def check_self_update():
@@ -129,14 +131,14 @@ def check_self_update():
Télécharge version.txt via HTTP et compare avec VERSION locale.
Retourne (needs_update: bool, info: str).
"""
repo_url, _ = _get_self_update_config()
repo_url, _, branch = _get_self_update_config()
if not repo_url:
log.info("Auto-update: pas de section [self-update] dans config.ini, skip")
return False, ""
log.info("Auto-update: verification via HTTP...")
version_url = f"{repo_url}/raw/branch/master/version.txt"
version_url = f"{repo_url}/raw/branch/{branch}/version.txt"
try:
req = urllib.request.Request(version_url, headers={"User-Agent": "GitUpdateChecker"})
with urllib.request.urlopen(req, timeout=10) as resp:
@@ -162,7 +164,7 @@ def do_self_update():
Stratégie : télécharger dans .new, renommer l'exe actuel en .old, placer le nouveau.
Retourne (ok, message).
"""
repo_url, exe_name = _get_self_update_config()
repo_url, exe_name, branch = _get_self_update_config()
if not repo_url:
return False, "Configuration [self-update] manquante"
@@ -176,21 +178,26 @@ def do_self_update():
exe_new_path = exe_path.with_suffix(".exe.new")
# Telecharger le nouvel exe
download_url = f"{repo_url}/raw/branch/master/{exe_name}"
download_url = f"{repo_url}/raw/branch/{branch}/{exe_name}"
log.info(f"Auto-update: telechargement de {download_url}")
try:
req = urllib.request.Request(download_url, headers={"User-Agent": "GitUpdateChecker"})
with urllib.request.urlopen(req, timeout=60) as resp:
data = resp.read()
total_bytes = 0
with urllib.request.urlopen(req, timeout=60) as resp, open(exe_new_path, "wb") as f:
while True:
chunk = resp.read(65536) # 64 Ko par bloc
if not chunk:
break
f.write(chunk)
total_bytes += len(chunk)
if len(data) < 1000:
log.error(f"Auto-update: fichier telecharge trop petit ({len(data)} octets)")
if total_bytes < 1000:
log.error(f"Auto-update: fichier telecharge trop petit ({total_bytes} octets)")
exe_new_path.unlink(missing_ok=True)
return False, "Le fichier telecharge semble invalide"
with open(exe_new_path, "wb") as f:
f.write(data)
log.info(f"Auto-update: telecharge {len(data)} octets -> {exe_new_path.name}")
log.info(f"Auto-update: telecharge {total_bytes} octets -> {exe_new_path.name}")
except (urllib.error.URLError, OSError) as e:
log.error(f"Auto-update: echec telechargement: {e}")
@@ -671,10 +678,21 @@ class App(tk.Tk):
threading.Thread(target=self._check_all, daemon=True).start()
def _check_all(self):
"""Vérifie tous les repos (dans un thread)."""
results = []
for repo in self.repos_config:
results.append(check_repo(repo))
"""Vérifie tous les repos en parallèle (max 4 à la fois)."""
total = len(self.repos_config)
results = [None] * total
done = 0
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(check_repo, repo): i for i, repo in enumerate(self.repos_config)}
for future in as_completed(futures):
idx = futures[future]
res = future.result()
results[idx] = res
done += 1
self._log_gui(f"[{res['name']}] Verification terminee", "info")
self.after(0, lambda d=done, t=total: self.status_label.configure(text=f"Verification {d}/{t}..."))
self.repo_results = results
self.after(0, self._display_results)

View File

@@ -1 +1 @@
0.5.3
0.5.4