terraform/vendor/github.com/apparentlymart/go-userdirs/userdirs/dirs.go

179 lines
6.2 KiB
Go

package userdirs
import (
"os"
"path/filepath"
)
// Dirs represents a set of directory paths with different purposes.
type Dirs struct {
// ConfigDirs is a list, in preference order, of directory paths to search
// for configuration files.
//
// The list must always contain at least one element, and its first element
// is the directory where any new configuration files should be written.
//
// On some systems, ConfigDirs and DataDirs may overlap, so applications
// which scan the contents of the configuration directories should impose
// some additional filtering to distinguish configuration files from data
// files.
//
// Files placed in ConfigDirs should ideally be things that it would be
// reasonable to share among multiple systems (possibly on different
// platforms, possibly to check into a version control system, etc.
ConfigDirs []string
// DataDirs is a list, in preference order, of directory paths to search for
// data files.
//
// The list must always contain at least one element, and its first element
// is the directory where any new data files should be written.
//
// On some systems, ConfigDirs and DataDirs may overlap, so applications
// which scan the contents of the data directories should impose some
// additional filtering to distinguish data files from configuration files.
DataDirs []string
// CacheDir is the path of a single directory that can be used for temporary
// cache data.
//
// The cache is suitable only for data that the calling application could
// recreate if lost. Any file or directory under this prefix may be deleted
// at any time by other software.
//
// This directory may, on some systems, match one of the directories
// returned in ConfigDirs and/or DataDirs. For this reason applications
// must ensure that they do not misinterpret config and data files as
// cache files, and in particular should not naively purge a cache by
// emptying this directory.
CacheDir string
}
// ConfigHome returns the path for the directory where any new configuration
// files should be written.
func (d Dirs) ConfigHome() string {
return d.ConfigDirs[0]
}
// DataHome returns the path for the directory where any new configuration
// files should be written.
func (d Dirs) DataHome() string {
return d.DataDirs[0]
}
// NewConfigPath joins the given path segments to the ConfigHome to produce a
// path where a new configuration file might be written.
func (d Dirs) NewConfigPath(parts ...string) string {
return filepath.Join(d.ConfigHome(), filepath.Join(parts...))
}
// NewDataPath joins the given path segments to the DataHome to produce a
// path where a new data file might be written.
func (d Dirs) NewDataPath(parts ...string) string {
return filepath.Join(d.DataHome(), filepath.Join(parts...))
}
// CachePath joins the given path segments to the CacheHome to produce a
// path for a cache file or directory.
func (d Dirs) CachePath(parts ...string) string {
return filepath.Join(d.CacheDir, filepath.Join(parts...))
}
// ConfigSearchPaths joins the given path segments to each of the directories
// in in ConfigDirs to produce a more specific set of paths to be searched
// in preference order.
func (d Dirs) ConfigSearchPaths(parts ...string) []string {
return searchPaths(d.ConfigDirs, parts...)
}
// DataSearchPaths joins the given path segments to each of the directories
// in in ConfigDirs to produce a more specific set of paths to be searched
// in preference order.
func (d Dirs) DataSearchPaths(parts ...string) []string {
return searchPaths(d.DataDirs, parts...)
}
// FindConfigFiles scans over all of the paths in ConfigDirs and tests whether
// a file of the given name is present in each, returning a slice of full
// paths that matched.
func (d Dirs) FindConfigFiles(parts ...string) []string {
return findFiles(d.ConfigDirs, parts...)
}
// FindDataFiles scans over all of the paths in ConfigDirs and tests whether
// a file of the given name is present in each, returning a slice of full
// paths that matched.
func (d Dirs) FindDataFiles(parts ...string) []string {
return findFiles(d.DataDirs, parts...)
}
// GlobConfigFiles joins the given parts to create a glob pattern and then
// applies it relative to each of the paths in ConfigDirs, returning all
// of the matches in a single slice.
//
// The order of the result preserves the directory preference order and
// sorts multiple files within the same directory lexicographically.
//
// Remember that on some platforms the config dirs and data dirs overlap,
// so to be robust you should use distinct naming patterns for configuration
// and data files to avoid accidentally matching data files with this method.
func (d Dirs) GlobConfigFiles(parts ...string) []string {
return globFiles(d.ConfigDirs, parts...)
}
// GlobDataFiles joins the given parts to create a glob pattern and then
// applies it relative to each of the paths in DataDirs, returning all
// of the matches in a single slice.
//
// The order of the result preserves the directory preference order and
// sorts multiple files within the same directory lexicographically.
//
// Remember that on some platforms the config dirs and data dirs overlap,
// so to be robust you should use distinct naming patterns for configuration
// and data files to avoid accidentally matching configuration files with this
// method.
func (d Dirs) GlobDataFiles(parts ...string) []string {
return globFiles(d.DataDirs, parts...)
}
func searchPaths(bases []string, parts ...string) []string {
extra := filepath.Join(parts...)
ret := make([]string, len(bases))
for i, base := range bases {
ret[i] = filepath.Join(base, extra)
}
return ret
}
func findFiles(bases []string, parts ...string) []string {
extra := filepath.Join(parts...)
ret := make([]string, 0, len(bases))
for _, base := range bases {
candidate := filepath.Join(base, extra)
if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
ret = append(ret, candidate)
}
}
if len(ret) == 0 {
return nil
}
return ret
}
func globFiles(bases []string, parts ...string) []string {
extra := filepath.Join(parts...)
var ret []string
for _, base := range bases {
pattern := filepath.Join(base, extra)
found, err := filepath.Glob(pattern)
if err != nil {
continue
}
ret = append(ret, found...)
}
if len(ret) == 0 {
return nil
}
return ret
}