mirror of https://github.com/stashapp/stash.git
140 lines
3.1 KiB
Go
140 lines
3.1 KiB
Go
package fsutil
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/stashapp/stash/pkg/logger"
|
|
)
|
|
|
|
// SafeMove attempts to move the file with path src to dest using os.Rename. If this fails, then it copies src to dest, then deletes src.
|
|
func SafeMove(src, dst string) error {
|
|
err := os.Rename(src, dst)
|
|
|
|
if err != nil {
|
|
in, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer in.Close()
|
|
|
|
out, err := os.Create(dst)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, in)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = out.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = os.Remove(src)
|
|
if err != nil {
|
|
logger.Errorf("error removing old file %s during SafeMove: %v", src, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MatchExtension returns true if the extension of the provided path
|
|
// matches any of the provided extensions.
|
|
func MatchExtension(path string, extensions []string) bool {
|
|
ext := filepath.Ext(path)
|
|
for _, e := range extensions {
|
|
if strings.EqualFold(ext, "."+e) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// FindInPaths returns the path to baseName in the first path where it exists from paths.
|
|
func FindInPaths(paths []string, baseName string) string {
|
|
for _, p := range paths {
|
|
filePath := filepath.Join(p, baseName)
|
|
if exists, _ := FileExists(filePath); exists {
|
|
return filePath
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// FileExists returns true if the given path exists and is a file.
|
|
// This function returns false and the error encountered if the call to os.Stat fails.
|
|
func FileExists(path string) (bool, error) {
|
|
info, err := os.Stat(path)
|
|
if err == nil {
|
|
return !info.IsDir(), nil
|
|
}
|
|
return false, err
|
|
}
|
|
|
|
// WriteFile writes file to path creating parent directories if needed
|
|
func WriteFile(path string, file []byte) error {
|
|
pathErr := EnsureDirAll(filepath.Dir(path))
|
|
if pathErr != nil {
|
|
return fmt.Errorf("cannot ensure path exists: %w", pathErr)
|
|
}
|
|
|
|
return os.WriteFile(path, file, 0755)
|
|
}
|
|
|
|
// GetNameFromPath returns the name of a file from its path
|
|
// if stripExtension is true the extension is omitted from the name
|
|
func GetNameFromPath(path string, stripExtension bool) string {
|
|
fn := filepath.Base(path)
|
|
if stripExtension {
|
|
ext := filepath.Ext(fn)
|
|
fn = strings.TrimSuffix(fn, ext)
|
|
}
|
|
return fn
|
|
}
|
|
|
|
// Touch creates an empty file at the given path if it doesn't already exist
|
|
func Touch(path string) error {
|
|
var _, err = os.Stat(path)
|
|
if os.IsNotExist(err) {
|
|
var file, err = os.Create(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
replaceCharsRE = regexp.MustCompile(`[&=\\/:*"?_ ]`)
|
|
removeCharsRE = regexp.MustCompile(`[^[:alnum:]-.]`)
|
|
multiHyphenRE = regexp.MustCompile(`\-+`)
|
|
)
|
|
|
|
// SanitiseBasename returns a file basename removing any characters that are illegal or problematic to use in the filesystem.
|
|
func SanitiseBasename(v string) string {
|
|
v = strings.TrimSpace(v)
|
|
|
|
// replace illegal filename characters with -
|
|
v = replaceCharsRE.ReplaceAllString(v, "-")
|
|
|
|
// remove other characters
|
|
v = removeCharsRE.ReplaceAllString(v, "")
|
|
|
|
// remove multiple hyphens
|
|
v = multiHyphenRE.ReplaceAllString(v, "-")
|
|
|
|
return strings.TrimSpace(v)
|
|
}
|