Go library for detecting and expanding the user's home directory without cgo.

go-homedir

This is a Go library for detecting the user's home directory without the use of cgo, so the library can be used in cross-compilation environments.

Usage is incredibly simple, just call homedir.Dir() to get the home directory for a user, and homedir.Expand() to expand the ~ in a path to the home directory.

Why not just use os/user? The built-in os/user package requires cgo on Darwin systems. This means that any Go code that uses that package cannot cross compile. But 99% of the time the use for os/user is just to retrieve the home directory, which we can do for the current user without cgo. This library does that, enabling cross-compilation.

Owner
Comments
  • Please push semantic version tag

    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.

  • Improve getent fallback

    Improve getent fallback

    If HOME is not defined and getent(1) is not found, dirUnix() currently immediately returns an error without even trying the third method (sh -c 'cd && pwd'). It means HOME is the only source for obtaining the home directory on Darwin where getent(1) is missing.

    One possible bug here is that the condition to detect if getent(1) is not found might be reversed, which I addressed in the first commit.

    The second commit adds a fallback method specially for Darwin. It is to execute dscl(1) via the shell, so no dependency on cgo will be involved.

  • Allow paths starting with a tilde

    Allow paths starting with a tilde

    Path expansion currently disallows paths starting with ~. The ~ character is a valid part of a directory or file name. A leading ~ is most commonly found in university server paths where the users have a public web directory, e.g., https://cs.fit.edu/~mmahoney/.

    Return the path as-is if the leading ~ is not referring to a directory name as in ~/ or ~.

  • Does this work on plan9?

    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

  • Directorys starting with ~something throw an 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.

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

    [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.

  • Move OS based implementations behind build flags.

    Move OS based implementations behind build flags.

    What

    Move OS based implementations behind build flags.

    Why

    The fork for choosing the OS based implementation for the home directory is a runtime fork. Go has build flags and can choose code at runtime and this is more efficient and results in the library containing less code.

    Note

    No changes were made to the windows or non-windows implementations. The functions were copied, renamed to dir() and then imports were updated to match the usage in each file.

  • Fixed a bug which would expand string incorrectly under *NIX.

    Fixed a bug which would expand string incorrectly under *NIX.

    If the home environment varible ended with slash ('/'), the the expanded string would have two slashes at some point. For detailed information, see the changed unit tests. homedir now uses filepath.Join to join the string correctly.

  • Prefer USERPROFILE over HOMEDRIVE/HOMEPATH

    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: https://github.com/terraform-providers/terraform-provider-azurerm/issues/1395

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

    https://github.com/mitchellh/go-homedir/blob/3864e76763d94a6df2f9960b16a20a33da9f9a66/homedir.go#L138-L155

  • Added Plan 9 support

    Added Plan 9 support

    Environment variables are lowercase on Plan 9, unlike the traditional unix system where they're uppercase.

    This fixes the check for the "HOME" environment variable under Plan 9.

  • Use path/filepath over hardcoded path separators.

    Use path/filepath over hardcoded path separators.

    What

    Change tests to use path/filepath instead of fmt and hardcoded / path separators.

    Why

    Joining paths with / causes the tests to fail when run on windows because it's file path separator is \. Using path/filepath allows the code to join paths together using the system path separator without the code needing to know what the separator is.

  • Respect Windows directory locations.

    Respect Windows directory locations.

    https://github.com/mitchellh/go-homedir/blob/af06845cf3004701891bf4fdb884bfe4920b3727/homedir.go#L148-L167

    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.

  • FYI

    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!)

  • exec.Run does not return exec.ErrNotFound error

    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()) {.

Command-line tool to organize large directories of media files recursively by date, detecting duplicates.

go-media-organizer Command-line tool written in Go to organise all media files in a directory recursively by date, detecting duplicates.

Jan 6, 2022
The runner project is to create an interface for users to run their code remotely without having to have any compiler on their machine
The runner project is to create an interface for users to run their code remotely without having to have any compiler on their machine

The runner project is to create an interface for users to run their code remotely without having to have any compiler on their machine. This is a work in progress project for TCSS 401X :)

