Merge pull request #3819 from lbausch/restore-validate-patterns

restore: validate include/exclude patterns
This commit is contained in:
MichaelEischer 2022-07-12 20:58:41 +02:00 committed by GitHub
commit 3934480da4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 0 deletions

View File

@ -0,0 +1,10 @@
Enhancement: Validate include/exclude patterns before restoring
Patterns provided to `restic restore` via `--exclude`, `--iexclude`,
`--include` and `--iinclude` weren't validated before running the restore.
Invalid patterns would result in error messages being printed repeatedly
and possibly unwanted files being restored.
restic now validates all patterns before running the restore and aborts with
a fatal error if an invalid pattern is detected.
https://github.com/restic/restic/pull/3819

View File

@ -70,6 +70,28 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
hasExcludes := len(opts.Exclude) > 0 || len(opts.InsensitiveExclude) > 0
hasIncludes := len(opts.Include) > 0 || len(opts.InsensitiveInclude) > 0
// Validate provided patterns
if len(opts.Exclude) > 0 {
if valid, invalidPatterns := filter.ValidatePatterns(opts.Exclude); !valid {
return errors.Fatalf("--exclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
}
}
if len(opts.InsensitiveExclude) > 0 {
if valid, invalidPatterns := filter.ValidatePatterns(opts.InsensitiveExclude); !valid {
return errors.Fatalf("--iexclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
}
}
if len(opts.Include) > 0 {
if valid, invalidPatterns := filter.ValidatePatterns(opts.Include); !valid {
return errors.Fatalf("--include: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
}
}
if len(opts.InsensitiveInclude) > 0 {
if valid, invalidPatterns := filter.ValidatePatterns(opts.InsensitiveInclude); !valid {
return errors.Fatalf("--iinclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
}
}
for i, str := range opts.InsensitiveExclude {
opts.InsensitiveExclude[i] = strings.ToLower(str)
}

View File

@ -67,3 +67,40 @@ func TestBackupFailsWhenUsingInvalidPatternsFromFile(t *testing.T) {
*[._]log[.-][0-9]
!*[._]log[.-][0-9]`, err.Error())
}
func TestRestoreFailsWhenUsingInvalidPatterns(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
testRunInit(t, env.gopts)
var err error
// Test --exclude
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{Exclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
rtest.Equals(t, `Fatal: --exclude: invalid pattern(s) provided:
*[._]log[.-][0-9]
!*[._]log[.-][0-9]`, err.Error())
// Test --iexclude
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{InsensitiveExclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
rtest.Equals(t, `Fatal: --iexclude: invalid pattern(s) provided:
*[._]log[.-][0-9]
!*[._]log[.-][0-9]`, err.Error())
// Test --include
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{Include: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
rtest.Equals(t, `Fatal: --include: invalid pattern(s) provided:
*[._]log[.-][0-9]
!*[._]log[.-][0-9]`, err.Error())
// Test --iinclude
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{InsensitiveInclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
rtest.Equals(t, `Fatal: --iinclude: invalid pattern(s) provided:
*[._]log[.-][0-9]
!*[._]log[.-][0-9]`, err.Error())
}

View File

@ -131,6 +131,12 @@ func testRunRestoreIncludes(t testing.TB, gopts GlobalOptions, dir string, snaps
rtest.OK(t, runRestore(opts, gopts, []string{snapshotID.String()}))
}
func testRunRestoreAssumeFailure(t testing.TB, snapshotID string, opts RestoreOptions, gopts GlobalOptions) error {
err := runRestore(opts, gopts, []string{snapshotID})
return err
}
func testRunCheck(t testing.TB, gopts GlobalOptions) {
opts := CheckOptions{
ReadData: true,