Skip to content

Commit

Permalink
use shell to resolve special paths with ~
Browse files Browse the repository at this point in the history
  • Loading branch information
creativeprojects committed Jun 21, 2021
1 parent 061d3f8 commit 4686dd2
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 3 deletions.
1 change: 1 addition & 0 deletions examples/dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ global:
default-command: snapshots
initialize: false
priority: low
restic-binary: ~/fake_restic

groups:
full-backup:
Expand Down
28 changes: 25 additions & 3 deletions filesearch/filesearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/adrg/xdg"
"github.com/creativeprojects/clog"
)

var (
Expand Down Expand Up @@ -126,9 +127,15 @@ func findConfigurationFileWithExtension(configFile string) string {

// FindResticBinary returns the path of restic executable
func FindResticBinary(configLocation string) (string, error) {
// Start by the location from the configuration
if configLocation != "" && fileExists(configLocation) {
return configLocation, nil
if configLocation != "" {
// Start by the location from the configuration
configLocation, err := ShellExpand(configLocation)
if err != nil {
clog.Warning(err)
}
if configLocation != "" && fileExists(configLocation) {
return configLocation, nil
}
}
paths := getDefaultBinaryLocations()
binaryFile := getResticBinary()
Expand All @@ -149,6 +156,21 @@ func FindResticBinary(configLocation string) (string, error) {
return filename, nil
}

// ShellExpand uses the shell to expand variables and ~ from a filename.
// On Windows the function simply returns the filename unchanged
func ShellExpand(filename string) (string, error) {
if runtime.GOOS == "windows" {
return filename, nil
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("echo %s", strings.ReplaceAll(filename, " ", `\ `)))
result, err := cmd.Output()
if err != nil {
return filename, err
}
filename = strings.TrimSuffix(string(result), "\n")
return filename, nil
}

func getDefaultConfigurationLocations() []string {
if runtime.GOOS == "windows" {
return defaultConfigurationLocationsWindows
Expand Down
54 changes: 54 additions & 0 deletions filesearch/filesearch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package filesearch

import (
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
"testing"

Expand Down Expand Up @@ -223,3 +225,55 @@ func TestFindResticBinary(t *testing.T) {
assert.Error(t, err)
}
}

func TestFindResticBinaryWithTilde(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("not supported on Windows")
return
}
home, err := os.UserHomeDir()
require.NoError(t, err)

tempFile, err := os.CreateTemp(home, "TestFindResticBinaryWithTilde")
require.NoError(t, err)
tempFile.Close()
defer func() {
os.Remove(tempFile.Name())
}()

search := filepath.Join("~", filepath.Base(tempFile.Name()))
binary, err := FindResticBinary(search)
require.NoError(t, err)
assert.Equalf(t, tempFile.Name(), binary, "cannot find %q", search)
}

func TestShellExpand(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("not supported on Windows")
return
}
home, err := os.UserHomeDir()
require.NoError(t, err)

user, err := user.Current()
require.NoError(t, err)

testData := []struct {
source string
expected string
}{
{"/", "/"},
{"~", home},
{"$HOME", home},
{"~" + user.Username, user.HomeDir},
{"1 2", "1 2"},
}

for _, testItem := range testData {
t.Run(testItem.source, func(t *testing.T) {
result, err := ShellExpand(testItem.source)
require.NoError(t, err)
assert.Equal(t, testItem.expected, result)
})
}
}

0 comments on commit 4686dd2

Please sign in to comment.