mirror of
https://github.com/octoleo/restic.git
synced 2025-01-24 15:48:25 +00:00
restore: read includes, insensitive includes, excludes and insensitive excludes from a file
feature for gh-4781
This commit is contained in:
parent
78485160fc
commit
b02117ef0b
@ -45,11 +45,15 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
|
|||||||
|
|
||||||
// RestoreOptions collects all options for the restore command.
|
// RestoreOptions collects all options for the restore command.
|
||||||
type RestoreOptions struct {
|
type RestoreOptions struct {
|
||||||
Exclude []string
|
Exclude []string
|
||||||
InsensitiveExclude []string
|
ExcludeFiles []string
|
||||||
Include []string
|
InsensitiveExclude []string
|
||||||
InsensitiveInclude []string
|
InsensitiveExcludeFiles []string
|
||||||
Target string
|
Include []string
|
||||||
|
IncludeFiles []string
|
||||||
|
InsensitiveInclude []string
|
||||||
|
InsensitiveIncludeFiles []string
|
||||||
|
Target string
|
||||||
restic.SnapshotFilter
|
restic.SnapshotFilter
|
||||||
Sparse bool
|
Sparse bool
|
||||||
Verify bool
|
Verify bool
|
||||||
@ -66,6 +70,10 @@ func init() {
|
|||||||
flags.StringArrayVarP(&restoreOptions.Include, "include", "i", nil, "include a `pattern`, exclude everything else (can be specified multiple times)")
|
flags.StringArrayVarP(&restoreOptions.Include, "include", "i", nil, "include a `pattern`, exclude everything else (can be specified multiple times)")
|
||||||
flags.StringArrayVar(&restoreOptions.InsensitiveInclude, "iinclude", nil, "same as --include but ignores the casing of `pattern`")
|
flags.StringArrayVar(&restoreOptions.InsensitiveInclude, "iinclude", nil, "same as --include but ignores the casing of `pattern`")
|
||||||
flags.StringVarP(&restoreOptions.Target, "target", "t", "", "directory to extract data to")
|
flags.StringVarP(&restoreOptions.Target, "target", "t", "", "directory to extract data to")
|
||||||
|
flags.StringArrayVar(&restoreOptions.ExcludeFiles, "exclude-file", nil, "read exclude patterns from a `file` (can be specified multiple times)")
|
||||||
|
flags.StringArrayVar(&restoreOptions.InsensitiveExcludeFiles, "iexclude-file", nil, "same as --exclude-file but ignores casing of `file`names in patterns")
|
||||||
|
flags.StringArrayVar(&restoreOptions.IncludeFiles, "include-file", nil, "read include patterns from a `file` (can be specified multiple times)")
|
||||||
|
flags.StringArrayVar(&restoreOptions.InsensitiveIncludeFiles, "iinclude-file", nil, "same as --include-file but ignores casing of `file`names in patterns")
|
||||||
|
|
||||||
initSingleSnapshotFilter(flags, &restoreOptions.SnapshotFilter)
|
initSingleSnapshotFilter(flags, &restoreOptions.SnapshotFilter)
|
||||||
flags.BoolVar(&restoreOptions.Sparse, "sparse", false, "restore files as sparse")
|
flags.BoolVar(&restoreOptions.Sparse, "sparse", false, "restore files as sparse")
|
||||||
@ -176,6 +184,27 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
|||||||
|
|
||||||
excludePatterns := filter.ParsePatterns(opts.Exclude)
|
excludePatterns := filter.ParsePatterns(opts.Exclude)
|
||||||
insensitiveExcludePatterns := filter.ParsePatterns(opts.InsensitiveExclude)
|
insensitiveExcludePatterns := filter.ParsePatterns(opts.InsensitiveExclude)
|
||||||
|
|
||||||
|
if len(opts.ExcludeFiles) > 0 {
|
||||||
|
patternsFromFile, err := readPatternsFromFiles(opts.ExcludeFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
excludePatternsFromFile := filter.ParsePatterns(patternsFromFile)
|
||||||
|
excludePatterns = append(excludePatterns, excludePatternsFromFile...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts.InsensitiveExcludeFiles) > 0 {
|
||||||
|
patternsFromFile, err := readPatternsFromFiles(opts.ExcludeFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
iexcludePatternsFromFile := filter.ParsePatterns(patternsFromFile)
|
||||||
|
insensitiveExcludePatterns = append(insensitiveExcludePatterns, iexcludePatternsFromFile...)
|
||||||
|
}
|
||||||
|
|
||||||
selectExcludeFilter := func(item string, _ string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
selectExcludeFilter := func(item string, _ string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
||||||
matched, err := filter.List(excludePatterns, item)
|
matched, err := filter.List(excludePatterns, item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -199,6 +228,27 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
|
|||||||
|
|
||||||
includePatterns := filter.ParsePatterns(opts.Include)
|
includePatterns := filter.ParsePatterns(opts.Include)
|
||||||
insensitiveIncludePatterns := filter.ParsePatterns(opts.InsensitiveInclude)
|
insensitiveIncludePatterns := filter.ParsePatterns(opts.InsensitiveInclude)
|
||||||
|
|
||||||
|
if len(opts.IncludeFiles) > 0 {
|
||||||
|
patternsFromFile, err := readPatternsFromFiles(opts.IncludeFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
includePatternsFromFile := filter.ParsePatterns(patternsFromFile)
|
||||||
|
includePatterns = append(includePatterns, includePatternsFromFile...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts.InsensitiveIncludeFiles) > 0 {
|
||||||
|
patternsFromFile, err := readPatternsFromFiles(opts.InsensitiveIncludeFiles)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
iincludePatternsFromFile := filter.ParsePatterns(patternsFromFile)
|
||||||
|
insensitiveIncludePatterns = append(insensitiveIncludePatterns, iincludePatternsFromFile...)
|
||||||
|
}
|
||||||
|
|
||||||
selectIncludeFilter := func(item string, _ string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
selectIncludeFilter := func(item string, _ string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
||||||
matched, childMayMatch, err := filter.ListWithChild(includePatterns, item)
|
matched, childMayMatch, err := filter.ListWithChild(includePatterns, item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -385,12 +385,12 @@ func rejectBySize(maxSizeStr string) (RejectFunc, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readExcludePatternsFromFiles reads all exclude files and returns the list of
|
// readPatternsFromFiles reads all files and returns the list of
|
||||||
// exclude patterns. For each line, leading and trailing white space is removed
|
// patterns. For each line, leading and trailing white space is removed
|
||||||
// and comment lines are ignored. For each remaining pattern, environment
|
// and comment lines are ignored. For each remaining pattern, environment
|
||||||
// variables are resolved. For adding a literal dollar sign ($), write $$ to
|
// variables are resolved. For adding a literal dollar sign ($), write $$ to
|
||||||
// the file.
|
// the file.
|
||||||
func readExcludePatternsFromFiles(excludeFiles []string) ([]string, error) {
|
func readPatternsFromFiles(files []string) ([]string, error) {
|
||||||
getenvOrDollar := func(s string) string {
|
getenvOrDollar := func(s string) string {
|
||||||
if s == "$" {
|
if s == "$" {
|
||||||
return "$"
|
return "$"
|
||||||
@ -398,8 +398,8 @@ func readExcludePatternsFromFiles(excludeFiles []string) ([]string, error) {
|
|||||||
return os.Getenv(s)
|
return os.Getenv(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
var excludes []string
|
var patterns []string
|
||||||
for _, filename := range excludeFiles {
|
for _, filename := range files {
|
||||||
err := func() (err error) {
|
err := func() (err error) {
|
||||||
data, err := textfile.Read(filename)
|
data, err := textfile.Read(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -421,15 +421,15 @@ func readExcludePatternsFromFiles(excludeFiles []string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
line = os.Expand(line, getenvOrDollar)
|
line = os.Expand(line, getenvOrDollar)
|
||||||
excludes = append(excludes, line)
|
patterns = append(patterns, line)
|
||||||
}
|
}
|
||||||
return scanner.Err()
|
return scanner.Err()
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read excludes from file %q: %w", filename, err)
|
return nil, fmt.Errorf("failed to read patterns from file %q: %w", filename, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return excludes, nil
|
return patterns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type excludePatternOptions struct {
|
type excludePatternOptions struct {
|
||||||
@ -454,7 +454,7 @@ func (opts excludePatternOptions) CollectPatterns() ([]RejectByNameFunc, error)
|
|||||||
var fs []RejectByNameFunc
|
var fs []RejectByNameFunc
|
||||||
// add patterns from file
|
// add patterns from file
|
||||||
if len(opts.ExcludeFiles) > 0 {
|
if len(opts.ExcludeFiles) > 0 {
|
||||||
excludePatterns, err := readExcludePatternsFromFiles(opts.ExcludeFiles)
|
excludePatterns, err := readPatternsFromFiles(opts.ExcludeFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -467,7 +467,7 @@ func (opts excludePatternOptions) CollectPatterns() ([]RejectByNameFunc, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.InsensitiveExcludeFiles) > 0 {
|
if len(opts.InsensitiveExcludeFiles) > 0 {
|
||||||
excludes, err := readExcludePatternsFromFiles(opts.InsensitiveExcludeFiles)
|
excludes, err := readPatternsFromFiles(opts.InsensitiveExcludeFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user