diff --git a/archive.go b/archive.go index 7cb3bb5..5b8dc22 100644 --- a/archive.go +++ b/archive.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" + "github.com/fujiwara/lambroll/wildcard" "github.com/pkg/errors" ) @@ -65,14 +66,8 @@ func createZipArchive(src string, excludes []string) (*os.File, os.FileInfo, err func matchExcludes(path string, excludes []string) bool { for _, pattern := range excludes { - for _, name := range []string{path, filepath.Base(path)} { - m, err := filepath.Match(pattern, name) - if err != nil { - log.Printf("[warn] failed to match exclude pattern %s to %s", pattern, name) - } - if m { - return true - } + if wildcard.Match(pattern, path) { + return true } } return false diff --git a/test/src/skip/subdir/subfile.txt b/test/src/skip/subdir/subfile.txt new file mode 100644 index 0000000..e69de29 diff --git a/wildcard/match.go b/wildcard/match.go new file mode 100644 index 0000000..a26b2f2 --- /dev/null +++ b/wildcard/match.go @@ -0,0 +1,83 @@ +/* + * MinIO Cloud Storage, (C) 2015, 2016 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package wildcard + +// MatchSimple - finds whether the text matches/satisfies the pattern string. +// supports only '*' wildcard in the pattern. +// considers a file system path as a flat name space. +func MatchSimple(pattern, name string) bool { + if pattern == "" { + return name == pattern + } + if pattern == "*" { + return true + } + rname := make([]rune, 0, len(name)) + rpattern := make([]rune, 0, len(pattern)) + for _, r := range name { + rname = append(rname, r) + } + for _, r := range pattern { + rpattern = append(rpattern, r) + } + simple := true // Does only wildcard '*' match. + return deepMatchRune(rname, rpattern, simple) +} + +// Match - finds whether the text matches/satisfies the pattern string. +// supports '*' and '?' wildcards in the pattern string. +// unlike path.Match(), considers a path as a flat name space while matching the pattern. +// The difference is illustrated in the example here https://play.golang.org/p/Ega9qgD4Qz . +func Match(pattern, name string) (matched bool) { + if pattern == "" { + return name == pattern + } + if pattern == "*" { + return true + } + rname := make([]rune, 0, len(name)) + rpattern := make([]rune, 0, len(pattern)) + for _, r := range name { + rname = append(rname, r) + } + for _, r := range pattern { + rpattern = append(rpattern, r) + } + simple := false // Does extended wildcard '*' and '?' match. + return deepMatchRune(rname, rpattern, simple) +} + +func deepMatchRune(str, pattern []rune, simple bool) bool { + for len(pattern) > 0 { + switch pattern[0] { + default: + if len(str) == 0 || str[0] != pattern[0] { + return false + } + case '?': + if len(str) == 0 && !simple { + return false + } + case '*': + return deepMatchRune(str, pattern[1:], simple) || + (len(str) > 0 && deepMatchRune(str[1:], pattern, simple)) + } + str = str[1:] + pattern = pattern[1:] + } + return len(str) == 0 && len(pattern) == 0 +}