restore: do not delete target if it is a file

This is implicitly achieved by creating the target directory as the
first step, which will fail if a file already exist in its place.
This commit is contained in:
Michael Eischer 2024-07-10 22:08:49 +02:00
parent 36a2857df6
commit 8731667156
2 changed files with 30 additions and 0 deletions

View File

@ -347,6 +347,14 @@ func (res *Restorer) RestoreTo(ctx context.Context, dst string) error {
}
}
if !res.opts.DryRun {
// ensure that the target directory exists and is actually a directory
// Using ensureDir is too aggressive here as it also removes unexpected files
if err := fs.MkdirAll(dst, 0700); err != nil {
return fmt.Errorf("cannot create target directory: %w", err)
}
}
idx := NewHardlinkIndex[string]()
filerestorer := newFileRestorer(dst, res.repo.LoadBlobsFromPack, res.repo.LookupBlob,
res.repo.Connections(), res.opts.Sparse, res.opts.Delete, res.opts.Progress)

View File

@ -1372,3 +1372,25 @@ func TestRestoreDelete(t *testing.T) {
})
}
}
func TestRestoreToFile(t *testing.T) {
snapshot := Snapshot{
Nodes: map[string]Node{
"foo": File{Data: "content: foo\n"},
},
}
repo := repository.TestRepository(t)
tempdir := filepath.Join(rtest.TempDir(t), "target")
// create a file in the place of the target directory
rtest.OK(t, os.WriteFile(tempdir, []byte{}, 0o700))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sn, _ := saveSnapshot(t, repo, snapshot, noopGetGenericAttributes)
res := NewRestorer(repo, sn, Options{})
err := res.RestoreTo(ctx, tempdir)
rtest.Assert(t, strings.Contains(err.Error(), "cannot create target directory"), "unexpected error %v", err)
}