From baac067a1a0aa0d387b60a19977c901a3863fe97 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Thu, 2 Nov 2017 10:25:50 -0200 Subject: [PATCH] expand home dir ("~" symbol) on paths fixes #74 --- Gopkg.lock | 8 +- Gopkg.toml | 4 + internal/status/glob.go | 5 + variables.go | 12 +- .../github.com/mitchellh/go-homedir/LICENSE | 21 +++ .../github.com/mitchellh/go-homedir/README.md | 14 ++ .../mitchellh/go-homedir/homedir.go | 137 ++++++++++++++++++ 7 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/mitchellh/go-homedir/LICENSE create mode 100644 vendor/github.com/mitchellh/go-homedir/README.md create mode 100644 vendor/github.com/mitchellh/go-homedir/homedir.go diff --git a/Gopkg.lock b/Gopkg.lock index a9040478e8..c92355144e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -43,6 +43,12 @@ packages = [".","fastwalk"] revision = "4ecb59231939b2e499b1f2fd8f075565977d2452" +[[projects]] + branch = "master" + name = "github.com/mitchellh/go-homedir" + packages = ["."] + revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" + [[projects]] name = "github.com/pmezard/go-difflib" packages = ["difflib"] @@ -106,6 +112,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "10e83efacd30cadfc07b31678375bdf2e6be288a8b9d175768b1f2efc914f5e1" + inputs-digest = "da52cb2c602c1362c303cf241aa18dfd6199f30484bb12684adb0b6927391cbf" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index c2b26cd57e..4545ba7aca 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -97,3 +97,7 @@ [[constraint]] branch = "master" name = "github.com/radovskyb/watcher" + +[[constraint]] + branch = "master" + name = "github.com/mitchellh/go-homedir" diff --git a/internal/status/glob.go b/internal/status/glob.go index 04ffe6d29a..ef8e5c50a8 100644 --- a/internal/status/glob.go +++ b/internal/status/glob.go @@ -5,6 +5,7 @@ import ( "sort" "github.com/mattn/go-zglob" + "github.com/mitchellh/go-homedir" ) func glob(dir string, globs []string) (files []string, err error) { @@ -12,6 +13,10 @@ func glob(dir string, globs []string) (files []string, err error) { if !filepath.IsAbs(g) { g = filepath.Join(dir, g) } + g, err = homedir.Expand(g) + if err != nil { + return nil, err + } f, err := zglob.Glob(g) if err != nil { return nil, err diff --git a/variables.go b/variables.go index 9133a68191..d370867878 100644 --- a/variables.go +++ b/variables.go @@ -12,6 +12,7 @@ import ( "github.com/go-task/task/internal/execext" "github.com/Masterminds/sprig" + "github.com/mitchellh/go-homedir" ) var ( @@ -202,12 +203,11 @@ func (e *Executor) CompiledTask(call Call) (*Task, error) { return nil, &taskNotFoundError{call.Task} } - var r varReplacer - if vars, err := e.getVariables(call); err == nil { - r.vars = vars - } else { + vars, err := e.getVariables(call) + if err != nil { return nil, err } + r := varReplacer{vars: vars} new := Task{ Task: origTask.Task, @@ -221,6 +221,10 @@ func (e *Executor) CompiledTask(call Call) (*Task, error) { Silent: origTask.Silent, Method: r.replace(origTask.Method), } + new.Dir, err = homedir.Expand(new.Dir) + if err != nil { + return nil, err + } if e.Dir != "" && !filepath.IsAbs(new.Dir) { new.Dir = filepath.Join(e.Dir, new.Dir) } diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 0000000000..f9c841a51e --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 0000000000..d70706d5b3 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md @@ -0,0 +1,14 @@ +# 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. diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go new file mode 100644 index 0000000000..47e1f9ef8e --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -0,0 +1,137 @@ +package homedir + +import ( + "bytes" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" +) + +// DisableCache will disable caching of the home directory. Caching is enabled +// by default. +var DisableCache bool + +var homedirCache string +var cacheLock sync.RWMutex + +// Dir returns the home directory for the executing user. +// +// This uses an OS-specific method for discovering the home directory. +// An error is returned if a home directory cannot be detected. +func Dir() (string, error) { + if !DisableCache { + cacheLock.RLock() + cached := homedirCache + cacheLock.RUnlock() + if cached != "" { + return cached, nil + } + } + + cacheLock.Lock() + defer cacheLock.Unlock() + + var result string + var err error + if runtime.GOOS == "windows" { + result, err = dirWindows() + } else { + // Unix-like system, so just assume Unix + result, err = dirUnix() + } + + if err != nil { + return "", err + } + homedirCache = result + return result, nil +} + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func Expand(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := Dir() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +func dirUnix() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + // If that fails, try getent + var stdout bytes.Buffer + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + + // If all else fails, try the shell + stdout.Reset() + cmd = exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil +} + +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 +}