diff --git a/internal/paths/paths.go b/internal/paths/paths.go new file mode 100644 index 0000000..cc7b425 --- /dev/null +++ b/internal/paths/paths.go @@ -0,0 +1,25 @@ +package paths + +import ( + "fmt" + "os" + "path/filepath" +) + +// TmpoDir returns the base directory for tmpo's data. Normally this is +// ~/.tmpo, but when the TMPO_DEV environment variable is set to "1" or +// "true" a separate ~/.tmpo-dev directory is used so development runs do +// not touch production data. +func TmpoDir() (string, error) { + home, err := os.UserHomeDir() + if err != nil { + return "", fmt.Errorf("failed to get home directory: %w", err) + } + + dir := ".tmpo" + if devMode := os.Getenv("TMPO_DEV"); devMode == "1" || devMode == "true" { + dir = ".tmpo-dev" + } + + return filepath.Join(home, dir), nil +} diff --git a/internal/paths/paths_test.go b/internal/paths/paths_test.go new file mode 100644 index 0000000..932eacd --- /dev/null +++ b/internal/paths/paths_test.go @@ -0,0 +1,46 @@ +package paths + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTmpoDir(t *testing.T) { + home, err := os.UserHomeDir() + assert.NoError(t, err) + + t.Run("uses .tmpo by default", func(t *testing.T) { + t.Setenv("TMPO_DEV", "") + + dir, err := TmpoDir() + assert.NoError(t, err) + assert.Equal(t, filepath.Join(home, ".tmpo"), dir) + }) + + t.Run("uses .tmpo-dev when TMPO_DEV=1", func(t *testing.T) { + t.Setenv("TMPO_DEV", "1") + + dir, err := TmpoDir() + assert.NoError(t, err) + assert.Equal(t, filepath.Join(home, ".tmpo-dev"), dir) + }) + + t.Run("uses .tmpo-dev when TMPO_DEV=true", func(t *testing.T) { + t.Setenv("TMPO_DEV", "true") + + dir, err := TmpoDir() + assert.NoError(t, err) + assert.Equal(t, filepath.Join(home, ".tmpo-dev"), dir) + }) + + t.Run("uses .tmpo for other TMPO_DEV values", func(t *testing.T) { + t.Setenv("TMPO_DEV", "0") + + dir, err := TmpoDir() + assert.NoError(t, err) + assert.Equal(t, filepath.Join(home, ".tmpo"), dir) + }) +} diff --git a/internal/settings/global_config.go b/internal/settings/global_config.go index 2c83488..1579177 100644 --- a/internal/settings/global_config.go +++ b/internal/settings/global_config.go @@ -8,6 +8,7 @@ import ( "github.com/DylanDevelops/tmpo/internal/currency" "github.com/DylanDevelops/tmpo/internal/fsperm" + "github.com/DylanDevelops/tmpo/internal/paths" "go.yaml.in/yaml/v3" ) @@ -33,14 +34,9 @@ func DefaultGlobalConfig() *GlobalConfig { // the TMPO_DEV environment variable is set to 1 or true, a // developer-specific config path is returned. func GetGlobalConfigPath() (string, error) { - home, err := os.UserHomeDir() + tmpoDir, err := paths.TmpoDir() if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - - tmpoDir := filepath.Join(home, ".tmpo") - if devMode := os.Getenv("TMPO_DEV"); devMode == "1" || devMode == "true" { - tmpoDir = filepath.Join(home, ".tmpo-dev") + return "", err } return filepath.Join(tmpoDir, "config.yaml"), nil diff --git a/internal/settings/projects.go b/internal/settings/projects.go index ed61450..79f8243 100644 --- a/internal/settings/projects.go +++ b/internal/settings/projects.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/DylanDevelops/tmpo/internal/fsperm" + "github.com/DylanDevelops/tmpo/internal/paths" "go.yaml.in/yaml/v3" ) @@ -25,14 +26,9 @@ type ProjectsRegistry struct { // GetProjectsPath returns the path to the global projects registry file func GetProjectsPath() (string, error) { - home, err := os.UserHomeDir() + tmpoDir, err := paths.TmpoDir() if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - - tmpoDir := filepath.Join(home, ".tmpo") - if devMode := os.Getenv("TMPO_DEV"); devMode == "1" || devMode == "true" { - tmpoDir = filepath.Join(home, ".tmpo-dev") + return "", err } return filepath.Join(tmpoDir, "projects.yaml"), nil diff --git a/internal/storage/db.go b/internal/storage/db.go index a96afa8..2e61def 100644 --- a/internal/storage/db.go +++ b/internal/storage/db.go @@ -3,12 +3,12 @@ package storage import ( "database/sql" "fmt" - "os" "path/filepath" "strings" "time" "github.com/DylanDevelops/tmpo/internal/fsperm" + "github.com/DylanDevelops/tmpo/internal/paths" _ "modernc.org/sqlite" ) @@ -17,15 +17,7 @@ type Database struct { } func getTmpoDir() (string, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - tmpoDir := filepath.Join(homeDir, ".tmpo") - if devMode := os.Getenv("TMPO_DEV"); devMode == "1" || devMode == "true" { - tmpoDir = filepath.Join(homeDir, ".tmpo-dev") - } - return tmpoDir, nil + return paths.TmpoDir() } func Initialize() (*Database, error) {