Skip to content

Commit eabd1dd

Browse files
jakebaileydeadprogram
authored andcommitted
os: add UserCacheDir and UserConfigDir
1 parent 0e84235 commit eabd1dd

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

src/os/file.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,108 @@ func UserHomeDir() (string, error) {
400400
return "", errors.New(enverr + " is not defined")
401401
}
402402

403+
// UserCacheDir returns the default root directory to use for user-specific
404+
// cached data. Users should create their own application-specific subdirectory
405+
// within this one and use that.
406+
//
407+
// On Unix systems, it returns $XDG_CACHE_HOME as specified by
408+
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
409+
// non-empty, else $HOME/.cache.
410+
// On Darwin, it returns $HOME/Library/Caches.
411+
// On Windows, it returns %LocalAppData%.
412+
// On Plan 9, it returns $home/lib/cache.
413+
//
414+
// If the location cannot be determined (for example, $HOME is not defined),
415+
// then it will return an error.
416+
func UserCacheDir() (string, error) {
417+
var dir string
418+
419+
switch runtime.GOOS {
420+
case "windows":
421+
dir = Getenv("LocalAppData")
422+
if dir == "" {
423+
return "", errors.New("%LocalAppData% is not defined")
424+
}
425+
426+
case "darwin", "ios":
427+
dir = Getenv("HOME")
428+
if dir == "" {
429+
return "", errors.New("$HOME is not defined")
430+
}
431+
dir += "/Library/Caches"
432+
433+
case "plan9":
434+
dir = Getenv("home")
435+
if dir == "" {
436+
return "", errors.New("$home is not defined")
437+
}
438+
dir += "/lib/cache"
439+
440+
default: // Unix
441+
dir = Getenv("XDG_CACHE_HOME")
442+
if dir == "" {
443+
dir = Getenv("HOME")
444+
if dir == "" {
445+
return "", errors.New("neither $XDG_CACHE_HOME nor $HOME are defined")
446+
}
447+
dir += "/.cache"
448+
}
449+
}
450+
451+
return dir, nil
452+
}
453+
454+
// UserConfigDir returns the default root directory to use for user-specific
455+
// configuration data. Users should create their own application-specific
456+
// subdirectory within this one and use that.
457+
//
458+
// On Unix systems, it returns $XDG_CONFIG_HOME as specified by
459+
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
460+
// non-empty, else $HOME/.config.
461+
// On Darwin, it returns $HOME/Library/Application Support.
462+
// On Windows, it returns %AppData%.
463+
// On Plan 9, it returns $home/lib.
464+
//
465+
// If the location cannot be determined (for example, $HOME is not defined),
466+
// then it will return an error.
467+
func UserConfigDir() (string, error) {
468+
var dir string
469+
470+
switch runtime.GOOS {
471+
case "windows":
472+
dir = Getenv("AppData")
473+
if dir == "" {
474+
return "", errors.New("%AppData% is not defined")
475+
}
476+
477+
case "darwin", "ios":
478+
dir = Getenv("HOME")
479+
if dir == "" {
480+
return "", errors.New("$HOME is not defined")
481+
}
482+
dir += "/Library/Application Support"
483+
484+
case "plan9":
485+
dir = Getenv("home")
486+
if dir == "" {
487+
return "", errors.New("$home is not defined")
488+
}
489+
dir += "/lib"
490+
491+
default: // Unix
492+
dir = Getenv("XDG_CONFIG_HOME")
493+
if dir == "" {
494+
dir = Getenv("HOME")
495+
if dir == "" {
496+
return "", errors.New("neither $XDG_CONFIG_HOME nor $HOME are defined")
497+
}
498+
dir += "/.config"
499+
}
500+
}
501+
502+
return dir, nil
503+
}
504+
403505
type (
404506
FileMode = fs.FileMode
405507
FileInfo = fs.FileInfo

src/os/os_anyos_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,42 @@ func TestUserHomeDir(t *testing.T) {
270270
}
271271
}
272272

273+
func TestUserCacheDir(t *testing.T) {
274+
dir, err := UserCacheDir()
275+
if dir == "" && err == nil {
276+
t.Fatal("UserCacheDir returned an empty string but no error")
277+
}
278+
if err != nil {
279+
t.Logf("UserCacheDir failed: %v", err)
280+
return
281+
}
282+
fi, err := Stat(dir)
283+
if err != nil {
284+
t.Fatal(err)
285+
}
286+
if !fi.IsDir() {
287+
t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())
288+
}
289+
}
290+
291+
func TestUserConfigDir(t *testing.T) {
292+
dir, err := UserConfigDir()
293+
if dir == "" && err == nil {
294+
t.Fatal("UserConfigDir returned an empty string but no error")
295+
}
296+
if err != nil {
297+
t.Logf("UserConfigDir failed: %v", err)
298+
return
299+
}
300+
fi, err := Stat(dir)
301+
if err != nil {
302+
t.Fatal(err)
303+
}
304+
if !fi.IsDir() {
305+
t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())
306+
}
307+
}
308+
273309
func TestDirFS(t *testing.T) {
274310
if runtime.GOOS == "windows" {
275311
t.Log("TODO: implement Readdir for Windows")

0 commit comments

Comments
 (0)