mirror of
https://github.com/restic/restic.git
synced 2024-12-21 23:33:03 +00:00
Merge pull request #5083 from greatroar/errors
Some error handling patches
This commit is contained in:
commit
0c0d8b8cfd
6 changed files with 46 additions and 57 deletions
|
@ -2,7 +2,6 @@ package errors
|
|||
|
||||
import (
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -36,35 +35,11 @@ func As(err error, tgt interface{}) bool { return stderrors.As(err, tgt) }
|
|||
// Is reports whether any error in err's tree matches target.
|
||||
func Is(x, y error) bool { return stderrors.Is(x, y) }
|
||||
|
||||
func Join(errs ...error) error { return stderrors.Join(errs...) }
|
||||
|
||||
// Unwrap returns the result of calling the Unwrap method on err, if err's type contains
|
||||
// an Unwrap method returning error. Otherwise, Unwrap returns nil.
|
||||
//
|
||||
// Unwrap only calls a method of the form "Unwrap() error". In particular Unwrap does not
|
||||
// unwrap errors returned by [Join].
|
||||
func Unwrap(err error) error { return stderrors.Unwrap(err) }
|
||||
|
||||
// CombineErrors combines multiple errors into a single error after filtering out any nil values.
|
||||
// If no errors are passed, it returns nil.
|
||||
// If one error is passed, it simply returns that same error.
|
||||
func CombineErrors(errors ...error) (err error) {
|
||||
var combinedErrorMsg string
|
||||
var multipleErrors bool
|
||||
for _, errVal := range errors {
|
||||
if errVal != nil {
|
||||
if combinedErrorMsg != "" {
|
||||
combinedErrorMsg += "; " // Separate error messages with a delimiter
|
||||
multipleErrors = true
|
||||
} else {
|
||||
// Set the first error
|
||||
err = errVal
|
||||
}
|
||||
combinedErrorMsg += errVal.Error()
|
||||
}
|
||||
}
|
||||
if combinedErrorMsg == "" {
|
||||
return nil // If no errors, return nil
|
||||
} else if !multipleErrors {
|
||||
return err // If only one error, return that first error
|
||||
}
|
||||
return fmt.Errorf("multiple errors occurred: [%s]", combinedErrorMsg)
|
||||
}
|
||||
|
|
|
@ -3,8 +3,16 @@
|
|||
|
||||
package fs
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
import (
|
||||
"os"
|
||||
|
||||
func mknod(path string, mode uint32, dev uint64) (err error) {
|
||||
return unix.Mknod(path, mode, int(dev))
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func mknod(path string, mode uint32, dev uint64) error {
|
||||
err := unix.Mknod(path, mode, int(dev))
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "mknod", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ func nodeFillExtra(node *restic.Node, path string, fi os.FileInfo, ignoreXattrLi
|
|||
allowExtended, err := nodeFillGenericAttributes(node, path, &stat)
|
||||
if allowExtended {
|
||||
// Skip processing ExtendedAttributes if allowExtended is false.
|
||||
err = errors.CombineErrors(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError))
|
||||
err = errors.Join(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -163,41 +163,29 @@ func lookupGroup(gid uint32) string {
|
|||
}
|
||||
|
||||
// NodeCreateAt creates the node at the given path but does NOT restore node meta data.
|
||||
func NodeCreateAt(node *restic.Node, path string) error {
|
||||
func NodeCreateAt(node *restic.Node, path string) (err error) {
|
||||
debug.Log("create node %v at %v", node.Name, path)
|
||||
|
||||
switch node.Type {
|
||||
case restic.NodeTypeDir:
|
||||
if err := nodeCreateDirAt(node, path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateDirAt(node, path)
|
||||
case restic.NodeTypeFile:
|
||||
if err := nodeCreateFileAt(path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateFileAt(path)
|
||||
case restic.NodeTypeSymlink:
|
||||
if err := nodeCreateSymlinkAt(node, path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateSymlinkAt(node, path)
|
||||
case restic.NodeTypeDev:
|
||||
if err := nodeCreateDevAt(node, path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateDevAt(node, path)
|
||||
case restic.NodeTypeCharDev:
|
||||
if err := nodeCreateCharDevAt(node, path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateCharDevAt(node, path)
|
||||
case restic.NodeTypeFifo:
|
||||
if err := nodeCreateFifoAt(path); err != nil {
|
||||
return err
|
||||
}
|
||||
err = nodeCreateFifoAt(path)
|
||||
case restic.NodeTypeSocket:
|
||||
return nil
|
||||
err = nil
|
||||
default:
|
||||
return errors.Errorf("filetype %q not implemented", node.Type)
|
||||
err = errors.Errorf("filetype %q not implemented", node.Type)
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func nodeCreateDirAt(node *restic.Node, path string) error {
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
|
||||
package fs
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func nodeRestoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mknod(path string, mode uint32, dev uint64) (err error) {
|
||||
return syscall.Mknod(path, mode, dev)
|
||||
func mknod(path string, mode uint32, dev uint64) error {
|
||||
err := syscall.Mknod(path, mode, dev)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "mknod", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/restic/restic/internal/errors"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
rtest "github.com/restic/restic/internal/test"
|
||||
)
|
||||
|
@ -134,3 +136,12 @@ func TestNodeFromFileInfo(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMknodError(t *testing.T) {
|
||||
d := t.TempDir()
|
||||
// Call mkfifo, which calls mknod, as mknod may give
|
||||
// "operation not permitted" on Mac.
|
||||
err := mkfifo(d, 0)
|
||||
rtest.Assert(t, errors.Is(err, os.ErrExist), "want ErrExist, got %q", err)
|
||||
rtest.Assert(t, strings.Contains(err.Error(), d), "filename not in %q", err)
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ func nodeRestoreGenericAttributes(node *restic.Node, path string, warn func(msg
|
|||
}
|
||||
|
||||
restic.HandleUnknownGenericAttributesFound(unknownAttribs, warn)
|
||||
return errors.CombineErrors(errs...)
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// genericAttributesToWindowsAttrs converts the generic attributes map to a WindowsAttributes and also returns a string of unknown attributes that it could not convert.
|
||||
|
|
Loading…
Reference in a new issue