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 8e9d2e2..8aee975 100644 Binary files a/cmd/jean/resource_windows_amd64.syso and b/cmd/jean/resource_windows_amd64.syso differ diff --git a/cmd/jean/resource_windows_arm64.syso b/cmd/jean/resource_windows_arm64.syso index 2dff83f..66bd09d 100644 Binary files a/cmd/jean/resource_windows_arm64.syso and b/cmd/jean/resource_windows_arm64.syso differ 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