Giter Site home page Giter Site logo

go-homedir's People

Contributors

bredov avatar crossai-2033 avatar knu avatar leighmcculloch avatar matt3o12 avatar mbrancato avatar mitchellh avatar rodcloutier avatar rubenv avatar sselph avatar tianon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-homedir's Issues

Respect Windows directory locations.

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.

exec.Run does not return exec.ErrNotFound error

I don't have getent on my system, so the dirUnix function failed to execute it. It checks (https://github.com/mitchellh/go-homedir/blob/master/homedir.go#L87) if the exec.ErrNotFound error is returned, but this error is wrapped by exec.Error() so the returned error will never be exec.ErrNotFound.

The actual returned error message is: exec: "getent": executable file not found in $PATH, whereas it expected the following: executable file not found in $PATH.

A fix would be if strings.HasSufix(err.Error(), err.ErrNotFound.Error()) {.

Directorys starting with ~something throw an error

In a MR in containers/common someone mentioned this package after I already reimplemented this module.
While looking into this, I found a bug in your code:
homedir.Expand("~something")

This throws an "cannot expand user-specific home dir". Directory names starting with a "~" are valid, so this is a bug in my opinion.

I implemented the function (using os/user) as follows:

// resolveHomeDir converts a path referencing the home directory via "~"
// to an absolute path
func resolveHomeDir(path string) (string, error) {
	// check if the path references the home dir to avoid work
	// don't use strings.HasPrefix(path, "~") as this doesn't match "~" alone
	// use strings.HasPrefix(...) to not match "something/~/something"
	if !(path == "~" || strings.HasPrefix(path, "~/")) {
		// path does not reference home dir -> Nothing to do
		return path, nil
	}

	// only get HomeDir when necessary
	home, err := unshare.HomeDir()
	if err != nil {
		return "", err
	}

	// replace the first "~" (start of path) with the HomeDir to resolve "~"
	return strings.Replace(path, "~", home, 1), nil
}

By replacing unshare.HomeDir with your Dir function, this issue should be fixed.

Prefer USERPROFILE over HOMEDRIVE/HOMEPATH

I originally opened this in a downstream terraform provider including go-homedir as a dependency. The main issue is that HOMEDRIVE/HOMEPATH are relics of NT4 and not standard environment variables post Windows Vista. They appear to exist sometimes in environments with a history of roaming profiles.

You may read the explanation in the original issue: hashicorp/terraform-provider-azurerm#1395

This document has a table of standard environment variables on Windows: https://msdn.microsoft.com/en-us/library/dd378457(v=vs.85).aspx

go-homedir/homedir.go

Lines 138 to 155 in 3864e76

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

FYI

Go 1.9 ships with os/user.LookupId, os/user.Lookup, os/user.LookupGroup, os/user.LookupGroupId that work without cgo. If you compile without cgo enabled, those functions will read /etc/passwd and /etc/group respectively to find answers to the questions you ask. Which may be good enough for your use case.

(I wrote the functions in question, and I'm curious how well they work for folks. I would appreciate feedback on how well they work or don't. If they don't work, I'd love to help fix them. Thanks!)

Versioning

It would be great to tag some versions.

Is this still relevant?

The os package code seems to be almost the very same. So, is this package still relevant? Or is the std lib os still using cgo somewhere?

From package os.

func UserHomeDir() (string, error) {
	env, enverr := "HOME", "$HOME"
	switch runtime.GOOS {
	case "windows":
		env, enverr = "USERPROFILE", "%userprofile%"
	case "plan9":
		env, enverr = "home", "$home"
	}
	if v := Getenv(env); v != "" {
		return v, nil
	}
	// On some geese the home directory is not always defined.
	switch runtime.GOOS {
	case "android":
		return "/sdcard", nil
	case "ios":
		return "/", nil
	}
	return "", errors.New(enverr + " is not defined")
}

[macOS] Can't expand home directory on if `$HOME` env var is missing

This line within dirUnix() (L87) fails in macOS, as it assumes getent is installed, which is not the case for macOS, as this is a Unix/Linux-only utility.

cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))

This is the error that's returned

"getent": executable file not found in $PATH

Suggest detecting whether the user is on a Mac and use a Mac name resolving binary like dscacheutil or dns-sd.

Does this work on plan9?

I'd like to use this library as one of my users has run into the OSX issue mentioned in the README.

I currently build plan9 binaries - is it likely to work there?

Thanks

Nick

Please push semantic version tag

This package turns out to be a dependency of https://github.com/ipfs/go-ipfs. I am in the process of packaging IPFS for Gentoo where we prefer to build our software from source when we install it. Thus I am also packaging this project and would kindly like to ask you to push a semantic version tag, which makes things a lot easier for me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.