backup: support specifying volume instead of path on Windows

"C:" (volume name) versus "C:\" (path)
This commit is contained in:
Michael Eischer
2024-08-30 11:25:51 +02:00
parent a0f2dfbc19
commit 4fcedb4bae
3 changed files with 85 additions and 1 deletions

View File

@@ -715,7 +715,12 @@ func resolveRelativeTargets(filesys fs.FS, targets []string) ([]string, error) {
debug.Log("targets before resolving: %v", targets)
result := make([]string, 0, len(targets))
for _, target := range targets {
target = filesys.Clean(target)
if target != "" && filesys.VolumeName(target) == target {
// special case to allow users to also specify a volume name "C:" instead of a path "C:\"
target = target + filesys.Separator()
} else {
target = filesys.Clean(target)
}
pc, _ := pathComponents(filesys, target, false)
if len(pc) > 0 {
result = append(result, target)

View File

@@ -1448,6 +1448,66 @@ func TestArchiverSnapshot(t *testing.T) {
}
}
func TestResolveRelativeTargetsSpecial(t *testing.T) {
var tests = []struct {
name string
targets []string
expected []string
win bool
}{
{
name: "basic relative path",
targets: []string{filepath.FromSlash("some/path")},
expected: []string{filepath.FromSlash("some/path")},
},
{
name: "partial relative path",
targets: []string{filepath.FromSlash("../some/path")},
expected: []string{filepath.FromSlash("../some/path")},
},
{
name: "basic absolute path",
targets: []string{filepath.FromSlash("/some/path")},
expected: []string{filepath.FromSlash("/some/path")},
},
{
name: "volume name",
targets: []string{"C:"},
expected: []string{"C:\\"},
win: true,
},
{
name: "volume root path",
targets: []string{"C:\\"},
expected: []string{"C:\\"},
win: true,
},
{
name: "UNC path",
targets: []string{"\\\\server\\volume"},
expected: []string{"\\\\server\\volume\\"},
win: true,
},
{
name: "UNC path with trailing slash",
targets: []string{"\\\\server\\volume\\"},
expected: []string{"\\\\server\\volume\\"},
win: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.win && runtime.GOOS != "windows" {
t.Skip("skip test on unix")
}
targets, err := resolveRelativeTargets(&fs.Local{}, test.targets)
rtest.OK(t, err)
rtest.Equals(t, test.expected, targets)
})
}
}
func TestArchiverSnapshotSelect(t *testing.T) {
var tests = []struct {
name string