1// Package config provides XDG Base Directory specification compliance utilities.
2package config
3
4import (
5 "os"
6 "path/filepath"
7)
8
9const appName = "dumber"
10
11// XDGDirs holds the XDG Base Directory paths for the application.
12type XDGDirs struct {
13 ConfigHome string
14 DataHome string
15 StateHome string
16}
17
18// GetXDGDirs returns the XDG Base Directory paths for dumber.
19// It follows the XDG Base Directory specification:
20// - $XDG_CONFIG_HOME/dumber (default: ~/.config/dumber)
21// - $XDG_DATA_HOME/dumber (default: ~/.local/share/dumber)
22// - $XDG_STATE_HOME/dumber (default: ~/.local/state/dumber)
23func GetXDGDirs() (*XDGDirs, error) {
24 homeDir, err := os.UserHomeDir()
25 if err != nil {
26 return nil, err
27 }
28
29 // XDG_CONFIG_HOME
30 configHome := os.Getenv("XDG_CONFIG_HOME")
31 if configHome == "" {
32 configHome = filepath.Join(homeDir, ".config")
33 }
34 configHome = filepath.Join(configHome, appName)
35
36 // XDG_DATA_HOME
37 dataHome := os.Getenv("XDG_DATA_HOME")
38 if dataHome == "" {
39 dataHome = filepath.Join(homeDir, ".local", "share")
40 }
41 dataHome = filepath.Join(dataHome, appName)
42
43 // XDG_STATE_HOME
44 stateHome := os.Getenv("XDG_STATE_HOME")
45 if stateHome == "" {
46 stateHome = filepath.Join(homeDir, ".local", "state")
47 }
48 stateHome = filepath.Join(stateHome, appName)
49
50 return &XDGDirs{
51 ConfigHome: configHome,
52 DataHome: dataHome,
53 StateHome: stateHome,
54 }, nil
55}
56
57// GetConfigDir returns the XDG config directory for dumber.
58func GetConfigDir() (string, error) {
59 dirs, err := GetXDGDirs()
60 if err != nil {
61 return "", err
62 }
63 return dirs.ConfigHome, nil
64}
65
66// GetDataDir returns the XDG data directory for dumber.
67func GetDataDir() (string, error) {
68 dirs, err := GetXDGDirs()
69 if err != nil {
70 return "", err
71 }
72 return dirs.DataHome, nil
73}
74
75// GetStateDir returns the XDG state directory for dumber.
76func GetStateDir() (string, error) {
77 dirs, err := GetXDGDirs()
78 if err != nil {
79 return "", err
80 }
81 return dirs.StateHome, nil
82}
83
84// GetLogDir returns the XDG-compliant log directory for dumber.
85// Logs are stored in XDG_STATE_HOME as per specification.
86func GetLogDir() (string, error) {
87 stateDir, err := GetStateDir()
88 if err != nil {
89 return "", err
90 }
91 return filepath.Join(stateDir, "logs"), nil
92}
93
94// GetConfigFile returns the path to the main configuration file.
95func GetConfigFile() (string, error) {
96 configDir, err := GetConfigDir()
97 if err != nil {
98 return "", err
99 }
100 return filepath.Join(configDir, "config.json"), nil
101}
102
103// GetDatabaseFile returns the path to the database file in the state directory.
104func GetDatabaseFile() (string, error) {
105 stateDir, err := GetStateDir()
106 if err != nil {
107 return "", err
108 }
109 return filepath.Join(stateDir, "history.db"), nil
110}
111
112// EnsureDirectories creates the XDG directories if they don't exist.
113func EnsureDirectories() error {
114 dirs, err := GetXDGDirs()
115 if err != nil {
116 return err
117 }
118
119 // Create all directories with proper permissions
120 directories := []string{
121 dirs.ConfigHome,
122 dirs.DataHome,
123 dirs.StateHome,
124 }
125
126 for _, dir := range directories {
127 if err := os.MkdirAll(dir, dirPerm); err != nil {
128 return err
129 }
130 }
131
132 return nil
133}