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:
Binary file not shown.
@@ -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)
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.5.3
|
||||
0.5.4
|
||||
|
||||
Reference in New Issue
Block a user