diff --git a/CLAUDE.md b/CLAUDE.md index ba7d759..a0096a7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,37 +6,53 @@ Outil Windows (.exe) avec interface graphique qui vérifie les mises à jour de Conçu pour être placé sur une **clé USB** dont la lettre de lecteur peut changer. Le programme peut **s'auto-mettre à jour** car il est lui-même dans un dépôt git. +## Langage + +**Go** (anciennement Python, migré en Go depuis v0.7.x). +- GUI : `github.com/lxn/walk` (contrôles natifs Windows) +- Exe unique, aucune dépendance externe à l'exécution +- Build : `go build` via `build.bat` + ## Structure du projet ``` Lanceur-geco/ -├── git_updater.py # Script principal Python (GUI tkinter) -├── version.txt # Fichier contenant le numéro de version (ex: "0.5.1") -├── config.ini # Configuration multi-repo -├── build.bat # Script de compilation en .exe via PyInstaller -├── log/ # Dossier de logs (créé automatiquement, 1 fichier par jour) +├── main.go # Point d'entrée, constante VERSION +├── config.go # Chargement config.ini (repos + self-update) +├── git.go # Opérations git (check, clone, pull, checkout, clean) +├── gui.go # Interface graphique (walk/TableView) +├── logger.go # Logging fichier (1 fichier/jour, rotation 30j) +├── selfupdate.go # Auto-mise à jour du programme +├── platform_windows.go # Code spécifique Windows (création processus) +├── version.txt # Numéro de version (utilisé par l'auto-update distant) +├── config.ini # Configuration multi-repo +├── build.bat # Script de compilation en .exe +├── app.manifest # Manifeste Windows (DPI, elevation) +├── icon.ico # Icône application +├── go.mod / go.sum # Dépendances Go +├── log/ # Dossier de logs (créé automatiquement) └── CLAUDE.md ``` ## Règles importantes - **Tous les chemins doivent être relatifs** à l'emplacement de l'exe. Jamais de chemin absolu (pas de `C:\`, `G:\`, etc.). Utiliser `..` et des chemins relatifs pour référencer les dossiers. -- **Accès lecture seule** : le programme ne fait que `git fetch`, `git pull` et `git checkout`. Jamais de `git push`, `git commit`, `git add`, ou toute opération d'écriture vers le remote. +- **Accès lecture seule** : le programme ne fait que `git ls-remote`, `git fetch`, `git pull`, `git checkout` et `git clean`. Jamais de `git push`, `git commit`, `git add`, ou toute opération d'écriture vers le remote. - **Multi-repo** : le programme peut surveiller plusieurs dépôts Git configurés dans `config.ini`. ## Versioning -- La version est définie en dur dans `git_updater.py` via la constante `VERSION` (ex: `VERSION = "0.5.1"`) +- La version est définie en dur dans `main.go` via la constante `VERSION` (ex: `const VERSION = "0.7.6"`) - Le fichier `version.txt` à la racine du projet contient le même numéro de version (utilisé par le mécanisme d'auto-update distant) -- Format : **semver simplifié** `MAJEUR.MINEUR.PATCH` (ex: `0.5.1`) -- **Les deux doivent toujours être synchronisés** : quand on change la version, mettre à jour `VERSION` dans `git_updater.py` ET `version.txt` +- Format : **semver simplifié** `MAJEUR.MINEUR.PATCH` (ex: `0.7.6`) +- **Les deux doivent toujours être synchronisés** : quand on change la version, mettre à jour `VERSION` dans `main.go` ET `version.txt` ### Mise à jour de la version A chaque changement de version, il faut mettre à jour **4 éléments** : -1. `VERSION` dans `git_updater.py` (constante en haut du fichier) +1. `VERSION` dans `main.go` (constante en haut du fichier) 2. `version.txt` à la racine du projet -3. **Recompiler l'exe** via `build.bat` et copier `dist/GitUpdateChecker.exe` à la racine du projet +3. **Recompiler l'exe** via `build.bat` (produit `GitUpdateChecker.exe` à la racine) 4. **Créer un commit** avec le message suivant : ``` @@ -50,18 +66,18 @@ Changements : Exemple : ``` -v0.5.2 - Detection depot hors ligne +v0.7.6 - Clone dossier non-vide et verification rapide Changements : -- Ajout verification connectivite remote avant fetch (git ls-remote) -- Affichage "HORS LIGNE" si le serveur est inaccessible -- Synchronisation auto de l'URL origin depuis config.ini +- Clone dans dossier non-vide (git init + remote add + fetch + checkout) +- Verification rapide via git ls-remote au lieu de git fetch +- Support branche par repo dans config.ini ``` ### Mécanisme de comparaison -- La fonction `_version_tuple(v)` convertit la chaîne version en tuple d'entiers (ex: `"0.5.1"` -> `(0, 5, 1)`) pour permettre la comparaison numérique -- L'auto-update télécharge `version.txt` depuis le serveur Gitea via HTTP (`{repo_url}/raw/branch/master/version.txt`) et compare avec la `VERSION` locale +- La fonction `parseVersion(v)` convertit la chaîne version en `[3]int` (ex: `"0.7.6"` -> `[0, 7, 6]`) pour permettre la comparaison numérique +- L'auto-update télécharge `version.txt` depuis le serveur Gitea via HTTP (`{repo_url}/raw/branch/{branch}/version.txt`) et compare avec la `VERSION` locale - Si la version distante est supérieure, une mise à jour est proposée ## Fonctionnement @@ -71,64 +87,77 @@ Changements : 2. Compare la version distante avec la constante `VERSION` locale (comparaison par tuple numérique) 3. Si la version distante est supérieure, propose de télécharger le nouvel exe 4. Stratégie de remplacement : télécharge dans `.new`, renomme l'exe actuel en `.old`, place le nouveau -5. Après mise à jour, demande un redémarrage +5. Après mise à jour, lance un script batch de redémarrage ### Vérification des dépôts 1. Lit la liste des dépôts depuis `config.ini` (chemins relatifs à l'exe) -2. Pour chaque dépôt : - - `git fetch` pour récupérer l'état distant - - Compare commits locaux vs distants - - Détecte les fichiers supprimés/modifiés localement -3. Affiche le résultat dans une interface graphique (tkinter) +2. Pour chaque dépôt (en parallèle via goroutines) : + - `git ls-remote` pour vérifier la disponibilité et comparer les hashs (rapide, timeout 15s) + - `git status --porcelain` pour détecter les fichiers modifiés/non suivis localement +3. Affiche le résultat dans une interface graphique (walk/TableView) 4. Propose pour chaque dépôt : - - `git pull` si nouveaux commits distants - - `git checkout -- .` si fichiers locaux manquants/modifiés + - `git pull` si MAJ disponible (hash distant différent) + - `git checkout -- .` si fichiers locaux modifiés + - `git clean -fd` si fichiers non suivis en trop + +### Clone dans dossier non-vide +Si le dossier cible existe déjà mais n'a pas de `.git` (ex: repos imbriqués), le programme fait un clone "in-place" : +`git init` + `git remote add` + `git fetch` + `git checkout -b ` ## Configuration (config.ini) Supporte plusieurs sections `[repo:NomDuRepo]` : ```ini -[repo:Batch] -url = http://192.168.1.235:3125/zogzog/Batch -path = ../Batch +[self-update] +url = http://192.168.1.235:3125/zogzog/Lanceur-geco +exe_name = GitUpdateChecker.exe +branch = master -[repo:Powershell] -url = http://192.168.1.235:3125/zogzog/Powershell -path = ../Powershell +[repo:Scripts] +url = http://192.168.1.235:3125/zogzog/Scripts +path = ../SOFT/Batch/Scripts + +[repo:Soft] +url = http://192.168.1.235:3125/zogzog/Soft.git +path = ../SOFT/ +branch = master ``` - `url` : URL du dépôt Git distant - `path` : Chemin **relatif** vers le dossier local du dépôt (relatif à l'exe) +- `branch` : Branche à suivre (optionnel, défaut: `master`) ## Logging - Les logs sont écrits dans `log/` à côté de l'exe (1 fichier par jour, format `YYYY-MM-DD.log`) - Les vieux logs sont nettoyés automatiquement (30 jours de rétention) - Chaque action git, erreur, et résultat est loggé avec timestamp -- Bouton "Ouvrir les logs" dans la GUI pour accéder au dossier +- Bouton "Logs" dans la GUI pour ouvrir le dossier ## Build ```bat build.bat ``` -Requiert Python + pip. Installe PyInstaller automatiquement si absent. -Produit `dist/GitUpdateChecker.exe`. Copier `config.ini` à côté de l'exe. +Requiert Go installé et dans le PATH. Installe `rsrc` automatiquement si absent. +Produit `GitUpdateChecker.exe` à la racine (exe unique, pas de dépendances). +Flags de build : `-H windowsgui -s -w` (pas de console, symboles strippés). ## Contraintes techniques - **Chemins relatifs** : Tout est relatif à l'exe, jamais de chemin absolu -- **Encodage** : Force UTF-8 pour les caractères Unicode - **Clé USB** : Fonctionne sur n'importe quelle lettre de lecteur - **Git requis** : Git doit être installé et dans le PATH de la machine - **Serveur Gitea** : Le remote origin pointe vers une instance Gitea locale (192.168.1.235:3125) - **Lecture seule** : Aucune opération d'écriture vers le remote (pas de push/commit) -- **Interface** : GUI tkinter (inclus dans Python, pas de dépendance externe) +- **Interface** : GUI native Windows via walk (pas de console) - **Logs** : Dossier `log/` à côté de l'exe, rotation automatique 30 jours +- **Repos imbriqués** : Supporte les dépôts git imbriqués (ex: parent/enfant) via clone in-place ## Conventions -- Langage : Python 3, pas de dépendances externes (seulement stdlib + tkinter) -- Interface : GUI tkinter en français -- Langue : Français pour l'interface utilisateur +- Langage : Go 1.22+ +- GUI : github.com/lxn/walk (contrôles natifs Windows) +- Interface en français +- Pas de console (flag `-H windowsgui`) diff --git a/GitUpdateChecker.exe b/GitUpdateChecker.exe index 4990f29..d91a3fa 100644 Binary files a/GitUpdateChecker.exe and b/GitUpdateChecker.exe differ diff --git a/gitchecker.exe b/gitchecker.exe index b5462aa..87a2e7d 100644 Binary files a/gitchecker.exe and b/gitchecker.exe differ diff --git a/gui.go b/gui.go index 48d47c6..e063982 100644 --- a/gui.go +++ b/gui.go @@ -1,7 +1,10 @@ package main import ( + "bytes" + _ "embed" "fmt" + "image/png" "os" "os/exec" "path/filepath" @@ -14,6 +17,9 @@ import ( . "github.com/lxn/walk/declarative" ) +//go:embed icon.png +var iconPNG []byte + // ── Modèle TableView ────────────────────────────────────────────────────────── type RepoItem struct { @@ -206,6 +212,7 @@ func (m *RepoModel) hasUpdates() bool { type App struct { mw *walk.MainWindow + iconView *walk.ImageView statusLabel *walk.Label tv *walk.TableView model *RepoModel @@ -242,6 +249,12 @@ func (a *App) buildAndRun() error { Composite{ Layout: HBox{MarginsZero: true}, Children: []Widget{ + ImageView{ + AssignTo: &a.iconView, + MinSize: Size{Width: 24, Height: 24}, + MaxSize: Size{Width: 24, Height: 24}, + Mode: ImageViewModeIdeal, + }, Label{ Text: "Git Update Checker v" + VERSION, Font: Font{Bold: true, PointSize: 12}, @@ -322,13 +335,20 @@ func (a *App) buildAndRun() error { return err } - // Icône fenêtre + // Icône fenêtre (depuis fichier .ico externe) if icoPath := filepath.Join(exeDir(), "icon.ico"); fileExists(icoPath) { if icon, err := walk.NewIconFromFile(icoPath); err == nil { a.mw.SetIcon(icon) } } + // Icône dans l'en-tête (depuis PNG embarqué dans l'exe) + if img, err := png.Decode(bytes.NewReader(iconPNG)); err == nil { + if bmp, err := walk.NewBitmapFromImageForDPI(img, 96); err == nil { + a.iconView.SetImage(bmp) + } + } + // Lancer la vérification au démarrage go func() { time.Sleep(150 * time.Millisecond) diff --git a/icon.png b/icon.png index b83e484..a599664 100644 Binary files a/icon.png and b/icon.png differ diff --git a/main.go b/main.go index 8e52737..f3033ad 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/lxn/walk" ) -const VERSION = "0.7.6" +const VERSION = "0.7.7" func exeDir() string { exe, err := os.Executable() diff --git a/version.txt b/version.txt index c006218..879be8a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.7.6 +0.7.7