Add iexclude and iinclude options to restore command

This commit is contained in:
Johannes Hertenstein 2018-10-16 22:39:55 +02:00 committed by Alexander Neumann
parent db82e6b80c
commit c13f79da02
2 changed files with 38 additions and 13 deletions

View File

@ -28,13 +28,15 @@ repository.
// 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
Include []string InsensitiveExclude []string
Target string Include []string
Host string InsensitiveInclude []string
Paths []string Target string
Tags restic.TagLists Host string
Verify bool Paths []string
Tags restic.TagLists
Verify bool
} }
var restoreOptions RestoreOptions var restoreOptions RestoreOptions
@ -44,7 +46,9 @@ func init() {
flags := cmdRestore.Flags() flags := cmdRestore.Flags()
flags.StringArrayVarP(&restoreOptions.Exclude, "exclude", "e", nil, "exclude a `pattern` (can be specified multiple times)") flags.StringArrayVarP(&restoreOptions.Exclude, "exclude", "e", nil, "exclude a `pattern` (can be specified multiple times)")
flags.StringArrayVar(&restoreOptions.InsensitiveExclude, "iexclude", nil, "same as `--exclude` but ignores the casing of filenames")
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 filenames")
flags.StringVarP(&restoreOptions.Target, "target", "t", "", "directory to extract data to") flags.StringVarP(&restoreOptions.Target, "target", "t", "", "directory to extract data to")
flags.StringVarP(&restoreOptions.Host, "host", "H", "", `only consider snapshots for this host when the snapshot ID is "latest"`) flags.StringVarP(&restoreOptions.Host, "host", "H", "", `only consider snapshots for this host when the snapshot ID is "latest"`)
@ -55,6 +59,8 @@ func init() {
func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error { func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
ctx := gopts.ctx ctx := gopts.ctx
hasExcludes := len(opts.Exclude) > 0 || len(opts.InsensitiveExclude) > 0
hasIncludes := len(opts.Include) > 0 || len(opts.InsensitiveInclude) > 0
switch { switch {
case len(args) == 0: case len(args) == 0:
@ -67,7 +73,7 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
return errors.Fatal("please specify a directory to restore to (--target)") return errors.Fatal("please specify a directory to restore to (--target)")
} }
if len(opts.Exclude) > 0 && len(opts.Include) > 0 { if hasExcludes && hasIncludes {
return errors.Fatal("exclude and include patterns are mutually exclusive") return errors.Fatal("exclude and include patterns are mutually exclusive")
} }
@ -125,11 +131,16 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
Warnf("error for exclude pattern: %v", err) Warnf("error for exclude pattern: %v", err)
} }
matchedInsensitive, _, err := filter.InsensitiveList(opts.InsensitiveExclude, item)
if err != nil {
Warnf("error for iexclude pattern: %v", err)
}
// An exclude filter is basically a 'wildcard but foo', // An exclude filter is basically a 'wildcard but foo',
// so even if a childMayMatch, other children of a dir may not, // so even if a childMayMatch, other children of a dir may not,
// therefore childMayMatch does not matter, but we should not go down // therefore childMayMatch does not matter, but we should not go down
// unless the dir is selected for restore // unless the dir is selected for restore
selectedForRestore = !matched selectedForRestore = !matched && !matchedInsensitive
childMayBeSelected = selectedForRestore && node.Type == "dir" childMayBeSelected = selectedForRestore && node.Type == "dir"
return selectedForRestore, childMayBeSelected return selectedForRestore, childMayBeSelected
@ -141,15 +152,20 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
Warnf("error for include pattern: %v", err) Warnf("error for include pattern: %v", err)
} }
selectedForRestore = matched matchedInsensitive, childMayMatchInsensitive, err := filter.InsensitiveList(opts.InsensitiveInclude, item)
childMayBeSelected = childMayMatch && node.Type == "dir" if err != nil {
Warnf("error for iexclude pattern: %v", err)
}
selectedForRestore = matched || matchedInsensitive
childMayBeSelected = (childMayMatch || childMayMatchInsensitive) && node.Type == "dir"
return selectedForRestore, childMayBeSelected return selectedForRestore, childMayBeSelected
} }
if len(opts.Exclude) > 0 { if hasExcludes {
res.SelectFilter = selectExcludeFilter res.SelectFilter = selectExcludeFilter
} else if len(opts.Include) > 0 { } else if hasIncludes {
res.SelectFilter = selectIncludeFilter res.SelectFilter = selectIncludeFilter
} }

View File

@ -187,3 +187,12 @@ func List(patterns []string, str string) (matched bool, childMayMatch bool, err
return matched, childMayMatch, nil return matched, childMayMatch, nil
} }
// InsensitiveList is the same as List but case insensitive.
func InsensitiveList(patterns []string, str string) (matched bool, childMayMatch bool, err error) {
str = strings.ToLower(str)
for index, path := range patterns {
patterns[index] = strings.ToLower(path)
}
return List(patterns, str)
}