v0.6.14 : creer le dossier bin a la premiere installation

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.
This commit is contained in:
nathaninline committed 2026-08-04 13:24:42 +02:00
1 parent 0e94f1e9e2
commit 26ce8a9a14
7 files changed
+40 -13

No files matched your search

+12 -9
View File
@@ -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.
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -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": {
+1 -1
View File
@@ -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() {
@@ -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) {
+9
View File
@@ -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