2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-27 15:26:37 +00:00

Add ability to report warnings to terminal

Report warnings to terminal when unrecognized generic attributes are found in the repository.
This commit is contained in:
Aneesh Nireshwalia 2024-02-22 17:52:26 -07:00
parent 0962917974
commit eeb1aa5388
No known key found for this signature in database
GPG Key ID: 6F5A52831C046F44
9 changed files with 26 additions and 22 deletions

View File

@ -178,6 +178,9 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
totalErrors++ totalErrors++
return nil return nil
} }
res.Warn = func(message string) {
msg.E("Warning: %s\n", message)
}
excludePatterns := filter.ParsePatterns(opts.Exclude) excludePatterns := filter.ParsePatterns(opts.Exclude)
insensitiveExcludePatterns := filter.ParsePatterns(opts.InsensitiveExclude) insensitiveExcludePatterns := filter.ParsePatterns(opts.InsensitiveExclude)

View File

@ -224,8 +224,8 @@ func (node *Node) CreateAt(ctx context.Context, path string, repo BlobLoader) er
} }
// RestoreMetadata restores node metadata // RestoreMetadata restores node metadata
func (node Node) RestoreMetadata(path string) error { func (node Node) RestoreMetadata(path string, warn func(msg string)) error {
err := node.restoreMetadata(path) err := node.restoreMetadata(path, warn)
if err != nil { if err != nil {
debug.Log("restoreMetadata(%s) error %v", path, err) debug.Log("restoreMetadata(%s) error %v", path, err)
} }
@ -233,7 +233,7 @@ func (node Node) RestoreMetadata(path string) error {
return err return err
} }
func (node Node) restoreMetadata(path string) error { func (node Node) restoreMetadata(path string, warn func(msg string)) error {
var firsterr error var firsterr error
if err := lchown(path, int(node.UID), int(node.GID)); err != nil { if err := lchown(path, int(node.UID), int(node.GID)); err != nil {
@ -261,7 +261,7 @@ func (node Node) restoreMetadata(path string) error {
} }
} }
if err := node.restoreGenericAttributes(path); err != nil { if err := node.restoreGenericAttributes(path, warn); err != nil {
debug.Log("error restoring generic attributes for %v: %v", path, err) debug.Log("error restoring generic attributes for %v: %v", path, err)
if firsterr != nil { if firsterr != nil {
firsterr = err firsterr = err
@ -766,14 +766,14 @@ func (node *Node) fillTimes(stat *statT) {
} }
// HandleUnknownGenericAttributesFound is used for handling and distinguing between scenarios related to future versions and cross-OS repositories // HandleUnknownGenericAttributesFound is used for handling and distinguing between scenarios related to future versions and cross-OS repositories
func HandleUnknownGenericAttributesFound(unknownAttribs []GenericAttributeType) { func HandleUnknownGenericAttributesFound(unknownAttribs []GenericAttributeType, warn func(msg string)) {
for _, unknownAttrib := range unknownAttribs { for _, unknownAttrib := range unknownAttribs {
handleUnknownGenericAttributeFound(unknownAttrib) handleUnknownGenericAttributeFound(unknownAttrib, warn)
} }
} }
// handleUnknownGenericAttributeFound is used for handling and distinguing between scenarios related to future versions and cross-OS repositories // handleUnknownGenericAttributeFound is used for handling and distinguing between scenarios related to future versions and cross-OS repositories
func handleUnknownGenericAttributeFound(genericAttributeType GenericAttributeType) { func handleUnknownGenericAttributeFound(genericAttributeType GenericAttributeType, warn func(msg string)) {
if checkGenericAttributeNameNotHandledAndPut(genericAttributeType) { if checkGenericAttributeNameNotHandledAndPut(genericAttributeType) {
// Print the unique error only once for a given execution // Print the unique error only once for a given execution
os, exists := genericAttributesForOS[genericAttributeType] os, exists := genericAttributesForOS[genericAttributeType]
@ -784,7 +784,7 @@ func handleUnknownGenericAttributeFound(genericAttributeType GenericAttributeTyp
debug.Log("Ignoring a generic attribute found in the repository: %s which may not be compatible with your OS. Compatible OS: %s", genericAttributeType, os) debug.Log("Ignoring a generic attribute found in the repository: %s which may not be compatible with your OS. Compatible OS: %s", genericAttributeType, os)
} else { } else {
// If genericAttributesForOS in node.go does not know about this attribute, then the repository may have been created by a newer version which has a newer GenericAttributeType. // If genericAttributesForOS in node.go does not know about this attribute, then the repository may have been created by a newer version which has a newer GenericAttributeType.
debug.Log("Found an unrecognized generic attribute in the repository: %s. You may need to upgrade to latest version of restic.", genericAttributeType) warn(fmt.Sprintf("Found an unrecognized generic attribute in the repository: %s. You may need to upgrade to latest version of restic.", genericAttributeType))
} }
} }
} }
@ -792,9 +792,9 @@ func handleUnknownGenericAttributeFound(genericAttributeType GenericAttributeTyp
// handleAllUnknownGenericAttributesFound performs validations for all generic attributes in the node. // handleAllUnknownGenericAttributesFound performs validations for all generic attributes in the node.
// This is not used on windows currently because windows has handling for generic attributes. // This is not used on windows currently because windows has handling for generic attributes.
// nolint:unused // nolint:unused
func (node Node) handleAllUnknownGenericAttributesFound() error { func (node Node) handleAllUnknownGenericAttributesFound(warn func(msg string)) error {
for name := range node.GenericAttributes { for name := range node.GenericAttributes {
handleUnknownGenericAttributeFound(name) handleUnknownGenericAttributeFound(name, warn)
} }
return nil return nil
} }

View File

@ -39,8 +39,8 @@ func Setxattr(path, name string, data []byte) error {
} }
// restoreGenericAttributes is no-op on AIX. // restoreGenericAttributes is no-op on AIX.
func (node *Node) restoreGenericAttributes(_ string) error { func (node *Node) restoreGenericAttributes(_ string, warn func(msg string)) error {
return node.handleAllUnknownGenericAttributesFound() return node.handleAllUnknownGenericAttributesFound(warn)
} }
// fillGenericAttributes is a no-op on AIX. // fillGenericAttributes is a no-op on AIX.

View File

@ -29,8 +29,8 @@ func Setxattr(path, name string, data []byte) error {
} }
// restoreGenericAttributes is no-op on netbsd. // restoreGenericAttributes is no-op on netbsd.
func (node *Node) restoreGenericAttributes(_ string) error { func (node *Node) restoreGenericAttributes(_ string, warn func(msg string)) error {
return node.handleAllUnknownGenericAttributesFound() return node.handleAllUnknownGenericAttributesFound(warn)
} }
// fillGenericAttributes is a no-op on netbsd. // fillGenericAttributes is a no-op on netbsd.

View File

@ -29,8 +29,8 @@ func Setxattr(path, name string, data []byte) error {
} }
// restoreGenericAttributes is no-op on openbsd. // restoreGenericAttributes is no-op on openbsd.
func (node *Node) restoreGenericAttributes(_ string) error { func (node *Node) restoreGenericAttributes(_ string, warn func(msg string)) error {
return node.handleAllUnknownGenericAttributesFound() return node.handleAllUnknownGenericAttributesFound(warn)
} }
// fillGenericAttributes is a no-op on openbsd. // fillGenericAttributes is a no-op on openbsd.

View File

@ -218,7 +218,7 @@ func TestNodeRestoreAt(t *testing.T) {
nodePath = filepath.Join(tempdir, test.Name) nodePath = filepath.Join(tempdir, test.Name)
} }
rtest.OK(t, test.CreateAt(context.TODO(), nodePath, nil)) rtest.OK(t, test.CreateAt(context.TODO(), nodePath, nil))
rtest.OK(t, test.RestoreMetadata(nodePath)) rtest.OK(t, test.RestoreMetadata(nodePath, func(msg string) { rtest.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", nodePath, msg)) }))
if test.Type == "dir" { if test.Type == "dir" {
rtest.OK(t, test.RestoreTimestamps(nodePath)) rtest.OK(t, test.RestoreTimestamps(nodePath))

View File

@ -118,7 +118,7 @@ func (s statT) ctim() syscall.Timespec {
} }
// restoreGenericAttributes restores generic attributes for Windows // restoreGenericAttributes restores generic attributes for Windows
func (node Node) restoreGenericAttributes(path string) (err error) { func (node Node) restoreGenericAttributes(path string, warn func(msg string)) (err error) {
if len(node.GenericAttributes) == 0 { if len(node.GenericAttributes) == 0 {
return nil return nil
} }
@ -138,7 +138,7 @@ func (node Node) restoreGenericAttributes(path string) (err error) {
} }
} }
HandleUnknownGenericAttributesFound(unknownAttribs) HandleUnknownGenericAttributesFound(unknownAttribs, warn)
return errors.CombineErrors(errs...) return errors.CombineErrors(errs...)
} }

View File

@ -50,8 +50,8 @@ func handleXattrErr(err error) error {
} }
// restoreGenericAttributes is no-op. // restoreGenericAttributes is no-op.
func (node *Node) restoreGenericAttributes(_ string) error { func (node *Node) restoreGenericAttributes(_ string, warn func(msg string)) error {
return node.handleAllUnknownGenericAttributesFound() return node.handleAllUnknownGenericAttributesFound(warn)
} }
// fillGenericAttributes is a no-op. // fillGenericAttributes is a no-op.

View File

@ -24,6 +24,7 @@ type Restorer struct {
progress *restoreui.Progress progress *restoreui.Progress
Error func(location string, err error) error Error func(location string, err error) error
Warn func(message string)
SelectFilter func(item string, dstpath string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) SelectFilter func(item string, dstpath string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool)
} }
@ -178,7 +179,7 @@ func (res *Restorer) restoreNodeTo(ctx context.Context, node *restic.Node, targe
func (res *Restorer) restoreNodeMetadataTo(node *restic.Node, target, location string) error { func (res *Restorer) restoreNodeMetadataTo(node *restic.Node, target, location string) error {
debug.Log("restoreNodeMetadata %v %v %v", node.Name, target, location) debug.Log("restoreNodeMetadata %v %v %v", node.Name, target, location)
err := node.RestoreMetadata(target) err := node.RestoreMetadata(target, res.Warn)
if err != nil { if err != nil {
debug.Log("node.RestoreMetadata(%s) error %v", target, err) debug.Log("node.RestoreMetadata(%s) error %v", target, err)
} }