Skip to content

Commit 0f152c2

Browse files
authored
Update paths to use os specific cache and config folders (#29)
1 parent 7e13c90 commit 0f152c2

7 files changed

Lines changed: 141 additions & 26 deletions

File tree

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,13 @@ gtnh-daily-updater extra add CustomMod --source https://example.com/CustomMod.ja
155155

156156
## Profiles
157157

158-
Profiles are stored as TOML files in:
158+
Profiles are stored as TOML files under the OS-native user config directory:
159159

160-
- `${XDG_CONFIG_HOME:-~/.config}/gtnh-daily-updater/profiles`
160+
- Linux: `${XDG_CONFIG_HOME:-~/.config}/gtnh-daily-updater/profiles`
161+
- macOS: `~/Library/Application Support/gtnh-daily-updater/profiles`
162+
- Windows: `%AppData%\gtnh-daily-updater\profiles`
163+
164+
Profiles previously stored under `~/.config/gtnh-daily-updater` on macOS/Windows are auto-migrated to the new location on first run.
161165

162166
Create and use a profile:
163167

@@ -189,13 +193,15 @@ gtnh-daily-updater update-all main-client alt-server
189193

190194
## Caching and Performance
191195

192-
- Default mod cache directory:
193-
`${XDG_CACHE_HOME:-~/.cache}/gtnh-daily-updater/mods`
194-
Windows: `%LOCALAPPDATA%/gtnh-daily-updater`
196+
- Default mod cache and log directory lives under the OS-native user cache directory:
197+
- Linux: `${XDG_CACHE_HOME:-~/.cache}/gtnh-daily-updater/{mods,logs}`
198+
- macOS: `~/Library/Caches/gtnh-daily-updater/{mods,logs}`
199+
- Windows: `%LocalAppData%\gtnh-daily-updater\{mods,logs}`
200+
- Caches/logs previously stored under `~/.cache/gtnh-daily-updater` on macOS/Windows are auto-migrated to the new location on first run.
195201
- Disable cache with `--no-cache`
196202
- Override cache location with `--cache-dir`
197203
- Control parallel downloads with `--concurrency` (default: `6`)
198-
- Logs are written to `${XDG_CACHE_HOME:-~/.cache}/gtnh-daily-updater/logs/<timestamp>.log`; debug output is always written to the log file regardless of the `-v` flag
204+
- Logs are written to `<cache-dir>/logs/<timestamp>.log`; debug output is always written to the log file regardless of the `-v` flag
199205

200206
## GitHub Token
201207

cmd/root.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/caedis/gtnh-daily-updater/internal/logging"
12+
"github.com/caedis/gtnh-daily-updater/internal/paths"
1213
"github.com/caedis/gtnh-daily-updater/internal/profile"
1314
"github.com/spf13/cobra"
1415
)
@@ -70,9 +71,8 @@ var rootCmd = &cobra.Command{
7071
}
7172

