update nodeRestoreExtendedAttributes() for win
- also other platforms - move xattr include/exclude filter parsing into separate func Signed-off-by: Tesshu Flower <tflower@redhat.com>
This commit is contained in:
parent
0d6e008114
commit
bb4c6d4934
7 changed files with 62 additions and 46 deletions
|
@ -101,9 +101,6 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||||
hasExcludes := len(excludePatternFns) > 0
|
hasExcludes := len(excludePatternFns) > 0
|
||||||
hasIncludes := len(includePatternFns) > 0
|
hasIncludes := len(includePatternFns) > 0
|
||||||
|
|
||||||
hasXattrExcludes := len(opts.ExcludeXattrPattern) > 0
|
|
||||||
hasXattrIncludes := len(opts.IncludeXattrPattern) > 0
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case len(args) == 0:
|
case len(args) == 0:
|
||||||
return errors.Fatal("no snapshot ID specified")
|
return errors.Fatal("no snapshot ID specified")
|
||||||
|
@ -119,10 +116,6 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||||
return errors.Fatal("exclude and include patterns are mutually exclusive")
|
return errors.Fatal("exclude and include patterns are mutually exclusive")
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasXattrExcludes && hasXattrIncludes {
|
|
||||||
return errors.Fatal("exclude and include xattr patterns are mutually exclusive")
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.DryRun && opts.Verify {
|
if opts.DryRun && opts.Verify {
|
||||||
return errors.Fatal("--dry-run and --verify are mutually exclusive")
|
return errors.Fatal("--dry-run and --verify are mutually exclusive")
|
||||||
}
|
}
|
||||||
|
@ -232,29 +225,9 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||||
res.SelectFilter = selectIncludeFilter
|
res.SelectFilter = selectIncludeFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasXattrExcludes && !hasXattrIncludes {
|
res.XattrSelectFilter, err = getXattrSelectFilter(opts)
|
||||||
// set default of including xattrs from the 'user' namespace
|
if err != nil {
|
||||||
opts.IncludeXattrPattern = []string{"user.*"}
|
return err
|
||||||
}
|
|
||||||
if hasXattrExcludes {
|
|
||||||
if err := filter.ValidatePatterns(opts.ExcludeXattrPattern); err != nil {
|
|
||||||
return errors.Fatalf("--exclude-xattr: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res.XattrSelectFilter = func(xattrName string) bool {
|
|
||||||
shouldReject := filter.RejectByPattern(opts.ExcludeXattrPattern, Warnf)(xattrName)
|
|
||||||
return !shouldReject
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// User has either input include xattr pattern(s) or we're using our default include pattern
|
|
||||||
if err := filter.ValidatePatterns(opts.IncludeXattrPattern); err != nil {
|
|
||||||
return errors.Fatalf("--include-xattr: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
res.XattrSelectFilter = func(xattrName string) bool {
|
|
||||||
shouldInclude, _ := filter.IncludeByPattern(opts.IncludeXattrPattern, Warnf)(xattrName)
|
|
||||||
return shouldInclude
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !gopts.JSON {
|
if !gopts.JSON {
|
||||||
|
@ -295,3 +268,38 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getXattrSelectFilter(opts RestoreOptions) (func(xattrName string) bool, error) {
|
||||||
|
hasXattrExcludes := len(opts.ExcludeXattrPattern) > 0
|
||||||
|
hasXattrIncludes := len(opts.IncludeXattrPattern) > 0
|
||||||
|
|
||||||
|
if hasXattrExcludes && hasXattrIncludes {
|
||||||
|
return nil, errors.Fatal("exclude and include xattr patterns are mutually exclusive")
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasXattrExcludes {
|
||||||
|
if err := filter.ValidatePatterns(opts.ExcludeXattrPattern); err != nil {
|
||||||
|
return nil, errors.Fatalf("--exclude-xattr: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(xattrName string) bool {
|
||||||
|
shouldReject := filter.RejectByPattern(opts.ExcludeXattrPattern, Warnf)(xattrName)
|
||||||
|
return !shouldReject
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasXattrIncludes {
|
||||||
|
// User has either input include xattr pattern(s) or we're using our default include pattern
|
||||||
|
if err := filter.ValidatePatterns(opts.IncludeXattrPattern); err != nil {
|
||||||
|
return nil, errors.Fatalf("--include-xattr: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(xattrName string) bool {
|
||||||
|
shouldInclude, _ := filter.IncludeByPattern(opts.IncludeXattrPattern, Warnf)(xattrName)
|
||||||
|
return shouldInclude
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// no includes or excludes, set default of including all xattrs
|
||||||
|
return func(_ string) bool { return true }, nil
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// nodeRestoreExtendedAttributes is a no-op
|
// nodeRestoreExtendedAttributes is a no-op
|
||||||
func nodeRestoreExtendedAttributes(_ *restic.Node, _ string) error {
|
func nodeRestoreExtendedAttributes(_ *restic.Node, _ string, _ func(xattrName string) bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,9 @@ func TestNodeRestoreAt(t *testing.T) {
|
||||||
nodePath = filepath.Join(tempdir, test.Name)
|
nodePath = filepath.Join(tempdir, test.Name)
|
||||||
}
|
}
|
||||||
rtest.OK(t, NodeCreateAt(&test, nodePath))
|
rtest.OK(t, NodeCreateAt(&test, nodePath))
|
||||||
|
// Restore metadata, restoring all xattrs
|
||||||
rtest.OK(t, NodeRestoreMetadata(&test, nodePath, func(msg string) { rtest.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", nodePath, msg)) },
|
rtest.OK(t, NodeRestoreMetadata(&test, nodePath, func(msg string) { rtest.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", nodePath, msg)) },
|
||||||
func(_ string) bool { return true } /* restore all xattrs */))
|
func(_ string) bool { return true }))
|
||||||
|
|
||||||
fs := &Local{}
|
fs := &Local{}
|
||||||
meta, err := fs.OpenFile(nodePath, O_NOFOLLOW, true)
|
meta, err := fs.OpenFile(nodePath, O_NOFOLLOW, true)
|
||||||
|
|
|
@ -69,17 +69,22 @@ func utimesNano(path string, atime, mtime int64, _ restic.NodeType) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore extended attributes for windows
|
// restore extended attributes for windows
|
||||||
func nodeRestoreExtendedAttributes(node *restic.Node, path string) (err error) {
|
func nodeRestoreExtendedAttributes(node *restic.Node, path string, xattrSelectFilter func(xattrName string) bool) error {
|
||||||
count := len(node.ExtendedAttributes)
|
count := len(node.ExtendedAttributes)
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
eas := make([]extendedAttribute, count)
|
eas := []extendedAttribute{}
|
||||||
for i, attr := range node.ExtendedAttributes {
|
for _, attr := range node.ExtendedAttributes {
|
||||||
eas[i] = extendedAttribute{Name: attr.Name, Value: attr.Value}
|
// Filter for xattrs we want to include/exclude
|
||||||
|
if xattrSelectFilter(attr.Name) {
|
||||||
|
eas = append(eas, extendedAttribute{Name: attr.Name, Value: attr.Value})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if len(eas) > 0 {
|
||||||
if errExt := restoreExtendedAttributes(node.Type, path, eas); errExt != nil {
|
if errExt := restoreExtendedAttributes(node.Type, path, eas); errExt != nil {
|
||||||
return errExt
|
return errExt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ func restoreAndGetNode(t *testing.T, tempDir string, testNode *restic.Node, warn
|
||||||
// If warning is not expected, this code should not get triggered.
|
// If warning is not expected, this code should not get triggered.
|
||||||
test.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", testPath, msg))
|
test.OK(t, fmt.Errorf("Warning triggered for path: %s: %s", testPath, msg))
|
||||||
}
|
}
|
||||||
})
|
}, func(_ string) bool { return true })
|
||||||
test.OK(t, errors.Wrapf(err, "Failed to restore metadata for: %s", testPath))
|
test.OK(t, errors.Wrapf(err, "Failed to restore metadata for: %s", testPath))
|
||||||
|
|
||||||
fs := &Local{}
|
fs := &Local{}
|
||||||
|
|
|
@ -26,7 +26,8 @@ func setAndVerifyXattr(t *testing.T, file string, attrs []restic.ExtendedAttribu
|
||||||
Type: restic.NodeTypeFile,
|
Type: restic.NodeTypeFile,
|
||||||
ExtendedAttributes: attrs,
|
ExtendedAttributes: attrs,
|
||||||
}
|
}
|
||||||
rtest.OK(t, nodeRestoreExtendedAttributes(node, file, func(_ string) bool { return true } /*restore all xattrs*/))
|
/* restore all xattrs */
|
||||||
|
rtest.OK(t, nodeRestoreExtendedAttributes(node, file, func(_ string) bool { return true }))
|
||||||
|
|
||||||
nodeActual := &restic.Node{
|
nodeActual := &restic.Node{
|
||||||
Type: restic.NodeTypeFile,
|
Type: restic.NodeTypeFile,
|
||||||
|
|
|
@ -104,6 +104,7 @@ func NewRestorer(repo restic.Repository, sn *restic.Snapshot, opts Options) *Res
|
||||||
fileList: make(map[string]bool),
|
fileList: make(map[string]bool),
|
||||||
Error: restorerAbortOnAllErrors,
|
Error: restorerAbortOnAllErrors,
|
||||||
SelectFilter: func(string, bool) (bool, bool) { return true, true },
|
SelectFilter: func(string, bool) (bool, bool) { return true, true },
|
||||||
|
XattrSelectFilter: func(string) bool { return true },
|
||||||
sn: sn,
|
sn: sn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue