v0.7.1 : ne plus afficher l'echec de migration a chaque commande

Remonte par un utilisateur Windows non administrateur. Renommer
C:\ProgramData\jean exige d'ecrire dans C:\ProgramData, ce qu'un compte
standard ne peut pas faire : le rename echouait a chaque lancement et le
message technique s'affichait avant CHAQUE commande, y compris `ajean help`.

Rien n'etait casse — le repli sur l'ancien chemin fonctionne comme prevu et
aucune donnee n'est en jeu. Le defaut etait entierement dans l'affichage :
un detail interne presente comme une erreur, sur une situation permanente et
sans consequence.

La raison est desormais enregistree au lieu d'etre imprimee, et ressortie la
ou elle est actionnable : `ajean where`, qui parle justement d'emplacements,
avec la marche a suivre. `ajean install` en administrateur retente la
migration — c'est le seul moment ou les droits sont reunis — et le fait AVANT
de resoudre le dossier, sinon la variable resterait sur l'ancien chemin et on
installerait a cote.

La cause du rename est extraite du *os.LinkError : son texte repete les deux
chemins complets, ce qui donnait trois fois les memes chemins dans un message
qui les cite deja et noyait l'essentiel (« Acces refuse »).

Deux tests : l'echec reste silencieux mais enregistre, et aucun message
parasite quand la migration reussit. Verifie sur un cas reproduit — `help`
est propre, `where` affiche le conseil.
This commit is contained in:
nathaninline committed 2026-08-04 16:40:22 +02:00
1 parent 2b20158e7c
commit b4d2d5ed02
9 files changed
+140 -42

No files matched your search

+17 -8
View File
@@ -38,15 +38,24 @@ EXTRA_ARGS=""
`
func cmdInstall(args []string) error {
jeanHome := AjeanHome()
// Lancé en administrateur, `install` est le moment où la migration peut
// enfin aboutir sur un poste où l'utilisateur courant n'a pas les droits sur
// %ProgramData%. On la retente donc AVANT de résoudre le dossier : l'inverse
// laisserait la variable pointer sur l'ancien chemin et installerait à côté.
if retryHomeMigration() {
fmt.Printf("%s dossier de données migré vers %s\n", green("✓"), AjeanHome())
} else if notice := homeMigrationNotice(); notice != "" {
fmt.Printf("%s %s\n", yellow("[info]"), notice)
}
ajeanHome := AjeanHome()
fmt.Printf("Installation (Windows)\n")
fmt.Printf(" JEAN_HOME = %s\n", jeanHome)
fmt.Printf(" AJEAN_HOME = %s\n", ajeanHome)
fmt.Printf(" service = %s\n", serviceName())
// 1-2. Dossiers + config.env de départ (partagé avec le premier lancement de
// l'app, voir provisionDataDir dans sys_firstrun_windows.go).
conf := filepath.Join(jeanHome, "config.env")
conf := filepath.Join(ajeanHome, "config.env")
_, statErr := os.Stat(conf)
alreadyThere := statErr == nil
if err := provisionDataDir(); err != nil {
@@ -61,7 +70,7 @@ func cmdInstall(args []string) error {
// 3. Install the binary into JEAN_HOME\bin and put that dir on the user PATH,
// so `ajean` is callable from any shell (this is the Windows analogue of the
// /usr/local/bin symlink the Unix installer creates).
binDir := filepath.Join(jeanHome, "bin")
binDir := filepath.Join(ajeanHome, "bin")
if err := os.MkdirAll(binDir, 0o755); err != nil {
return err
}
@@ -237,11 +246,11 @@ func cmdUninstall(args []string) error {
}
if !keepData {
jeanHome := AjeanHome()
if err := os.RemoveAll(jeanHome); err != nil {
return fmt.Errorf("suppression de %s: %w", jeanHome, err)
ajeanHome := AjeanHome()
if err := os.RemoveAll(ajeanHome); err != nil {
return fmt.Errorf("suppression de %s: %w", ajeanHome, err)
}
fmt.Printf(" %s %s supprimé\n", green("✓"), jeanHome)
fmt.Printf(" %s %s supprimé\n", green("✓"), ajeanHome)
} else {
fmt.Println(dim("(données utilisateur conservées — relance avec --purge pour tout supprimer)"))
}