7273
if logFile == "" {
73-
if cacheHome, err := os.UserCacheDir(); err == nil {
74-
logFile = filepath.Join(cacheHome, "gtnh-daily-updater", "logs",
75-
time.Now().Format("2006-01-02_15-04-05")+".log")
74+
if logsDir, err := paths.LogsDir(); err == nil {
75+
logFile = filepath.Join(logsDir, time.Now().Format("2006-01-02_15-04-05")+".log")
7676
}
7777
}
7878

cmd/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func init() {
6767
updateCmd.Flags().BoolVar(&force, "force", false, "Force update even if already up to date")
6868
updateCmd.Flags().BoolVar(&latest, "latest", false, "Use latest non-pre versions for all mods instead of manifest-pinned versions")
6969
updateCmd.Flags().IntVar(&concurrency, "concurrency", 6, "Number of concurrent downloads")
70-
updateCmd.Flags().StringVar(&cacheDir, "cache-dir", "", "Directory for caching downloaded mods (default: ~/.cache/gtnh-daily-updater/mods/)")
70+
updateCmd.Flags().StringVar(&cacheDir, "cache-dir", "", "Directory for caching downloaded mods (default: OS user cache dir + /gtnh-daily-updater/mods/)")
7171
updateCmd.Flags().BoolVar(&noCache, "no-cache", false, "Disable download caching")
7272
rootCmd.AddCommand(updateCmd)
7373
}

cmd/update_all.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func init() {
160160
updateAllCmd.Flags().BoolVar(&forceAll, "force", false, "Force update even if already up to date")
161161
updateAllCmd.Flags().BoolVar(&latestAll, "latest", false, "Use latest non-pre versions for all mods instead of manifest-pinned versions")
162162
updateAllCmd.Flags().IntVar(&concurrencyAll, "concurrency", 6, "Number of concurrent downloads")
163-
updateAllCmd.Flags().StringVar(&cacheDirAll, "cache-dir", "", "Directory for caching downloaded mods (default: ~/.cache/gtnh-daily-updater/mods/)")
163+
updateAllCmd.Flags().StringVar(&cacheDirAll, "cache-dir", "", "Directory for caching downloaded mods (default: OS user cache dir + /gtnh-daily-updater/mods/)")
164164
updateAllCmd.Flags().BoolVar(&noCacheAll, "no-cache", false, "Disable download caching")
165165
rootCmd.AddCommand(updateAllCmd)
166166
}

internal/paths/paths.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Package paths centralizes OS-native cache and config directory resolution
2+
// for gtnh-daily-updater, with lazy migration from previously used
3+
// XDG-hardcoded locations on macOS and Windows.
4+
package paths
5+
6+
import (
7+
"errors"
8+
"os"
9+
"path/filepath"
10+
11+
"github.com/caedis/gtnh-daily-updater/internal/logging"
12+
)
13+
14+
const appName = "gtnh-daily-updater"
15+
16+
// CacheDir returns <UserCacheDir>/gtnh-daily-updater, migrating from the
17+
// legacy XDG_CACHE_HOME / ~/.cache location if present.
18+
func CacheDir() (string, error) {
19+
base, err := os.UserCacheDir()
20+
if err != nil {
21+
return "", err
22+
}
23+
dir := filepath.Join(base, appName)
24+
migrate(legacyCacheDir(), dir)
25+
return dir, nil
26+
}
27+
28+
// ModsCacheDir returns the mod jar cache directory.
29+
func ModsCacheDir() (string, error) {
30+
d, err := CacheDir()
31+
if err != nil {
32+
return "", err
33+
}
34+
return filepath.Join(d, "mods"), nil
35+
}
36+
37+
// LogsDir returns the log directory.
38+
func LogsDir() (string, error) {
39+
d, err := CacheDir()
40+
if err != nil {
41+
return "", err
42+
}
43+
return filepath.Join(d, "logs"), nil
44+
}
45+
46+
// ConfigDir returns <UserConfigDir>/gtnh-daily-updater, migrating from the
47+
// legacy XDG_CONFIG_HOME / ~/.config location if present.
48+
func ConfigDir() (string, error) {
49+
base, err := os.UserConfigDir()
50+
if err != nil {
51+
return "", err
52+
}
53+
dir := filepath.Join(base, appName)
54+
migrate(legacyConfigDir(), dir)
55+
return dir, nil
56+
}
57+
58+
// ProfilesDir returns the profiles directory.
59+
func ProfilesDir() (string, error) {
60+
d, err := ConfigDir()
61+
if err != nil {
62+
return "", err
63+
}
64+
return filepath.Join(d, "profiles"), nil
65+
}
66+
67+
func legacyCacheDir() string {
68+
base := os.Getenv("XDG_CACHE_HOME")
69+
if base == "" {
70+
home, err := os.UserHomeDir()
71+
if err != nil {
72+
return ""
73+
}
74+
base = filepath.Join(home, ".cache")
75+
}
76+
return filepath.Join(base, appName)
77+
}
78+
79+
func legacyConfigDir() string {
80+
base := os.Getenv("XDG_CONFIG_HOME")
81+
if base == "" {
82+
home, err := os.UserHomeDir()
83+
if err != nil {
84+
return ""
85+
}
86+
base = filepath.Join(home, ".config")
87+
}
88+
return filepath.Join(base, appName)
89+
}
90+
91+
// migrate moves oldDir to newDir if oldDir exists, newDir does not, and the
92+
// two paths differ. Failures are logged but non-fatal.
93+
func migrate(oldDir, newDir string) {
94+
if oldDir == "" || oldDir == newDir {
95+
return
96+
}
97+
if _, err := os.Stat(oldDir); err != nil {
98+
return
99+
}
100+
if _, err := os.Stat(newDir); err == nil {
101+
return
102+
} else if !errors.Is(err, os.ErrNotExist) {
103+
return
104+
}
105+
if err := os.MkdirAll(filepath.Dir(newDir), 0o755); err != nil {
106+
logging.Infof(" Warning: could not create %s: %v\n", filepath.Dir(newDir), err)
107+
return
108+
}
109+
if err := os.Rename(oldDir, newDir); err != nil {
110+
logging.Infof(" Warning: could not migrate %s -> %s: %v\n", oldDir, newDir, err)
111+
return
112+
}
113+
logging.Infof("Migrated %s -> %s\n", oldDir, newDir)
114+
}

internal/profile/profile.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"strings"
99

1010
"github.com/BurntSushi/toml"
11+
12+
"github.com/caedis/gtnh-daily-updater/internal/paths"
1113
)
1214

1315
// Profile holds saveable CLI options. All fields are pointers so we can
@@ -24,15 +26,13 @@ type Profile struct {
2426
LogFile *string `toml:"log-file,omitempty"`
2527
}
2628

27-
// Dir returns the profiles directory, using XDG_CONFIG_HOME with a fallback
28-
// to ~/.config.
29+
// Dir returns the profiles directory under the OS-native user config dir.
2930
func Dir() string {
30-
base := os.Getenv("XDG_CONFIG_HOME")
31-
if base == "" {
32-
home, _ := os.UserHomeDir()
33-
base = filepath.Join(home, ".config")
31+
d, err := paths.ProfilesDir()
32+
if err != nil {
33+
return ""
3434
}
35-
return filepath.Join(base, "gtnh-daily-updater", "profiles")
35+
return d
3636
}
3737

3838
// Load reads a named profile from the profiles directory.

internal/updater/workflow_steps.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/caedis/gtnh-daily-updater/internal/logging"
1818
"github.com/caedis/gtnh-daily-updater/internal/lwjgl3ify"
1919
"github.com/caedis/gtnh-daily-updater/internal/manifest"
20+
"github.com/caedis/gtnh-daily-updater/internal/paths"
2021
)
2122

2223
func normalizeRunOptions(opts Options) Options {
@@ -268,14 +269,8 @@ func resolveCacheDirectory(opts Options) string {
268269
if !opts.NoCache {
269270
cacheDir = opts.CacheDir
270271
if cacheDir == "" {
271-
base := os.Getenv("XDG_CACHE_HOME")
272-
if base == "" {
273-
if home, err := os.UserHomeDir(); err == nil {
274-
base = filepath.Join(home, ".cache")
275-
}
276-
}
277-
if base != "" {
278-
cacheDir = filepath.Join(base, "gtnh-daily-updater", "mods")
272+
if d, err := paths.ModsCacheDir(); err == nil {
273+
cacheDir = d
279274
}
280275
}
281276
if cacheDir != "" {

0 commit comments

Comments
 (0)