commit 31d0031
Jan Fooken
·
2025-01-29 16:37:42 +0000 UTC
parent 743bbea
Prefer $XDG_CONFIG_HOME over platform's directory on MacOS This commit implements the preference of $XDG_CONFIG_HOME over the platform's native equivalent on MacOS. This allows users to use $HOME/.config as preferred path for storing configurations. This is preferred by a lot of people, who are using Git repositories to backup their dotfiles. Furthermore, there is precedence of macOS applications storing their configuration files in $HOME/.config by default. Also added: a "migration" from the preivous configuration file for users that had already this envrionment variable set. Signed-off-by: Jan Fooken <jan@faulty.computer> Co-authored-by: delthas <delthas@dille.cc> Fixes: https://todo.sr.ht/~delthas/senpai/174
2 files changed,
+74,
-17
+73,
-16
1@@ -4,11 +4,13 @@ import (
2 "errors"
3 "flag"
4 "fmt"
5+ "io"
6 "math/rand"
7 "os"
8 "os/signal"
9 "os/user"
10 "path"
11+ "runtime"
12 "strings"
13 "syscall"
14 "time"
15@@ -38,15 +40,49 @@ func main() {
16 return
17 }
18
19+ var previousConfigPath string
20 if configPath == "" {
21 configDir, err := os.UserConfigDir()
22 if err != nil {
23 panic(err)
24 }
25+ if runtime.GOOS == "darwin" {
26+ if dir := os.Getenv("XDG_CONFIG_HOME"); dir != "" && dir != configDir {
27+ previousConfigPath = configDir
28+ configDir = dir
29+ }
30+ }
31 configPath = path.Join(configDir, "senpai", "senpai.scfg")
32+ if previousConfigPath != "" {
33+ previousConfigPath = path.Join(previousConfigPath, "senpai", "senpai.scfg")
34+ }
35 }
36
37 cfg, err := senpai.LoadConfigFile(configPath)
38+ if err != nil && errors.Is(err, os.ErrNotExist) && previousConfigPath != "" {
39+ var ee error
40+ cfg, ee = senpai.LoadConfigFile(previousConfigPath)
41+ if ee == nil {
42+ err = nil
43+ fmt.Fprintf(os.Stderr, "Configuration assistant: Previous configuration file found at %q; the new default configuration location is now %q\n", previousConfigPath, configPath)
44+ fmt.Fprintf(os.Stderr, "Configuration assistant: You can run senpai with an explicit -config path argument, or move the file to its new location.\n")
45+ fmt.Fprintf(os.Stderr, "Configuration assistant: Would you like senpai to move the configuration file to the new location? (examples: yes, no) [optional, default: yes]: ")
46+ move := true
47+ scanBool(&move)
48+ if move {
49+ if err := copyContents(configPath, previousConfigPath); err != nil {
50+ fmt.Fprintf(os.Stderr, "failed to move the configuration file: %v\n", err)
51+ os.Exit(1)
52+ return
53+ }
54+ if err := os.Remove(previousConfigPath); err != nil {
55+ fmt.Fprintf(os.Stderr, "failed to delete the previous configuration file at %q: %v\n", previousConfigPath, err)
56+ os.Exit(1)
57+ return
58+ }
59+ }
60+ }
61+ }
62 if err != nil {
63 if !errors.Is(err, os.ErrNotExist) {
64 fmt.Fprintf(os.Stderr, "failed to load the required configuration file at %q: %s\n", configPath, err)
65@@ -72,22 +108,7 @@ func main() {
66 fmt.Fprintf(os.Stderr, "Configuration assistant: Enter your server port (examples: 6667, 6697) [optional]: ")
67 fmt.Scanln(&port)
68 fmt.Fprintf(os.Stderr, "Configuration assistant: Enter whether your server uses TLS (examples: yes, no) [optional, default: yes]: ")
69- for {
70- var tlsStr string
71- fmt.Scanln(&tlsStr)
72- if tlsStr == "" {
73- break
74- }
75- switch strings.ToLower(tlsStr) {
76- case "y", "yes":
77- tls = true
78- case "n", "no":
79- tls = false
80- default:
81- continue
82- }
83- break
84- }
85+ scanBool(&tls)
86 var defaultNick string
87 if u, err := user.Current(); err == nil {
88 defaultNick = u.Username
89@@ -147,6 +168,7 @@ func main() {
90 time.Sleep(500 * time.Millisecond)
91 fmt.Fprintf(os.Stderr, ".")
92 }
93+ fmt.Fprintf(os.Stderr, "\n")
94 }
95
96 cfg.Debug = cfg.Debug || debug
97@@ -183,6 +205,41 @@ func main() {
98 }
99 }
100
101+func scanBool(v *bool) {
102+ for {
103+ var s string
104+ fmt.Scanln(&s)
105+ if s == "" {
106+ return
107+ }
108+ switch strings.ToLower(s) {
109+ case "y", "yes":
110+ *v = true
111+ return
112+ case "n", "no":
113+ *v = false
114+ return
115+ }
116+ }
117+}
118+
119+func copyContents(dstPath string, srcPath string) error {
120+ src, err := os.Open(srcPath)
121+ if err != nil {
122+ return fmt.Errorf("open %q: %v", srcPath, err)
123+ }
124+ defer src.Close()
125+ dst, err := os.Create(dstPath)
126+ if err != nil {
127+ return fmt.Errorf("create %q: %v", dstPath, err)
128+ }
129+ defer dst.Close()
130+ if _, err := io.Copy(dst, src); err != nil {
131+ return fmt.Errorf("copy %q to %q: %v", srcPath, dstPath, err)
132+ }
133+ return nil
134+}
135+
136 func cachePath() string {
137 cacheDir, err := os.UserCacheDir()
138 if err != nil {
+1,
-1
1@@ -39,7 +39,7 @@ senpai searches for it in the following location:
2
3 $XDG_CONFIG_HOME/senpai/senpai.scfg
4
5-If unset, $XDG_CONFIG_HOME defaults to *~/.config*.
6+If unset, $XDG_CONFIG_HOME defaults to *~/.config* or the platform's equivalent
7
8 For information about the configuration format, see *senpai*(5).
9