diff --git a/README.md b/README.md index 291bd53..9ccfb62 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Sensible fallback locations are used for the folders which are not set. | XDG_CONFIG_DIRS | /etc/xdg | ~/Library/Preferences
/Library/Application Support
/Library/Preferences
~/.config | /lib | | XDG_STATE_HOME | ~/.local/state | ~/Library/Application Support | $home/lib/state | | XDG_CACHE_HOME | ~/.cache | ~/Library/Caches | $home/lib/cache | -| XDG_RUNTIME_DIR | /run/user/UID | ~/Library/Application Support | /tmp | +| XDG_RUNTIME_DIR | /run/user/$UID | ~/Library/Application Support | /tmp | | XDG_BIN_HOME | ~/.local/bin | ~/.local/bin | $home/bin | diff --git a/base_dirs.go b/base_dirs.go index fc482e2..0cdca02 100644 --- a/base_dirs.go +++ b/base_dirs.go @@ -1,6 +1,10 @@ package xdg -import "github.com/adrg/xdg/internal/pathutil" +import ( + "os" + + "github.com/adrg/xdg/internal/pathutil" +) // XDG Base Directory environment variables. const ( @@ -48,7 +52,13 @@ func (bd baseDirectories) cacheFile(relPath string) (string, error) { } func (bd baseDirectories) runtimeFile(relPath string) (string, error) { - return pathutil.Create(relPath, []string{bd.runtime}) + var paths []string + for _, p := range pathutil.Unique([]string{bd.runtime, os.TempDir()}) { + if pathutil.Exists(p) { + paths = append(paths, p) + } + } + return pathutil.Create(relPath, paths) } func (bd baseDirectories) searchDataFile(relPath string) (string, error) { diff --git a/internal/pathutil/pathutil.go b/internal/pathutil/pathutil.go index 554eda6..981580d 100644 --- a/internal/pathutil/pathutil.go +++ b/internal/pathutil/pathutil.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "path/filepath" - "strings" ) // Unique eliminates the duplicate paths from the provided slice and returns @@ -52,7 +51,6 @@ func First(paths []string) string { // relative to the selected parent path. func Create(name string, paths []string) (string, error) { searchedPaths := make([]string, 0, len(paths)) - for _, p := range paths { p = filepath.Join(p, name) @@ -67,8 +65,8 @@ func Create(name string, paths []string) (string, error) { searchedPaths = append(searchedPaths, dir) } - return "", fmt.Errorf("could not create any of the following paths: %s", - strings.Join(searchedPaths, ", ")) + return "", fmt.Errorf("could not create any of the following paths: %v", + searchedPaths) } // Search searches for the file with the specified `name` in the provided @@ -76,7 +74,6 @@ func Create(name string, paths []string) (string, error) { // but it can also contain a set of parent directories. func Search(name string, paths []string) (string, error) { searchedPaths := make([]string, 0, len(paths)) - for _, p := range paths { p = filepath.Join(p, name) if Exists(p) { @@ -86,8 +83,8 @@ func Search(name string, paths []string) (string, error) { searchedPaths = append(searchedPaths, filepath.Dir(p)) } - return "", fmt.Errorf("could not locate `%s` in any of the following paths: %s", - filepath.Base(name), strings.Join(searchedPaths, ", ")) + return "", fmt.Errorf("could not locate `%s` in any of the following paths: %v", + filepath.Base(name), searchedPaths) } // EnvPath returns the value of the environment variable with the specified diff --git a/xdg.go b/xdg.go index 654d1d7..059d695 100644 --- a/xdg.go +++ b/xdg.go @@ -161,8 +161,9 @@ func CacheFile(relPath string) (string, error) { // The relPath parameter must contain the name of the runtime file, and // optionally, a set of parent directories (e.g. appname/app.pid). // If the specified directories do not exist, they will be created relative -// to the base runtime directory. On failure, an error containing the -// attempted paths is returned. +// to the base runtime directory. If the base runtime directory does not exist, +// the operating system's temporary directory is used as a fallback. On failure, +// an error containing the attempted paths is returned. func RuntimeFile(relPath string) (string, error) { return baseDirs.runtimeFile(relPath) } diff --git a/xdg_test.go b/xdg_test.go index 72e1910..53d0604 100644 --- a/xdg_test.go +++ b/xdg_test.go @@ -199,3 +199,20 @@ func TestInvalidPaths(t *testing.T) { require.Error(t, err) } } + +func TestNonExistentRuntimeDir(t *testing.T) { + var ( + envRuntimeDirVar = "XDG_RUNTIME_DIR" + originalRuntimeDir = xdg.RuntimeDir + nonExistentRuntimeDir = filepath.Join(xdg.Home, "runtime") + ) + defer os.Setenv(envRuntimeDirVar, originalRuntimeDir) + + require.NoError(t, os.Setenv(envRuntimeDirVar, nonExistentRuntimeDir)) + xdg.Reload() + require.Equal(t, nonExistentRuntimeDir, xdg.RuntimeDir) + + p, err := xdg.RuntimeFile("app.pid") + require.NoError(t, err) + require.Equal(t, filepath.Clean(os.TempDir()), filepath.Dir(p)) +}