aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/BurntSushi/xdg/xdg.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/BurntSushi/xdg/xdg.go')
-rw-r--r--vendor/github.com/BurntSushi/xdg/xdg.go236
1 files changed, 236 insertions, 0 deletions
diff --git a/vendor/github.com/BurntSushi/xdg/xdg.go b/vendor/github.com/BurntSushi/xdg/xdg.go
new file mode 100644
index 0000000..fddceb9
--- /dev/null
+++ b/vendor/github.com/BurntSushi/xdg/xdg.go
@@ -0,0 +1,236 @@
+package xdg
+
+import (
+ "fmt"
+ "go/build"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+)
+
+// Paths determines which directories to search. The first directory
+// containing a matching file is used. Here is the order:
+//
+// Override is always checked first.
+//
+// Directories specified in the XDG spec are searched after "XDGSuffix" is
+// appended.
+//
+// For configuration files, these are:
+//
+// $XDG_CONFIG_HOME (or $HOME/.config when not set)
+// Directories in $XDG_CONFIG_DIRS (or /etc/xdg when not set)
+//
+// For data files, these are:
+//
+// $XDG_DATA_HOME (or $HOME/.local/share when not set)
+// Directories in $XDG_DATA_DIRS (or /usr/local/share:/usr/share when not set)
+//
+// For runtime files, these are:
+//
+// $XDG_RUNTIME_DIR (or /tmp when not set; implementation defined)
+//
+// Finally, the directory specified by GoImportPath is searched in all
+// source directories reported by the `go/build` package.
+type Paths struct {
+ // When non-empty, this will be the first directory searched.
+ Override string
+
+ // The suffix path appended to XDG directories.
+ // i.e., "wingo" and NOT "/home/andrew/.config/wingo"
+ XDGSuffix string
+
+ // The path in which your data files live inside your project directory.
+ // This should include your Go import path plus the directory containing
+ // files in your repo. This is used as a last resort to find files.
+ // (And it will only work if your package was installed using the GOPATH
+ // environment.)
+ //
+ // N.B. XDGSuffix is not used here,
+ // i.e., "github.com/BurntSushi/wingo/config"
+ GoImportPath string
+}
+
+// MustPanic takes the return values of ConfigFile or DataFile, reads the file
+// into a []byte, and returns the bytes.
+//
+// If the operation does not succeed, it panics.
+func (ps Paths) MustPanic(fpath string, err error) []byte {
+ if err != nil {
+ panic(err)
+ }
+ bs, err := ioutil.ReadFile(fpath)
+ if err != nil {
+ panic(err)
+ }
+ return bs
+}
+
+// MustError is like MustPanic, but instead of panicing when something goes
+// wrong, it prints the error to stderr and calls os.Exit(1).
+func (ps Paths) MustError(fpath string, err error) []byte {
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Could not read %s: %s", fpath, err)
+ os.Exit(1)
+ }
+ bs, err := ioutil.ReadFile(fpath)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Could not read %s: %s", fpath, err)
+ os.Exit(1)
+ }
+ return bs
+}
+
+// ConfigFile returns a file path containing the configuration file
+// specified. If one cannot be found, an error will be returned which
+// contains a list of all file paths searched.
+func (ps Paths) ConfigFile(name string) (string, error) {
+ home := os.Getenv("HOME")
+ xdgHome := os.Getenv("XDG_CONFIG_HOME")
+ xdgDirs := os.Getenv("XDG_CONFIG_DIRS")
+
+ // We're going to accumulate a list of directories for places to inspect
+ // for configuration files. Basically, this includes following the
+ // xdg basedir spec for the XDG_CONFIG_HOME and XDG_CONFIG_DIRS environment
+ // variables.
+ try := make([]string, 0)
+
+ // from override
+ if len(ps.Override) > 0 {
+ try = append(try, ps.Override)
+ }
+
+ // XDG_CONFIG_HOME
+ if len(xdgHome) > 0 && strings.HasPrefix(xdgHome, "/") {
+ try = append(try, path.Join(xdgHome, ps.XDGSuffix))
+ } else if len(home) > 0 {
+ try = append(try, path.Join(home, ".config", ps.XDGSuffix))
+ }
+
+ // XDG_CONFIG_DIRS
+ if len(xdgDirs) > 0 {
+ for _, p := range strings.Split(xdgDirs, ":") {
+ // XDG basedir spec does not allow relative paths
+ if !strings.HasPrefix(p, "/") {
+ continue
+ }
+ try = append(try, path.Join(p, ps.XDGSuffix))
+ }
+ } else {
+ try = append(try, path.Join("/", "etc", "xdg", ps.XDGSuffix))
+ }
+
+ // Add directories from GOPATH. Last resort.
+ for _, dir := range build.Default.SrcDirs() {
+ d := path.Join(dir, ps.GoImportPath)
+ try = append(try, d)
+ }
+
+ return searchPaths(try, name)
+}
+
+// DataFile returns a file path containing the data file
+// specified. If one cannot be found, an error will be returned which
+// contains a list of all file paths searched.
+func (ps Paths) DataFile(name string) (string, error) {
+ home := os.Getenv("HOME")
+ xdgHome := os.Getenv("XDG_DATA_HOME")
+ xdgDirs := os.Getenv("XDG_DATA_DIRS")
+
+ // We're going to accumulate a list of directories for places to inspect
+ // for data files. Basically, this includes following the
+ // xdg basedir spec for the XDG_DATA_HOME and XDG_DATA_DIRS environment
+ // variables.
+ try := make([]string, 0)
+
+ // from override
+ if len(ps.Override) > 0 {
+ try = append(try, ps.Override)
+ }
+
+ // XDG_DATA_HOME
+ if len(xdgHome) > 0 && strings.HasPrefix(xdgHome, "/") {
+ try = append(try, path.Join(xdgHome, ps.XDGSuffix))
+ } else if len(home) > 0 {
+ try = append(try, path.Join(home, ".local", "share", ps.XDGSuffix))
+ }
+
+ // XDG_CONFIG_DIRS
+ if len(xdgDirs) > 0 {
+ for _, p := range strings.Split(xdgDirs, ":") {
+ // XDG basedir spec does not allow relative paths
+ if !strings.HasPrefix(p, "/") {
+ continue
+ }
+ try = append(try, path.Join(p, ps.XDGSuffix))
+ }
+ } else {
+ try = append(try, path.Join("/", "usr", "local", "share", ps.XDGSuffix))
+ try = append(try, path.Join("/", "usr", "share", ps.XDGSuffix))
+ }
+
+ // Add directories from GOPATH. Last resort.
+ for _, dir := range build.Default.SrcDirs() {
+ d := path.Join(dir, ps.GoImportPath)
+ try = append(try, d)
+ }
+
+ return searchPaths(try, name)
+}
+
+// RuntimeFile returns a file path containing the runtime file
+// specified. If one cannot be found, an error will be returned which
+// contains a list of all file paths searched.
+func (ps Paths) RuntimeFile(name string) (string, error) {
+ xdgRuntime := os.Getenv("XDG_RUNTIME_DIR")
+
+ try := make([]string, 0)
+
+ // from override
+ if len(ps.Override) > 0 {
+ try = append(try, ps.Override)
+ }
+
+ // XDG_RUNTIME_DIR
+ if len(xdgRuntime) > 0 {
+ try = append(try, path.Join(xdgRuntime, ps.XDGSuffix))
+ } else {
+ try = append(try, path.Join(os.TempDir(), ps.XDGSuffix))
+ }
+
+ // Add directories from GOPATH. Last resort.
+ for _, dir := range build.Default.SrcDirs() {
+ d := path.Join(dir, ps.GoImportPath)
+ try = append(try, d)
+ }
+
+ return searchPaths(try, name)
+}
+
+func searchPaths(paths []string, suffix string) (string, error) {
+ // Now use the first one and keep track of the ones we've tried.
+ tried := make([]string, 0, len(paths))
+ for _, dir := range paths {
+ if len(dir) == 0 {
+ continue
+ }
+
+ fpath := path.Join(dir, suffix)
+ if exists(fpath) {
+ return fpath, nil
+ } else {
+ tried = append(tried, fpath)
+ }
+ }
+
+ // Show the user where we've looked for config files...
+ triedStr := strings.Join(tried, ", ")
+ return "", fmt.Errorf("Could not find a '%s' file. Tried "+
+ "the following paths: %s", suffix, triedStr)
+}
+
+func exists(p string) bool {
+ _, err := os.Stat(p)
+ return err == nil || os.IsExist(err)
+}