From c13f79da0231a3a2b63e37ed3d755accc6614ce1 Mon Sep 17 00:00:00 2001 From: Johannes Hertenstein Date: Tue, 16 Oct 2018 22:39:55 +0200 Subject: [PATCH] Add iexclude and iinclude options to restore command --- cmd/restic/cmd_restore.go | 42 +++++++++++++++++++++++++++------------ internal/filter/filter.go | 9 +++++++++ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index 477192eab..a711da4dd 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -28,13 +28,15 @@ repository. // RestoreOptions collects all options for the restore command. type RestoreOptions struct { - Exclude []string - Include []string - Target string - Host string - Paths []string - Tags restic.TagLists - Verify bool + Exclude []string + InsensitiveExclude []string + Include []string + InsensitiveInclude []string + Target string + Host string + Paths []string + Tags restic.TagLists + Verify bool } var restoreOptions RestoreOptions @@ -44,7 +46,9 @@ func init() { flags := cmdRestore.Flags() 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.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.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 { ctx := gopts.ctx + hasExcludes := len(opts.Exclude) > 0 || len(opts.InsensitiveExclude) > 0 + hasIncludes := len(opts.Include) > 0 || len(opts.InsensitiveInclude) > 0 switch { 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)") } - if len(opts.Exclude) > 0 && len(opts.Include) > 0 { + if hasExcludes && hasIncludes { 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) } + 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', // so even if a childMayMatch, other children of a dir may not, // therefore childMayMatch does not matter, but we should not go down // unless the dir is selected for restore - selectedForRestore = !matched + selectedForRestore = !matched && !matchedInsensitive childMayBeSelected = selectedForRestore && node.Type == "dir" return selectedForRestore, childMayBeSelected @@ -141,15 +152,20 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error { Warnf("error for include pattern: %v", err) } - selectedForRestore = matched - childMayBeSelected = childMayMatch && node.Type == "dir" + matchedInsensitive, childMayMatchInsensitive, err := filter.InsensitiveList(opts.InsensitiveInclude, item) + if err != nil { + Warnf("error for iexclude pattern: %v", err) + } + + selectedForRestore = matched || matchedInsensitive + childMayBeSelected = (childMayMatch || childMayMatchInsensitive) && node.Type == "dir" return selectedForRestore, childMayBeSelected } - if len(opts.Exclude) > 0 { + if hasExcludes { res.SelectFilter = selectExcludeFilter - } else if len(opts.Include) > 0 { + } else if hasIncludes { res.SelectFilter = selectIncludeFilter } diff --git a/internal/filter/filter.go b/internal/filter/filter.go index 74deddb03..71ae4817c 100644 --- a/internal/filter/filter.go +++ b/internal/filter/filter.go @@ -187,3 +187,12 @@ func List(patterns []string, str string) (matched bool, childMayMatch bool, err 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) +}