forked from TrueCloudLab/restic
Add more error checks
This commit is contained in:
parent
cbd88c457a
commit
200f09522d
11 changed files with 63 additions and 24 deletions
|
@ -32,7 +32,7 @@ func TestCollectTargets(t *testing.T) {
|
||||||
// All mentioned files must exist for collectTargets.
|
// All mentioned files must exist for collectTargets.
|
||||||
f, err := os.Create(filepath.Join(dir, filename))
|
f, err := os.Create(filepath.Join(dir, filename))
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
f.Close()
|
rtest.OK(t, f.Close())
|
||||||
|
|
||||||
expect = append(expect, f.Name())
|
expect = append(expect, f.Name())
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func TestCollectTargets(t *testing.T) {
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
// Empty lines should be ignored. A line starting with '#' is a comment.
|
// Empty lines should be ignored. A line starting with '#' is a comment.
|
||||||
fmt.Fprintf(f1, "\n%s*\n # here's a comment\n", f1.Name())
|
fmt.Fprintf(f1, "\n%s*\n # here's a comment\n", f1.Name())
|
||||||
f1.Close()
|
rtest.OK(t, f1.Close())
|
||||||
|
|
||||||
f2, err := os.Create(filepath.Join(dir, "fromfile-verbatim"))
|
f2, err := os.Create(filepath.Join(dir, "fromfile-verbatim"))
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
@ -49,7 +49,7 @@ func TestCollectTargets(t *testing.T) {
|
||||||
// Empty lines should be ignored. CR+LF is allowed.
|
// Empty lines should be ignored. CR+LF is allowed.
|
||||||
fmt.Fprintf(f2, "%s\r\n\n", filepath.Join(dir, filename))
|
fmt.Fprintf(f2, "%s\r\n\n", filepath.Join(dir, filename))
|
||||||
}
|
}
|
||||||
f2.Close()
|
rtest.OK(t, f2.Close())
|
||||||
|
|
||||||
f3, err := os.Create(filepath.Join(dir, "fromfile-raw"))
|
f3, err := os.Create(filepath.Join(dir, "fromfile-raw"))
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
@ -57,7 +57,7 @@ func TestCollectTargets(t *testing.T) {
|
||||||
fmt.Fprintf(f3, "%s\x00", filepath.Join(dir, filename))
|
fmt.Fprintf(f3, "%s\x00", filepath.Join(dir, filename))
|
||||||
}
|
}
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
f3.Close()
|
rtest.OK(t, f3.Close())
|
||||||
|
|
||||||
opts := BackupOptions{
|
opts := BackupOptions{
|
||||||
FilesFrom: []string{f1.Name()},
|
FilesFrom: []string{f1.Name()},
|
||||||
|
|
|
@ -148,7 +148,7 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.Write(gopts.stdout)
|
_ = tab.Write(gopts.stdout)
|
||||||
Printf("%d cache dirs in %s\n", len(dirs), cachedir)
|
Printf("%d cache dirs in %s\n", len(dirs), cachedir)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -563,7 +563,10 @@ func runFind(opts FindOptions, gopts GlobalOptions, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.PackID {
|
if opts.PackID {
|
||||||
f.packsToBlobs(ctx, []string{f.pat.pattern[0]}) // TODO: support multiple packs
|
err := f.packsToBlobs(ctx, []string{f.pat.pattern[0]}) // TODO: support multiple packs
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for sn := range FindFilteredSnapshots(ctx, repo, opts.Hosts, opts.Tags, opts.Paths, opts.Snapshots) {
|
for sn := range FindFilteredSnapshots(ctx, repo, opts.Hosts, opts.Tags, opts.Paths, opts.Snapshots) {
|
||||||
|
|
|
@ -159,16 +159,17 @@ func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
|
||||||
enc := json.NewEncoder(gopts.stdout)
|
enc := json.NewEncoder(gopts.stdout)
|
||||||
|
|
||||||
printSnapshot = func(sn *restic.Snapshot) {
|
printSnapshot = func(sn *restic.Snapshot) {
|
||||||
enc.Encode(lsSnapshot{
|
err = enc.Encode(lsSnapshot{
|
||||||
Snapshot: sn,
|
Snapshot: sn,
|
||||||
ID: sn.ID(),
|
ID: sn.ID(),
|
||||||
ShortID: sn.ID().Str(),
|
ShortID: sn.ID().Str(),
|
||||||
StructType: "snapshot",
|
StructType: "snapshot",
|
||||||
})
|
})
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
printNode = func(path string, node *restic.Node) {
|
printNode = func(path string, node *restic.Node) {
|
||||||
enc.Encode(lsNode{
|
err = enc.Encode(lsNode{
|
||||||
Name: node.Name,
|
Name: node.Name,
|
||||||
Type: node.Type,
|
Type: node.Type,
|
||||||
Path: path,
|
Path: path,
|
||||||
|
@ -181,6 +182,7 @@ func runLs(opts LsOptions, gopts GlobalOptions, args []string) error {
|
||||||
ChangeTime: node.ChangeTime,
|
ChangeTime: node.ChangeTime,
|
||||||
StructType: "node",
|
StructType: "node",
|
||||||
})
|
})
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printSnapshot = func(sn *restic.Snapshot) {
|
printSnapshot = func(sn *restic.Snapshot) {
|
||||||
|
|
|
@ -117,7 +117,10 @@ func runRecover(gopts GlobalOptions) error {
|
||||||
ModTime: time.Now(),
|
ModTime: time.Now(),
|
||||||
ChangeTime: time.Now(),
|
ChangeTime: time.Now(),
|
||||||
}
|
}
|
||||||
tree.Insert(&node)
|
err = tree.Insert(&node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
treeID, err := repo.SaveTree(gopts.ctx, tree)
|
treeID, err := repo.SaveTree(gopts.ctx, tree)
|
||||||
|
|
|
@ -243,7 +243,10 @@ func PrintSnapshots(stdout io.Writer, list restic.Snapshots, reasons []restic.Ke
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.Write(stdout)
|
err := tab.Write(stdout)
|
||||||
|
if err != nil {
|
||||||
|
Warnf("error printing: %v\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintSnapshotGroupHeader prints which group of the group-by option the
|
// PrintSnapshotGroupHeader prints which group of the group-by option the
|
||||||
|
|
|
@ -11,7 +11,8 @@ import (
|
||||||
func TestEmptySnapshotGroupJSON(t *testing.T) {
|
func TestEmptySnapshotGroupJSON(t *testing.T) {
|
||||||
for _, grouped := range []bool{false, true} {
|
for _, grouped := range []bool{false, true} {
|
||||||
var w strings.Builder
|
var w strings.Builder
|
||||||
printSnapshotGroupJSON(&w, nil, grouped)
|
err := printSnapshotGroupJSON(&w, nil, grouped)
|
||||||
|
rtest.OK(t, err)
|
||||||
|
|
||||||
rtest.Equals(t, "[]", strings.TrimSpace(w.String()))
|
rtest.Equals(t, "[]", strings.TrimSpace(w.String()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
// DeleteFiles deletes the given fileList of fileType in parallel
|
// DeleteFiles deletes the given fileList of fileType in parallel
|
||||||
// it will print a warning if there is an error, but continue deleting the remaining files
|
// it will print a warning if there is an error, but continue deleting the remaining files
|
||||||
func DeleteFiles(gopts GlobalOptions, repo restic.Repository, fileList restic.IDSet, fileType restic.FileType) {
|
func DeleteFiles(gopts GlobalOptions, repo restic.Repository, fileList restic.IDSet, fileType restic.FileType) {
|
||||||
deleteFiles(gopts, true, repo, fileList, fileType)
|
_ = deleteFiles(gopts, true, repo, fileList, fileType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFilesChecked deletes the given fileList of fileType in parallel
|
// DeleteFilesChecked deletes the given fileList of fileType in parallel
|
||||||
|
|
|
@ -180,7 +180,9 @@ func isDirExcludedByFile(dir, tagFilename, header string) bool {
|
||||||
Warnf("could not open exclusion tagfile: %v", err)
|
Warnf("could not open exclusion tagfile: %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer func() {
|
||||||
|
_ = f.Close()
|
||||||
|
}()
|
||||||
buf := make([]byte, len(header))
|
buf := make([]byte, len(header))
|
||||||
_, err = io.ReadFull(f, buf)
|
_, err = io.ReadFull(f, buf)
|
||||||
// EOF is handled with a dedicated message, otherwise the warning were too cryptic
|
// EOF is handled with a dedicated message, otherwise the warning were too cryptic
|
||||||
|
|
|
@ -566,9 +566,9 @@ func TestBackupErrors(t *testing.T) {
|
||||||
|
|
||||||
// Assume failure
|
// Assume failure
|
||||||
inaccessibleFile := filepath.Join(env.testdata, "0", "0", "9", "0")
|
inaccessibleFile := filepath.Join(env.testdata, "0", "0", "9", "0")
|
||||||
os.Chmod(inaccessibleFile, 0000)
|
rtest.OK(t, os.Chmod(inaccessibleFile, 0000))
|
||||||
defer func() {
|
defer func() {
|
||||||
os.Chmod(inaccessibleFile, 0644)
|
rtest.OK(t, os.Chmod(inaccessibleFile, 0644))
|
||||||
}()
|
}()
|
||||||
opts := BackupOptions{}
|
opts := BackupOptions{}
|
||||||
gopts := env.gopts
|
gopts := env.gopts
|
||||||
|
@ -933,7 +933,7 @@ func testRunKeyAddNewKeyUserHost(t testing.TB, gopts GlobalOptions) {
|
||||||
keyHostname = ""
|
keyHostname = ""
|
||||||
}()
|
}()
|
||||||
|
|
||||||
cmdKey.Flags().Parse([]string{"--user=john", "--host=example.com"})
|
rtest.OK(t, cmdKey.Flags().Parse([]string{"--user=john", "--host=example.com"}))
|
||||||
|
|
||||||
t.Log("adding key for john@example.com")
|
t.Log("adding key for john@example.com")
|
||||||
rtest.OK(t, runKey(gopts, []string{"add"}))
|
rtest.OK(t, runKey(gopts, []string{"add"}))
|
||||||
|
@ -1106,7 +1106,7 @@ func TestRestoreLatest(t *testing.T) {
|
||||||
testRunBackup(t, "", []string{filepath.Base(env.testdata)}, opts, env.gopts)
|
testRunBackup(t, "", []string{filepath.Base(env.testdata)}, opts, env.gopts)
|
||||||
testRunCheck(t, env.gopts)
|
testRunCheck(t, env.gopts)
|
||||||
|
|
||||||
os.Remove(p)
|
rtest.OK(t, os.Remove(p))
|
||||||
rtest.OK(t, appendRandomData(p, 101))
|
rtest.OK(t, appendRandomData(p, 101))
|
||||||
testRunBackup(t, "", []string{filepath.Base(env.testdata)}, opts, env.gopts)
|
testRunBackup(t, "", []string{filepath.Base(env.testdata)}, opts, env.gopts)
|
||||||
testRunCheck(t, env.gopts)
|
testRunCheck(t, env.gopts)
|
||||||
|
@ -1747,16 +1747,32 @@ func copyFile(dst string, src string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer srcFile.Close()
|
|
||||||
|
|
||||||
dstFile, err := os.Create(dst)
|
dstFile, err := os.Create(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// ignore subsequent errors
|
||||||
|
_ = srcFile.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer dstFile.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
return err
|
if err != nil {
|
||||||
|
// ignore subsequent errors
|
||||||
|
_ = srcFile.Close()
|
||||||
|
_ = dstFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = srcFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dstFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var diffOutputRegexPatterns = []string{
|
var diffOutputRegexPatterns = []string{
|
||||||
|
|
|
@ -405,7 +405,10 @@ func (arch *Archiver) Save(ctx context.Context, snPath, target string, previous
|
||||||
debug.Log("%v hasn't changed, but contents are missing!", target)
|
debug.Log("%v hasn't changed, but contents are missing!", target)
|
||||||
// There are contents missing - inform user!
|
// There are contents missing - inform user!
|
||||||
err := errors.Errorf("parts of %v not found in the repository index; storing the file again", target)
|
err := errors.Errorf("parts of %v not found in the repository index; storing the file again", target)
|
||||||
arch.error(abstarget, fi, err)
|
err = arch.error(abstarget, fi, err)
|
||||||
|
if err != nil {
|
||||||
|
return FutureNode{}, false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reopen file and do an fstat() on the open file to check it is still
|
// reopen file and do an fstat() on the open file to check it is still
|
||||||
|
@ -457,7 +460,10 @@ func (arch *Archiver) Save(ctx context.Context, snPath, target string, previous
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
oldSubtree, err := arch.loadSubtree(ctx, previous)
|
oldSubtree, err := arch.loadSubtree(ctx, previous)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
arch.error(abstarget, fi, err)
|
err = arch.error(abstarget, fi, err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return FutureNode{}, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fn.isTree = true
|
fn.isTree = true
|
||||||
|
@ -592,7 +598,10 @@ func (arch *Archiver) SaveTree(ctx context.Context, snPath string, atree *Tree,
|
||||||
oldNode := previous.Find(name)
|
oldNode := previous.Find(name)
|
||||||
oldSubtree, err := arch.loadSubtree(ctx, oldNode)
|
oldSubtree, err := arch.loadSubtree(ctx, oldNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
arch.error(join(snPath, name), nil, err)
|
err = arch.error(join(snPath, name), nil, err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// not a leaf node, archive subtree
|
// not a leaf node, archive subtree
|
||||||
|
@ -751,7 +760,7 @@ func (arch *Archiver) loadParentTree(ctx context.Context, snapshotID restic.ID)
|
||||||
tree, err := arch.Repo.LoadTree(ctx, *sn.Tree)
|
tree, err := arch.Repo.LoadTree(ctx, *sn.Tree)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("unable to load tree %v: %v", *sn.Tree, err)
|
debug.Log("unable to load tree %v: %v", *sn.Tree, err)
|
||||||
arch.error("/", nil, arch.wrapLoadTreeError(*sn.Tree, err))
|
_ = arch.error("/", nil, arch.wrapLoadTreeError(*sn.Tree, err))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return tree
|
return tree
|
||||||
|
|
Loading…
Reference in a new issue