Merge pull request #5129 from tesshuflower/5089_exclude_xattrs_on_restore

Allow excluding xattrs at restore time
This commit is contained in:
Michael Eischer
2025-01-18 23:15:11 +01:00
committed by GitHub
11 changed files with 271 additions and 35 deletions
+51 -5
View File
@@ -54,11 +54,13 @@ type RestoreOptions struct {
filter.IncludePatternOptions
Target string
restic.SnapshotFilter
DryRun bool
Sparse bool
Verify bool
Overwrite restorer.OverwriteBehavior
Delete bool
DryRun bool
Sparse bool
Verify bool
Overwrite restorer.OverwriteBehavior
Delete bool
ExcludeXattrPattern []string
IncludeXattrPattern []string
}
var restoreOptions RestoreOptions
@@ -72,6 +74,9 @@ func init() {
restoreOptions.ExcludePatternOptions.Add(flags)
restoreOptions.IncludePatternOptions.Add(flags)
flags.StringArrayVar(&restoreOptions.ExcludeXattrPattern, "exclude-xattr", nil, "exclude xattr by `pattern` (can be specified multiple times)")
flags.StringArrayVar(&restoreOptions.IncludeXattrPattern, "include-xattr", nil, "include xattr by `pattern` (can be specified multiple times)")
initSingleSnapshotFilter(flags, &restoreOptions.SnapshotFilter)
flags.BoolVar(&restoreOptions.DryRun, "dry-run", false, "do not write any data, just show what would be done")
flags.BoolVar(&restoreOptions.Sparse, "sparse", false, "restore files as sparse")
@@ -110,6 +115,7 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
if hasExcludes && hasIncludes {
return errors.Fatal("exclude and include patterns are mutually exclusive")
}
if opts.DryRun && opts.Verify {
return errors.Fatal("--dry-run and --verify are mutually exclusive")
}
@@ -219,6 +225,11 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
res.SelectFilter = selectIncludeFilter
}
res.XattrSelectFilter, err = getXattrSelectFilter(opts)
if err != nil {
return err
}
if !gopts.JSON {
msg.P("restoring %s to %s\n", res.Snapshot(), opts.Target)
}
@@ -257,3 +268,38 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
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
}
// default to including all xattrs
return func(_ string) bool { return true }, nil
}