stash/pkg/fsutil/dir.go

123 lines
3.1 KiB
Go

package fsutil
import (
"fmt"
"io/fs"
"os"
"os/user"
"path/filepath"
"strings"
)
// DirExists returns true if the given path exists and is a directory
func DirExists(path string) (bool, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return false, fs.ErrNotExist
}
if !fileInfo.IsDir() {
return false, fmt.Errorf("path is not a directory <%s>", path)
}
return true, nil
}
// IsPathInDir returns true if pathToCheck is within dir.
func IsPathInDir(dir, pathToCheck string) bool {
rel, err := filepath.Rel(dir, pathToCheck)
if err == nil {
if !strings.HasPrefix(rel, "..") {
return true
}
}
return false
}
// IsPathInDirs returns true if pathToCheck is within anys of the paths in dirs.
func IsPathInDirs(dirs []string, pathToCheck string) bool {
for _, dir := range dirs {
if IsPathInDir(dir, pathToCheck) {
return true
}
}
return false
}
// GetWorkingDirectory returns the current working directory.
func GetWorkingDirectory() string {
ret, err := os.Getwd()
if err != nil {
// if we can't get cwd for whatever reason, just return "."
ret = "."
}
return ret
}
// GetHomeDirectory returns the path of the user's home directory. ~ on Unix and C:\Users\UserName on Windows
func GetHomeDirectory() string {
currentUser, err := user.Current()
if err != nil {
panic(err)
}
return currentUser.HomeDir
}
// EnsureDir will create a directory at the given path if it doesn't already exist
func EnsureDir(path string) error {
exists, err := DirExists(path)
if !exists {
err = os.Mkdir(path, 0755)
return err
}
return err
}
// EnsureDirAll will create a directory at the given path along with any necessary parents if they don't already exist
func EnsureDirAll(path string) error {
return os.MkdirAll(path, 0755)
}
// RemoveDir removes the given dir (if it exists) along with all of its contents
func RemoveDir(path string) error {
return os.RemoveAll(path)
}
// EmptyDir will recursively remove the contents of a directory at the given path
func EmptyDir(path string) error {
d, err := os.Open(path)
if err != nil {
return err
}
defer d.Close()
names, err := d.Readdirnames(-1)
if err != nil {
return err
}
for _, name := range names {
err = os.RemoveAll(filepath.Join(path, name))
if err != nil {
return err
}
}
return nil
}
// GetIntraDir returns a string that can be added to filepath.Join to implement directory depth, "" on error
// eg given a pattern of 0af63ce3c99162e9df23a997f62621c5 and a depth of 2 length of 3
// returns 0af/63c or 0af\63c ( dependin on os) that can be later used like this filepath.Join(directory, intradir, basename)
func GetIntraDir(pattern string, depth, length int) string {
if depth < 1 || length < 1 || (depth*length > len(pattern)) {
return ""
}
intraDir := pattern[0:length] // depth 1 , get length number of characters from pattern
for i := 1; i < depth; i++ { // for every extra depth: move to the right of the pattern length positions, get length number of chars
intraDir = filepath.Join(intraDir, pattern[length*i:length*(i+1)]) // adding each time to intradir the extra characters with a filepath join
}
return intraDir
}