1
0
mirror of https://github.com/restic/restic.git synced 2024-07-27 12:37:40 +02:00

restore: use case insensitive file name comparison on windows

This commit is contained in:
Michael Eischer 2024-06-29 19:54:12 +02:00
parent 013a6156bd
commit 168fc09d5f
4 changed files with 59 additions and 2 deletions

View File

@ -480,11 +480,11 @@ func (res *Restorer) removeUnexpectedFiles(target, location string, expectedFile
keep := map[string]struct{}{}
for _, name := range expectedFilenames {
keep[name] = struct{}{}
keep[toComparableFilename(name)] = struct{}{}
}
for _, entry := range entries {
if _, ok := keep[entry]; ok {
if _, ok := keep[toComparableFilename(entry)]; ok {
continue
}

View File

@ -0,0 +1,10 @@
//go:build !windows
// +build !windows
package restorer
// toComparableFilename returns a filename suitable for equality checks. On Windows, it returns the
// uppercase version of the string. On all other systems, it returns the unmodified filename.
func toComparableFilename(path string) string {
return path
}

View File

@ -0,0 +1,13 @@
//go:build windows
// +build windows
package restorer
import "strings"
// toComparableFilename returns a filename suitable for equality checks. On Windows, it returns the
// uppercase version of the string. On all other systems, it returns the unmodified filename.
func toComparableFilename(path string) string {
// apparently NTFS internally uppercases filenames for comparision
return strings.ToUpper(path)
}

View File

@ -9,6 +9,7 @@ import (
"math"
"os"
"path"
"path/filepath"
"syscall"
"testing"
"time"
@ -539,3 +540,36 @@ func TestDirAttributeCombinationsOverwrite(t *testing.T) {
}
}
}
func TestRestoreDeleteCaseInsensitive(t *testing.T) {
repo := repository.TestRepository(t)
tempdir := rtest.TempDir(t)
sn, _ := saveSnapshot(t, repo, Snapshot{
Nodes: map[string]Node{
"anotherfile": File{Data: "content: file\n"},
},
}, noopGetGenericAttributes)
// should delete files that no longer exist in the snapshot
deleteSn, _ := saveSnapshot(t, repo, Snapshot{
Nodes: map[string]Node{
"AnotherfilE": File{Data: "content: file\n"},
},
}, noopGetGenericAttributes)
res := NewRestorer(repo, sn, Options{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := res.RestoreTo(ctx, tempdir)
rtest.OK(t, err)
res = NewRestorer(repo, deleteSn, Options{Delete: true})
err = res.RestoreTo(ctx, tempdir)
rtest.OK(t, err)
// anotherfile must still exist
_, err = os.Stat(filepath.Join(tempdir, "anotherfile"))
rtest.OK(t, err)
}