From 26ce8a9a14ce8b5e4fd19ea187ed417be53b7e0d Mon Sep 17 00:00:00 2001 From: nathaninline Date: Tue, 4 Aug 2026 13:24:42 +0200 Subject: [PATCH] v0.6.14 : creer le dossier bin a la premiere installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sur une machine vierge, le premier lancement du fichier telecharge echouait sur « open C:\ProgramData\jean\bin\jean.exe: The system cannot find the path specified » : appFirstRun creait le dossier de donnees mais pas son sous-dossier bin, cree jusqu'ici par le seul `jean install`. AJEAN demarrait alors depuis le fichier telecharge, sans installation ni raccourcis. MkdirAll deplace dans installSelf, donc valable quel que soit l'appelant. Reproduit puis verifie sur banc d'essai Windows (parcours complet depuis un dossier de donnees inexistant), + test unitaire. --- RELEASE_NOTES.md | 21 ++++++++++++--------- cmd/jean/resource_windows_amd64.syso | Bin 7544 -> 7544 bytes cmd/jean/resource_windows_arm64.syso | Bin 7544 -> 7544 bytes cmd/jean/versioninfo.json | 6 +++--- internal/jean/run.go | 2 +- internal/jean/sys_firstrun_windows_test.go | 15 +++++++++++++++ internal/jean/sys_install_windows.go | 9 +++++++++ 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f500efa..c8d957b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,23 +1,26 @@ ## Correction -**Lancer le fichier téléchargé pendant qu'AJEAN tourne.** Windows désigne un même fichier sous plusieurs écritures, par exemple `Administrateur` et sa forme abrégée `ADMINI~1`. AJEAN comparait ces chemins tels quels, sans les ramener à une écriture commune. Il pouvait donc ne pas reconnaître l'application en cours d'exécution, remplacer le programme en la croyant fermée, et vous laisser avec l'ancienne version toujours à l'écran. C'est le comportement corrigé en 0.6.12, qui revenait par un autre chemin. +**L'installation échouait sur un ordinateur vierge.** Au tout premier lancement du fichier téléchargé, sur une machine où AJEAN n'avait jamais été installé, la fenêtre d'installation s'affichait, puis répondait : -Le même défaut pouvait, dans le cas où le dossier de données est désigné par une écriture abrégée, amener l'application installée à se prendre pour une copie téléchargée et à se relancer sans fin. +``` +Installation impossible : +open C:\ProgramData\jean\bin\jean.exe: The system cannot find the path specified +``` -Les chemins sont désormais ramenés à une écriture unique avant d'être comparés. +AJEAN démarrait alors depuis le fichier téléchargé, sans s'être installé : aucun raccourci, aucun programme dans le menu Démarrer, et le fichier téléchargé restait le seul moyen de le lancer. -## Vérification +La cause : le premier lancement créait bien le dossier de réglages, mais pas le sous-dossier destiné à recevoir le programme. Il n'était créé que par l'installation en ligne de commande. Le dossier est désormais créé au moment d'écrire le programme, quel que soit le chemin emprunté. -Les six situations du lancement sous Windows ont cette fois été jouées sur une machine réelle, avec trois versions distinctes du programme : mise à jour silencieuse application fermée, application en cours avec acceptation puis avec refus, fichier plus ancien que la version installée avec les deux réponses, et recréation des raccourcis supprimés. Le contenu des fenêtres et les numéros de version affichés ont été relus, et chaque essai vérifie que la fenêtre s'est bien refermée avant de conclure. - -C'est ce banc d'essai qui a mis au jour le défaut ci-dessus, que trois relectures du code avaient laissé passer. +Ce cas échappait aux essais des versions précédentes, qui partaient toujours d'une installation déjà en place. Le parcours complet sur une machine vierge est maintenant vérifié, fenêtre après fenêtre, jusqu'au démarrage de l'application et à la présence des raccourcis. ## Mise à jour +Si vous êtes dans ce cas, rien n'est à réparer : téléchargez `jean-windows-amd64.exe` depuis cette page et lancez-le, l'installation se fera cette fois. + +Pour une installation déjà en place : + ``` jean update ``` -Sous Windows, télécharger le fichier depuis la page des releases et le lancer fait le même travail. - L'icône de la barre de menus macOS, introduite en 0.6.10, n'a toujours pas été vérifiée sur une vraie machine. diff --git a/cmd/jean/resource_windows_amd64.syso b/cmd/jean/resource_windows_amd64.syso index 8e9d2e2f9e04de1d771788fdd4dda1e8c5b81b72..8aee975f3f671ff5d129c1ff781e9a9938a4a3f6 100644 GIT binary patch delta 35 ocmexi^}}idmn0`20~-Sf@NE{B6lY>I*{m%c&d6voxmo5b0F>4UJpcdz delta 35 ocmexi^}}idmn0`I0~-Sf@NO2C6lY>I-mEPh&d6vyxmo5b0F;*qIRF3v diff --git a/cmd/jean/resource_windows_arm64.syso b/cmd/jean/resource_windows_arm64.syso index 2dff83fb5de8e88ffb2691440f560c6a686eaac4..66bd09de0156fffb3422f181adb6efc709897226 100644 GIT binary patch delta 35 ocmexi^}}idmn0`20~-Sf@NE{B6lY>I*{m%c&d6voxmo5b0F>4UJpcdz delta 35 ocmexi^}}idmn0`I0~-Sf@NO2C6lY>I-mEPh&d6vyxmo5b0F;*qIRF3v diff --git a/cmd/jean/versioninfo.json b/cmd/jean/versioninfo.json index fc58113..2dd6790 100644 --- a/cmd/jean/versioninfo.json +++ b/cmd/jean/versioninfo.json @@ -3,13 +3,13 @@ "FileVersion": { "Major": 0, "Minor": 6, - "Patch": 13, + "Patch": 14, "Build": 0 }, "ProductVersion": { "Major": 0, "Minor": 6, - "Patch": 13, + "Patch": 14, "Build": 0 }, "FileFlagsMask": "3f", @@ -25,7 +25,7 @@ "LegalCopyright": "Copyright (c) 2026 AJEAN contributors. MIT License.", "OriginalFilename": "jean.exe", "ProductName": "AJEAN", - "ProductVersion": "0.6.13", + "ProductVersion": "0.6.14", "Comments": "https://github.com/nathaninline/jean — projet open source (MIT)" }, "VarFileInfo": { diff --git a/internal/jean/run.go b/internal/jean/run.go index ac54215..e9d7d41 100644 --- a/internal/jean/run.go +++ b/internal/jean/run.go @@ -10,7 +10,7 @@ import ( "strings" ) -const Version = "0.6.13" +const Version = "0.6.14" // Main est le vrai main() du binaire (cmd/jean ne fait que l'appeler). func Main() { diff --git a/internal/jean/sys_firstrun_windows_test.go b/internal/jean/sys_firstrun_windows_test.go index 62bd6d8..43449ec 100644 --- a/internal/jean/sys_firstrun_windows_test.go +++ b/internal/jean/sys_firstrun_windows_test.go @@ -26,6 +26,21 @@ func TestBinaryVersionReadsResource(t *testing.T) { } } +// Sur une machine vierge, le dossier bin n'existe pas encore : installSelf doit +// le créer. Sans ça, le premier lancement échouait sur « open +// C:\ProgramData\jean\bin\jean.exe: The system cannot find the path specified » +// et AJEAN ne s'installait jamais. +func TestInstallSelfCreatesBinDir(t *testing.T) { + binDir := filepath.Join(t.TempDir(), "jean", "bin") // deux niveaux absents + dst, err := installSelf(binDir) + if err != nil { + t.Fatalf("installSelf sur un dossier absent : %v", err) + } + if _, err := os.Stat(dst); err != nil { + t.Fatalf("binaire non écrit : %v", err) + } +} + // replaceInstalled doit écraser le binaire en place, y compris quand le fichier // cible existe déjà, et laisser l'ancien de côté sans le confondre avec la cible. func TestReplaceInstalled(t *testing.T) { diff --git a/internal/jean/sys_install_windows.go b/internal/jean/sys_install_windows.go index 58bc896..ccce2b6 100644 --- a/internal/jean/sys_install_windows.go +++ b/internal/jean/sys_install_windows.go @@ -100,6 +100,12 @@ func cmdInstall(args []string) error { // installSelf copies the currently running executable into binDir as jean.exe // and returns the destination path. If the running exe already lives there // (re-install), it's a no-op. +// +// binDir est créé ici, et pas seulement par l'appelant : sur une machine vierge, +// le premier lancement passait par appFirstRun, qui ne créait que le dossier de +// données et pas son sous-dossier bin. L'utilisateur recevait alors « open +// C:\ProgramData\jean\bin\jean.exe: The system cannot find the path specified » +// et AJEAN démarrait depuis le fichier téléchargé, sans jamais s'installer. func installSelf(binDir string) (string, error) { src, err := os.Executable() if err != nil { @@ -110,6 +116,9 @@ func installSelf(binDir string) (string, error) { if strings.EqualFold(src, dst) { return dst, nil } + if err := os.MkdirAll(binDir, 0o755); err != nil { + return "", err + } in, err := os.Open(src) if err != nil { return "", err