mirror of
https://github.com/restic/restic.git
synced 2024-12-22 15:57:07 +00:00
backup: store but warn if extended metadata for item is incomplete
Files were not included in the backup if the extended metadata for the file could not be read. This is rather drastic. Instead settle on returning a warning but still including the file in the backup.
This commit is contained in:
parent
d407abb50f
commit
73c9780321
3 changed files with 43 additions and 1 deletions
15
changelog/unreleased/pull-4977
Normal file
15
changelog/unreleased/pull-4977
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Change: let `backup` store files with incomplete metadata
|
||||||
|
|
||||||
|
If restic failed to read the extended metadata for a file or folder while
|
||||||
|
creating a backup, then the file or folder was not included in the resulting
|
||||||
|
snapshot. Instead, only a warning message was printed along with exiting
|
||||||
|
with exit code 3.
|
||||||
|
|
||||||
|
Now, restic also includes items for which the extended metadata could not
|
||||||
|
be read in a snapshot. The warning message has been changed to read
|
||||||
|
```
|
||||||
|
incomplete metadata for /path/to/file: details on error
|
||||||
|
```
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/4953
|
||||||
|
https://github.com/restic/restic/pull/4977
|
|
@ -263,7 +263,8 @@ func (arch *Archiver) nodeFromFileInfo(snPath, filename string, fi os.FileInfo,
|
||||||
// overwrite name to match that within the snapshot
|
// overwrite name to match that within the snapshot
|
||||||
node.Name = path.Base(snPath)
|
node.Name = path.Base(snPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return node, fmt.Errorf("nodeFromFileInfo %v: %w", filename, err)
|
err = fmt.Errorf("incomplete metadata for %v: %w", filename, err)
|
||||||
|
return node, arch.error(filename, err)
|
||||||
}
|
}
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package archiver
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -2338,3 +2339,28 @@ func TestRacyFileSwap(t *testing.T) {
|
||||||
t.Errorf("Save() excluded the node, that's unexpected")
|
t.Errorf("Save() excluded the node, that's unexpected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMetadataBackupErrorFiltering(t *testing.T) {
|
||||||
|
tempdir := t.TempDir()
|
||||||
|
repo := repository.TestRepository(t)
|
||||||
|
|
||||||
|
filename := filepath.Join(tempdir, "file")
|
||||||
|
rtest.OK(t, os.WriteFile(filename, []byte("example"), 0o600))
|
||||||
|
fi, err := os.Stat(filename)
|
||||||
|
rtest.OK(t, err)
|
||||||
|
|
||||||
|
arch := New(repo, fs.Local{}, Options{})
|
||||||
|
|
||||||
|
var filteredErr error
|
||||||
|
replacementErr := fmt.Errorf("replacement")
|
||||||
|
arch.Error = func(item string, err error) error {
|
||||||
|
filteredErr = err
|
||||||
|
return replacementErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that errors from reading extended metadata are properly filtered
|
||||||
|
node, err := arch.nodeFromFileInfo("file", filename+"invalid", fi, false)
|
||||||
|
rtest.Assert(t, node != nil, "node is missing")
|
||||||
|
rtest.Assert(t, err == replacementErr, "expected %v got %v", replacementErr, err)
|
||||||
|
rtest.Assert(t, filteredErr != nil, "missing inner error")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue