mitchellh/go-homedir

Respect Windows directory locations.

MicahZoltu opened this issue · 1 comments

go-homedir/homedir.go

Lines 148 to 167 in af06845

func dirWindows() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
// Prefer standard environment variable USERPROFILE
if home := os.Getenv("USERPROFILE"); home != "" {
return home, nil
}
drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH")
home := drive + path
if drive == "" || path == "" {
return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank")
}
return home, nil
}

TL;DR, change code to

func dirWindows() (string, error) {
	home := os.Getenv("LOCALAPPDATA")
 	if home == "" {
		return "", errors.New("LOCALAPPDATA environment variable is missing or empty")
	}
	return home, nil
}

$HOME is non-standard on Windows, and likely references $USERPROFILE. $USERPROFILE is not meant to be a location that applications store files other than via a save dialog box or similar situation where the user is explicitly putting files there. The proper location to store data that should be automatically synced to a network or uploaded to the cloud is $APPDATA. For data that should be machine-local (e.g., caches, application data, etc.) it should be stored in $LOCALAPPDATA.

In this library, it doesn't appear that you distinguish between data types so $LOCALAPPDATA is the best location. If someone throws a cache in there you don't break the user's profile.

Note: $LOCALAPPDATA has been around since Windows XP/2003 while the fallback you were using of $HOMEDRIVE I think has been deprecated and $HOMEPATH is fairly new (and I think also deprecated), so this is not only more correct, but also more backward compatible than the code currently present.

Since Go 1.13 it is better to use os.UserConfigDir() or os.UserCacheDir() (and probably avoid os.UserHomeDir() to store application data).