Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion commands_display.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func displayResticHelp(output io.Writer, configuration *config.Config, flags com
}
}

if restic, err := filesearch.FindResticBinary(resticBinary); err == nil {
if restic, err := filesearch.NewFinder().FindResticBinary(resticBinary); err == nil {
buf := bytes.Buffer{}
cmd := shell.NewCommand(restic, []string{"help", command})
cmd.Stdout = &buf
Expand Down
2 changes: 1 addition & 1 deletion complete.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (c *Completer) listProfileNames() (list []string) {
format = formatFlag.Value.String()
}

if file, err := filesearch.FindConfigurationFile(filename); err == nil {
if file, err := filesearch.NewFinder().FindConfigurationFile(filename); err == nil {
if conf, err := config.LoadFile(file, format); err == nil {
list = append(list, conf.GetProfileNames()...)
for name := range conf.GetProfileGroups() {
Expand Down
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func LoadFile(configFile, format string) (config *Config, err error) {

// Load includes (if any).
var includes []string
if includes, err = filesearch.FindConfigurationIncludes(configFile, config.getIncludes()); err == nil {
if includes, err = filesearch.NewFinder().FindConfigurationIncludes(configFile, config.getIncludes()); err == nil {
for _, include := range includes {
format := formatFromExtension(include)

Expand Down
52 changes: 27 additions & 25 deletions filesearch/filesearch.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package filesearch

import (
"errors"
"fmt"
iofs "io/fs"
"os"
"os/exec"
"path/filepath"
Expand All @@ -12,20 +10,20 @@ import (

"github.com/adrg/xdg"
"github.com/creativeprojects/clog"
"github.com/creativeprojects/resticprofile/constants"
"github.com/creativeprojects/resticprofile/platform"
"github.com/spf13/afero"
)

var (
AppName = "resticprofile"

// configurationExtensions list the possible extensions for the config file
configurationExtensions = []string{
"conf",
"yaml",
"toml",
"json",
"hcl",
"yml",
}

defaultConfigurationLocationsUnix = []string{
Expand All @@ -41,7 +39,7 @@ var (
}

addConfigurationLocationsDarwin = []string{
".config/" + AppName + "/",
".config/" + constants.ApplicationName + "/",
}

defaultConfigurationLocationsWindows = []string{
Expand Down Expand Up @@ -69,27 +67,31 @@ var (
}
)

var fs afero.Fs // we could probably change the implementation to use fs.FS instead
type Finder struct {
fs afero.Fs
}

func init() {
fs = afero.NewOsFs()
func NewFinder() Finder {
return Finder{
fs: afero.NewOsFs(), // external packages will always need files from the OS
}
}

// FindConfigurationFile returns the path of the configuration file
// If the file doesn't have an extension, it will search for all possible extensions
func FindConfigurationFile(configFile string) (string, error) {
func (f Finder) FindConfigurationFile(configFile string) (string, error) {
found := ""
extension := filepath.Ext(configFile)
displayFile := ""
if extension != "" {
displayFile = fmt.Sprintf("'%s'", configFile)
// Search only once through the paths
found = findConfigurationFileWithExtension(configFile)
found = f.findConfigurationFileWithExtension(configFile)
} else {
displayFile = fmt.Sprintf("'%s' with extensions %s", configFile, strings.Join(configurationExtensions, ", "))
// Search all extensions one by one
for _, ext := range configurationExtensions {
found = findConfigurationFileWithExtension(configFile + "." + ext)
found = f.findConfigurationFileWithExtension(configFile + "." + ext)
if found != "" {
break
}
Expand All @@ -105,9 +107,9 @@ func FindConfigurationFile(configFile string) (string, error) {
strings.Join(getSearchConfigurationLocations(), ", "))
}

func findConfigurationFileWithExtension(configFile string) string {
func (f Finder) findConfigurationFileWithExtension(configFile string) string {
// simple case: try current folder (or rooted path)
if fileExists(configFile) {
if fileExists(f.fs, configFile) {
return configFile
}

Expand All @@ -116,7 +118,7 @@ func findConfigurationFileWithExtension(configFile string) string {

for _, configPath := range paths {
filename := filepath.Join(configPath, configFile)
if fileExists(filename) {
if fileExists(f.fs, filename) {
return filename
}
}
Expand All @@ -125,7 +127,7 @@ func findConfigurationFileWithExtension(configFile string) string {
}

// FindConfigurationIncludes finds includes (glob patterns) relative to the configuration file.
func FindConfigurationIncludes(configFile string, includes []string) ([]string, error) {
func (f Finder) FindConfigurationIncludes(configFile string, includes []string) ([]string, error) {
if !filepath.IsAbs(configFile) {
var err error
if configFile, err = filepath.Abs(configFile); err != nil {
Expand All @@ -150,10 +152,10 @@ func FindConfigurationIncludes(configFile string, includes []string) ([]string,
include = filepath.Join(base, include)
}

if fileExists(include) {
if fileExists(f.fs, include) {
addFile(include)
} else {
if matches, err := afero.Glob(fs, include); err == nil && matches != nil {
if matches, err := afero.Glob(f.fs, include); err == nil && matches != nil {
sort.Strings(matches)
for _, match := range matches {
addFile(match)
Expand All @@ -170,14 +172,14 @@ func FindConfigurationIncludes(configFile string, includes []string) ([]string,
}

// FindResticBinary returns the path of restic executable
func FindResticBinary(configLocation string) (string, error) {
func (f Finder) FindResticBinary(configLocation string) (string, error) {
if configLocation != "" {
// Start by the location from the configuration
filename, err := ShellExpand(configLocation)
if err != nil {
clog.Warning(err)
}
if filename != "" && fileExists(filename) {
if filename != "" && fileExists(f.fs, filename) {
return filename, nil
}
clog.Warningf("cannot find or read the restic binary specified in the configuration: %q", configLocation)
Expand All @@ -187,7 +189,7 @@ func FindResticBinary(configLocation string) (string, error) {

for _, configPath := range paths {
filename := filepath.Join(configPath, binaryFile)
if fileExists(filename) {
if fileExists(f.fs, filename) {
return filename, nil
}
}
Expand Down Expand Up @@ -219,9 +221,9 @@ func ShellExpand(filename string) (string, error) {
func getSearchConfigurationLocations() []string {
home, _ := os.UserHomeDir()

locations := []string{filepath.Join(xdg.ConfigHome, AppName)}
locations := []string{filepath.Join(xdg.ConfigHome, constants.ApplicationName)}
for _, configDir := range xdg.ConfigDirs {
locations = append(locations, filepath.Join(configDir, AppName))
locations = append(locations, filepath.Join(configDir, constants.ApplicationName))
}

if platform.IsWindows() {
Expand Down Expand Up @@ -268,9 +270,9 @@ func getResticBinaryName() string {
return resticBinaryUnix
}

func fileExists(filename string) bool {
_, err := fs.Stat(filename)
return err == nil || errors.Is(err, iofs.ErrExist)
func fileExists(fs afero.Fs, filename string) bool {
info, err := fs.Stat(filename)
return err == nil && !info.IsDir()
}
Comment thread
creativeprojects marked this conversation as resolved.

func addRootToRelativePaths(home string, paths []string) []string {
Expand Down
Loading