May 29, 2022
A wrapper around cd and xdg-open to use aliases to directory paths in terminal

CDD - Change directories Dynamically I am a lazy linux user and turns out that basic tab completion wasn't enough for me to navigate through my direct

Dec 15, 2022
Grab is a tool that downloads source code repositories into a convenient directory layout created from the repo's URL's domain and path

Grab is a tool that downloads source code repositories into a convenient directory layout created from the repo's URL's domain and path. It supports Git, Mercurial (hg), Subversion, and Bazaar repositories.

Jun 2, 2022
The go mod init command initializes and writes a new go.mod file in the current directory

go mod: The go mod init command initializes and writes a new go.mod file in the current directory, in effect creating a new module rooted at the curre

Nov 21, 2021
Watcher - A simple command line app to watch files in a directory for changes and run a command when files change!

Watcher - Develop your programs easily Watcher watches all the files present in the directory it is run from of the directory that is specified while

Mar 27, 2022
A CLI tool for leveraging IDP signing keys to impersonate users and groups

Imperson8 Disclaimer This is a security testing tool. Only use this on systems you have explicit authorization to test. This isn't an exploit and won'

Jul 23, 2022
Scrappy is a cli tool that allows multiple web scrappers to monitor periodically for a basic ruleset coverage and inform users when the criteria have been met.

Scrappy - A multi-type web scrapper with alerting Scrappy is a cli tool that allows multiple web scrappers to monitor periodically for a basic ruleset

Nov 7, 2021
a command line tool for syncing a local directory to wnfs

wnfs-sync demo demo CLI application to syncronize a local filesystem directory to a public web-native file system directory. # get this binary, assume

Mar 28, 2022
lls is lightweight ls. Using lls, you can get a list of files in a directory that contains a large number of files.

lls lls is lightweight ls. Using lls, you can get a list of files in a directory that contains a large number of files. How? You allocate a buffer for

Dec 29, 2022
A simple CLI tool that identifies duplicate JARS in a directory. It can remove them also if desired.

Mendix Userlib Cleaner This little utility can be used to identify and clean duplicate JARs. It was created mainly for Mendix apps due to lack of form

Nov 15, 2022
A go language implementation of a CLI, based on input directory files

A go language implementation of a CLI, based on input directory files, using tree output of all file names, based on input database links, dynamic reading of database table information, based on input swagger files to automate the generation of the RESTFUL API.

Aug 23, 2022
Golang-based simple file server to serve files of the current working directory

fileserve Golang-based simple file server to serve static files of the current working directory File sharing in LAN or home network Web application t

Jan 9, 2022
Sync local file/directory to pod volume

Sync local file/directory to pod volume

Mar 19, 2022
Rpfaudio - A small opinionated cli to create Readium Audiobooks from a directory containing mp3 files

rpfaudio A small opinionated cli to create Readium Audiobooks from a directory c

Feb 18, 2022
Turn .mp3 files in current directory to a podcast feed just one command.

dir2cast Turn .mp3 files in current directory to a podcast feed just one command. Then you can subscribe to it with your favorite podcast client, down

Jun 27, 2022
An easy to use menu structure for cli applications that prompts users to make choices.
An easy to use menu structure for cli applications that prompts users to make choices.

WMenu Package wmenu creates menus for cli programs. It uses wlog for its interface with the command line. It uses os.Stdin, os.Stdout, and os.Stderr w

Dec 26, 2022
Visp is a Vi-like Spotify client for terminal users.
Visp is a Vi-like Spotify client for terminal users.

Visp Visp is an interactive console client for Spotify, written in Go. Its interface is similar to Vim, and aims to be fast, configurable, and practic

Dec 31, 2022
Prompts users to enter values for required flags in Cobra CLI applications

Cobra Flag Prompt Cobra Flag Prompt prompts users to enter values for required flags. It is an extension of Cobra, and requires that you use Cobra to

Nov 13, 2021