third_party: Add github.com/bmatcuk/doublestar
The native Go file glob doesn't support '**' patterns for matching
any number of path components.
MultiPart: 3/3
Change-Id: Ic836555c4df1b4c85ac54874f4e9aa54740b423d
diff --git a/go/src/github.com/bmatcuk/doublestar/.gitignore b/go/src/github.com/bmatcuk/doublestar/.gitignore
new file mode 100644
index 0000000..76d92ba
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/.gitignore
@@ -0,0 +1,29 @@
+# vi
+*~
+*.swp
+*.swo
+
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/go/src/github.com/bmatcuk/doublestar/.travis.yml b/go/src/github.com/bmatcuk/doublestar/.travis.yml
new file mode 100644
index 0000000..92cf2ce
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+
+go:
+ - 1.3
+ - 1.4
+
+before_install:
+ - sudo pip install codecov
+
+script:
+ - go test -coverprofile=coverage.txt -covermode=atomic
+
+after_success:
+ - codecov
+
diff --git a/go/src/github.com/bmatcuk/doublestar/LICENSE b/go/src/github.com/bmatcuk/doublestar/LICENSE
new file mode 100644
index 0000000..309c9d1
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Bob Matcuk
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/go/src/github.com/bmatcuk/doublestar/README.google b/go/src/github.com/bmatcuk/doublestar/README.google
new file mode 100644
index 0000000..62f6d10
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/README.google
@@ -0,0 +1,10 @@
+URL: https://github.com/bmatcuk/doublestar/archive/3d7b9fdaa0003377934692e98a5d3233f11a5baa.zip
+Version: 3d7b9fdaa0003377934692e98a5d3233f11a5baa
+License: MIT
+License File: LICENSE
+
+Description:
+doublestar expands Go file globbing to match `**` (any number of path components).
+
+Local Modifications:
+Applied gofmt.
diff --git a/go/src/github.com/bmatcuk/doublestar/README.md b/go/src/github.com/bmatcuk/doublestar/README.md
new file mode 100644
index 0000000..335a793
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/README.md
@@ -0,0 +1,80 @@
+![Release](https://img.shields.io/github/release/bmatcuk/doublestar.svg?branch=master)
+[![Build Status](https://travis-ci.org/bmatcuk/doublestar.svg?branch=master)](https://travis-ci.org/bmatcuk/doublestar)
+[![codecov.io](https://img.shields.io/codecov/c/github/bmatcuk/doublestar.svg?branch=master)](https://codecov.io/github/bmatcuk/doublestar?branch=master)
+
+# doublestar
+
+**doublestar** is a [golang](http://golang.org/) implementation of path pattern matching and globbing with support for "doublestar" (aka globstar: `**`) patterns.
+
+doublestar patterns match files and directories recursively. For example, if you had the following directory structure:
+
+```
+grandparent
+`-- parent
+ |-- child1
+ `-- child2
+```
+
+You could find the children with patterns such as: `**/child*`, `grandparent/**/child?`, `**/parent/*`, or even just `**` by itself (which will return all files and directories recursively).
+
+## Installation
+
+**doublestar** can be installed via `go get`:
+
+```bash
+go get github.com/bmatcuk/doublestar
+```
+
+To use it in your code, you must import it:
+
+```go
+import "github.com/bmatcuk/doublestar"
+```
+
+## Functions
+
+### Match
+```go
+func Match(pattern, name string) (bool, error)
+```
+
+Match returns true if `name` matches the file name `pattern` ([see below](#patterns)). `name` and `pattern` are split on forward slash (`/`) characters.
+
+### PathMatch
+```go
+func PathMatch(pattern, name string) (bool, error)
+```
+
+PathMatch returns true if `name` matches the file name `pattern` ([see below](#patterns)). The difference between Match and PathMatch is that PathMatch will automatically use your system's path separator to split `name` and `pattern`.
+
+### Glob
+```go
+func Glob(pattern string) ([]string, error)
+```
+
+Glob finds all files and directories in the filesystem that match `pattern` ([see below](#patterns)).
+
+## Patterns
+
+**doublestar** supports the following special terms in the patterns:
+
+Special Terms | Meaning
+------------- | -------
+`*` | matches any sequence of non-path-separators
+`**` | matches any sequence of characters, including path separators
+`?` | matches any single non-path-separator character
+`[class]` | matches any single non-path-separator character against a class of characters ([see below](#character-classes))
+`{alt1,...}` | matches a sequence of characters if one of the comma-separated alternatives matches
+
+Any character with a special meaning can be escaped with a backslash (`\`).
+
+### Character Classes
+
+Character classes support the following:
+
+Class | Meaning
+---------- | -------
+`[abc]` | matches any single character within the set
+`[a-z]` | matches any single character in the range
+`[^class]` | matches any single character which does *not* match the class
+
diff --git a/go/src/github.com/bmatcuk/doublestar/doublestar.go b/go/src/github.com/bmatcuk/doublestar/doublestar.go
new file mode 100644
index 0000000..7256309
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/doublestar.go
@@ -0,0 +1,392 @@
+package doublestar
+
+import (
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "unicode/utf8"
+)
+
+var ErrBadPattern = path.ErrBadPattern
+
+func splitPathOnSeparator(path string, separator rune) []string {
+ // if the separator is '\\', then we can just split...
+ if separator == '\\' {
+ return strings.Split(path, string(separator))
+ }
+
+ // otherwise, we need to be careful of situations where the separator was escaped
+ cnt := strings.Count(path, string(separator))
+ if cnt == 0 {
+ return []string{path}
+ }
+ ret := make([]string, cnt+1)
+ pathlen := len(path)
+ separatorLen := utf8.RuneLen(separator)
+ idx := 0
+ for start := 0; start < pathlen; {
+ end := indexRuneWithEscaping(path[start:], separator)
+ if end == -1 {
+ end = pathlen
+ } else {
+ end += start
+ }
+ ret[idx] = path[start:end]
+ start = end + separatorLen
+ idx++
+ }
+ return ret[:idx]
+}
+
+func indexRuneWithEscaping(s string, r rune) int {
+ end := strings.IndexRune(s, r)
+ if end == -1 {
+ return -1
+ }
+ if end > 0 && s[end-1] == '\\' {
+ start := end + utf8.RuneLen(r)
+ end = indexRuneWithEscaping(s[start:], r)
+ if end != -1 {
+ end += start
+ }
+ }
+ return end
+}
+
+// Match returns true if name matches the shell file name pattern.
+// The pattern syntax is:
+//
+// pattern:
+// { term }
+// term:
+// '*' matches any sequence of non-path-separators
+// '**' matches any sequence of characters, including
+// path separators.
+// '?' matches any single non-path-separator character
+// '[' [ '^' ] { character-range } ']'
+// character class (must be non-empty)
+// '{' { term } [ ',' { term } ... ] '}'
+// c matches character c (c != '*', '?', '\\', '[')
+// '\\' c matches character c
+//
+// character-range:
+// c matches character c (c != '\\', '-', ']')
+// '\\' c matches character c
+// lo '-' hi matches character c for lo <= c <= hi
+//
+// Match requires pattern to match all of name, not just a substring.
+// The path-separator defaults to the '/' character. The only possible
+// returned error is ErrBadPattern, when pattern is malformed.
+//
+func Match(pattern, name string) (bool, error) {
+ return matchWithSeparator(pattern, name, '/')
+}
+
+// PathMatch is like Match except that it uses your system's path separator.
+// For most systems, this will be '/'. However, for Windows, it would be '\\'.
+// Note that for systems where the path separator is '\\', escaping is
+// disabled.
+//
+func PathMatch(pattern, name string) (bool, error) {
+ return matchWithSeparator(pattern, name, os.PathSeparator)
+}
+
+// Match returns true if name matches the shell file name pattern.
+// The pattern syntax is:
+//
+// pattern:
+// { term }
+// term:
+// '*' matches any sequence of non-path-separators
+// '**' matches any sequence of characters, including
+// path separators.
+// '?' matches any single non-path-separator character
+// '[' [ '^' ] { character-range } ']'
+// character class (must be non-empty)
+// '{' { term } [ ',' { term } ... ] '}'
+// c matches character c (c != '*', '?', '\\', '[')
+// '\\' c matches character c
+//
+// character-range:
+// c matches character c (c != '\\', '-', ']')
+// '\\' c matches character c, unless separator is '\\'
+// lo '-' hi matches character c for lo <= c <= hi
+//
+// Match requires pattern to match all of name, not just a substring.
+// The only possible returned error is ErrBadPattern, when pattern
+// is malformed.
+//
+func matchWithSeparator(pattern, name string, separator rune) (bool, error) {
+ patternComponents := splitPathOnSeparator(pattern, separator)
+ nameComponents := splitPathOnSeparator(name, separator)
+ return doMatching(patternComponents, nameComponents)
+}
+
+func doMatching(patternComponents, nameComponents []string) (matched bool, err error) {
+ patternLen, nameLen := len(patternComponents), len(nameComponents)
+ if patternLen == 0 && nameLen == 0 {
+ return true, nil
+ }
+ if patternLen == 0 || nameLen == 0 {
+ return false, nil
+ }
+ patIdx, nameIdx := 0, 0
+ for patIdx < patternLen && nameIdx < nameLen {
+ if patternComponents[patIdx] == "**" {
+ if patIdx++; patIdx >= patternLen {
+ return true, nil
+ }
+ for ; nameIdx < nameLen; nameIdx++ {
+ if m, _ := doMatching(patternComponents[patIdx:], nameComponents[nameIdx:]); m {
+ return true, nil
+ }
+ }
+ return false, nil
+ } else {
+ matched, err = matchComponent(patternComponents[patIdx], nameComponents[nameIdx])
+ if !matched || err != nil {
+ return
+ }
+ }
+ patIdx++
+ nameIdx++
+ }
+ return patIdx >= patternLen && nameIdx >= nameLen, nil
+}
+
+// Glob returns the names of all files matching pattern or nil
+// if there is no matching file. The syntax of pattern is the same
+// as in Match. The pattern may describe hierarchical names such as
+// /usr/*/bin/ed (assuming the Separator is '/').
+//
+// Glob ignores file system errors such as I/O errors reading directories.
+// The only possible returned error is ErrBadPattern, when pattern
+// is malformed.
+//
+// Your system path separator is automatically used. This means on
+// systems where the separator is '\\' (Windows), escaping will be
+// disabled.
+//
+func Glob(pattern string) (matches []string, err error) {
+ patternComponents := splitPathOnSeparator(pattern, os.PathSeparator)
+ if len(patternComponents) == 0 {
+ return nil, nil
+ }
+
+ // if the first pattern component is blank, the pattern is an absolute path.
+ if patternComponents[0] == "" {
+ return doGlob("", patternComponents, matches)
+ }
+ return doGlob(".", patternComponents, matches)
+}
+
+func doGlob(basedir string, components, matches []string) (m []string, e error) {
+ m = matches
+ e = nil
+
+ // figure out how many components we don't need to glob because they're
+ // just straight directory names
+ patLen := len(components)
+ patIdx := 0
+ for ; patIdx < patLen; patIdx++ {
+ if strings.IndexAny(components[patIdx], "*?[{\\") >= 0 {
+ break
+ }
+ }
+ if patIdx > 0 {
+ basedir = filepath.Join(basedir, filepath.Join(components[0:patIdx]...))
+ }
+
+ // Stat will return an error if the file/directory doesn't exist
+ fi, err := os.Stat(basedir)
+ if err != nil {
+ return
+ }
+
+ // if there are no more components, we've found a match
+ if patIdx >= patLen {
+ m = append(m, basedir)
+ return
+ }
+
+ // otherwise, we need to check each item in the directory...
+ // so confirm it's a directory first...
+ if !fi.IsDir() {
+ return
+ }
+
+ // read directory
+ dir, err := os.Open(basedir)
+ if err != nil {
+ return
+ }
+ defer dir.Close()
+
+ files, _ := dir.Readdir(-1)
+ lastComponent := patIdx+1 >= patLen
+ if components[patIdx] == "**" {
+ // if the current component is a doublestar, we'll try depth-first
+ for _, file := range files {
+ if file.IsDir() {
+ m = append(m, filepath.Join(basedir, file.Name()))
+ m, e = doGlob(filepath.Join(basedir, file.Name()), components[patIdx:], m)
+ } else if lastComponent {
+ // if the pattern's last component is a doublestar, we match filenames, too
+ m = append(m, filepath.Join(basedir, file.Name()))
+ }
+ }
+ if lastComponent {
+ return
+ }
+ patIdx++
+ lastComponent = patIdx+1 >= patLen
+ }
+
+ var match bool
+ for _, file := range files {
+ match, e = matchComponent(components[patIdx], file.Name())
+ if e != nil {
+ return
+ }
+ if match {
+ if lastComponent {
+ m = append(m, filepath.Join(basedir, file.Name()))
+ } else {
+ m, e = doGlob(filepath.Join(basedir, file.Name()), components[patIdx+1:], m)
+ }
+ }
+ }
+ return
+}
+
+func matchComponent(pattern, name string) (bool, error) {
+ patternLen, nameLen := len(pattern), len(name)
+ if patternLen == 0 && nameLen == 0 {
+ return true, nil
+ }
+ if patternLen == 0 {
+ return false, nil
+ }
+ if nameLen == 0 && pattern != "*" {
+ return false, nil
+ }
+ patIdx, nameIdx := 0, 0
+ for patIdx < patternLen && nameIdx < nameLen {
+ patRune, patAdj := utf8.DecodeRuneInString(pattern[patIdx:])
+ nameRune, nameAdj := utf8.DecodeRuneInString(name[nameIdx:])
+ if patRune == '\\' {
+ patIdx += patAdj
+ patRune, patAdj = utf8.DecodeRuneInString(pattern[patIdx:])
+ if patRune == utf8.RuneError {
+ return false, ErrBadPattern
+ } else if patRune == nameRune {
+ patIdx += patAdj
+ nameIdx += nameAdj
+ } else {
+ return false, nil
+ }
+ } else if patRune == '*' {
+ if patIdx += patAdj; patIdx >= patternLen {
+ return true, nil
+ }
+ for ; nameIdx < nameLen; nameIdx += nameAdj {
+ if m, _ := matchComponent(pattern[patIdx:], name[nameIdx:]); m {
+ return true, nil
+ }
+ }
+ return false, nil
+ } else if patRune == '[' {
+ patIdx += patAdj
+ endClass := indexRuneWithEscaping(pattern[patIdx:], ']')
+ if endClass == -1 {
+ return false, ErrBadPattern
+ }
+ endClass += patIdx
+ classRunes := []rune(pattern[patIdx:endClass])
+ classRunesLen := len(classRunes)
+ if classRunesLen > 0 {
+ classIdx := 0
+ matchClass := false
+ if classRunes[0] == '^' {
+ classIdx++
+ }
+ for classIdx < classRunesLen {
+ low := classRunes[classIdx]
+ if low == '-' {
+ return false, ErrBadPattern
+ }
+ classIdx++
+ if low == '\\' {
+ if classIdx < classRunesLen {
+ low = classRunes[classIdx]
+ classIdx++
+ } else {
+ return false, ErrBadPattern
+ }
+ }
+ high := low
+ if classIdx < classRunesLen && classRunes[classIdx] == '-' {
+ if classIdx++; classIdx >= classRunesLen {
+ return false, ErrBadPattern
+ }
+ high = classRunes[classIdx]
+ if high == '-' {
+ return false, ErrBadPattern
+ }
+ classIdx++
+ if high == '\\' {
+ if classIdx < classRunesLen {
+ high = classRunes[classIdx]
+ classIdx++
+ } else {
+ return false, ErrBadPattern
+ }
+ }
+ }
+ if low <= nameRune && nameRune <= high {
+ matchClass = true
+ }
+ }
+ if matchClass == (classRunes[0] == '^') {
+ return false, nil
+ }
+ } else {
+ return false, ErrBadPattern
+ }
+ patIdx = endClass + 1
+ nameIdx += nameAdj
+ } else if patRune == '{' {
+ patIdx += patAdj
+ endOptions := indexRuneWithEscaping(pattern[patIdx:], '}')
+ if endOptions == -1 {
+ return false, ErrBadPattern
+ }
+ endOptions += patIdx
+ options := splitPathOnSeparator(pattern[patIdx:endOptions], ',')
+ patIdx = endOptions + 1
+ for _, o := range options {
+ m, e := matchComponent(o+pattern[patIdx:], name[nameIdx:])
+ if e != nil {
+ return false, e
+ }
+ if m {
+ return true, nil
+ }
+ }
+ return false, nil
+ } else if patRune == '?' || patRune == nameRune {
+ patIdx += patAdj
+ nameIdx += nameAdj
+ } else {
+ return false, nil
+ }
+ }
+ if patIdx >= patternLen && nameIdx >= nameLen {
+ return true, nil
+ }
+ if nameIdx >= nameLen && pattern[patIdx:] == "*" {
+ return true, nil
+ }
+ return false, nil
+}
diff --git a/go/src/github.com/bmatcuk/doublestar/doublestar_test.go b/go/src/github.com/bmatcuk/doublestar/doublestar_test.go
new file mode 100644
index 0000000..d931da3
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/doublestar_test.go
@@ -0,0 +1,139 @@
+// This file is mostly copied from Go's path/match_test.go
+
+package doublestar
+
+import "testing"
+
+type MatchTest struct {
+ pattern, s string
+ match bool
+ err error
+ testGlob bool
+}
+
+var matchTests = []MatchTest{
+ {"abc", "abc", true, nil, true},
+ {"*", "abc", true, nil, true},
+ {"*c", "abc", true, nil, true},
+ {"a*", "a", true, nil, true},
+ {"a*", "abc", true, nil, true},
+ {"a*", "ab/c", false, nil, true},
+ {"a*/b", "abc/b", true, nil, true},
+ {"a*/b", "a/c/b", false, nil, true},
+ {"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil, true},
+ {"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil, true},
+ {"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil, true},
+ {"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil, true},
+ {"a*b?c*x", "abxbbxdbxebxczzx", true, nil, true},
+ {"a*b?c*x", "abxbbxdbxebxczzy", false, nil, true},
+ {"ab[c]", "abc", true, nil, true},
+ {"ab[b-d]", "abc", true, nil, true},
+ {"ab[e-g]", "abc", false, nil, true},
+ {"ab[^c]", "abc", false, nil, true},
+ {"ab[^b-d]", "abc", false, nil, true},
+ {"ab[^e-g]", "abc", true, nil, true},
+ {"a\\*b", "a*b", true, nil, true},
+ {"a\\*b", "ab", false, nil, true},
+ {"a?b", "a☺b", true, nil, true},
+ {"a[^a]b", "a☺b", true, nil, true},
+ {"a???b", "a☺b", false, nil, true},
+ {"a[^a][^a][^a]b", "a☺b", false, nil, true},
+ {"[a-ζ]*", "α", true, nil, true},
+ {"*[a-ζ]", "A", false, nil, true},
+ {"a?b", "a/b", false, nil, true},
+ {"a*b", "a/b", false, nil, true},
+ {"[\\]a]", "]", true, nil, true},
+ {"[\\-]", "-", true, nil, true},
+ {"[x\\-]", "x", true, nil, true},
+ {"[x\\-]", "-", true, nil, true},
+ {"[x\\-]", "z", false, nil, true},
+ {"[\\-x]", "x", true, nil, true},
+ {"[\\-x]", "-", true, nil, true},
+ {"[\\-x]", "a", false, nil, true},
+ {"[]a]", "]", false, ErrBadPattern, true},
+ {"[-]", "-", false, ErrBadPattern, true},
+ {"[x-]", "x", false, ErrBadPattern, true},
+ {"[x-]", "-", false, ErrBadPattern, true},
+ {"[x-]", "z", false, ErrBadPattern, true},
+ {"[-x]", "x", false, ErrBadPattern, true},
+ {"[-x]", "-", false, ErrBadPattern, true},
+ {"[-x]", "a", false, ErrBadPattern, true},
+ {"\\", "a", false, ErrBadPattern, true},
+ {"[a-b-c]", "a", false, ErrBadPattern, true},
+ {"[", "a", false, ErrBadPattern, true},
+ {"[^", "a", false, ErrBadPattern, true},
+ {"[^bc", "a", false, ErrBadPattern, true},
+ {"a[", "a", false, nil, false},
+ {"a[", "ab", false, ErrBadPattern, true},
+ {"*x", "xxx", true, nil, true},
+ {"a/**", "a", false, nil, true},
+ {"a/**", "a/b", true, nil, true},
+ {"a/**", "a/b/c", true, nil, true},
+ {"**/c", "c", true, nil, true},
+ {"**/c", "b/c", true, nil, true},
+ {"**/c", "a/b/c", true, nil, true},
+ {"a/**/b", "a/b", true, nil, true},
+ {"a/**/c", "a/b/c", true, nil, true},
+ {"a/**/d", "a/b/c/d", true, nil, true},
+ {"a/\\**", "a/b/c", false, nil, true},
+ {"a/\\**", "a/*", true, nil, true},
+ {"ab{c,d}", "abc", true, nil, true},
+ {"ab{c,d,*}", "abcde", true, nil, true},
+ {"ab{c,d}[", "abcd", false, ErrBadPattern, true},
+}
+
+func TestMatch(t *testing.T) {
+ for idx, tt := range matchTests {
+ testMatchWith(t, idx, tt)
+ }
+}
+
+func testMatchWith(t *testing.T, idx int, tt MatchTest) {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Errorf("#%v. Match(%#q, %#q) panicked: %#v", idx, tt.pattern, tt.s, r)
+ }
+ }()
+
+ ok, err := Match(tt.pattern, tt.s)
+ if ok != tt.match || err != tt.err {
+ t.Errorf("#%v. Match(%#q, %#q) = %v, %v want %v, %v", idx, tt.pattern, tt.s, ok, err, tt.match, tt.err)
+ }
+}
+
+func TestGlob(t *testing.T) {
+ for idx, tt := range matchTests {
+ if tt.testGlob {
+ testGlobWith(t, idx, tt)
+ }
+ }
+}
+
+func testGlobWith(t *testing.T, idx int, tt MatchTest) {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Errorf("#%v. Glob(%#q) panicked: %#v", idx, tt.pattern, r)
+ }
+ }()
+
+ matches, err := Glob("test/" + tt.pattern)
+ if inSlice("test/"+tt.s, matches) != tt.match {
+ if tt.match {
+ t.Errorf("#%v. Glob(%#q) = %#v - doesn't contain %v, but should", idx, tt.pattern, matches, tt.s)
+ } else {
+ t.Errorf("#%v. Glob(%#q) = %#v - contains %v, but shouldn't", idx, tt.pattern, matches, tt.s)
+ }
+ }
+ if err != tt.err {
+ t.Errorf("#%v. Glob(%#q) has error %v, but should be %v", idx, tt.pattern, err, tt.err)
+ }
+}
+
+func inSlice(s string, a []string) bool {
+ for _, i := range a {
+ if i == s {
+ return true
+ }
+ }
+ return false
+}
diff --git a/go/src/github.com/bmatcuk/doublestar/test/- b/go/src/github.com/bmatcuk/doublestar/test/-
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/-
diff --git a/go/src/github.com/bmatcuk/doublestar/test/README.md b/go/src/github.com/bmatcuk/doublestar/test/README.md
new file mode 100644
index 0000000..7312628
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/README.md
@@ -0,0 +1 @@
+This directory and associated subdirectories and files are for testing the Glob() function.
diff --git "a/go/src/github.com/bmatcuk/doublestar/test/\135" "b/go/src/github.com/bmatcuk/doublestar/test/\135"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/go/src/github.com/bmatcuk/doublestar/test/\135"
diff --git a/go/src/github.com/bmatcuk/doublestar/test/a*b b/go/src/github.com/bmatcuk/doublestar/test/a*b
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/a*b
diff --git a/go/src/github.com/bmatcuk/doublestar/test/a/* b/go/src/github.com/bmatcuk/doublestar/test/a/*
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/a/*
diff --git a/go/src/github.com/bmatcuk/doublestar/test/a/b/c/d b/go/src/github.com/bmatcuk/doublestar/test/a/b/c/d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/a/b/c/d
diff --git a/go/src/github.com/bmatcuk/doublestar/test/a/c/b b/go/src/github.com/bmatcuk/doublestar/test/a/c/b
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/a/c/b
diff --git a/go/src/github.com/bmatcuk/doublestar/test/abc/b b/go/src/github.com/bmatcuk/doublestar/test/abc/b
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/abc/b
diff --git a/go/src/github.com/bmatcuk/doublestar/test/abcd b/go/src/github.com/bmatcuk/doublestar/test/abcd
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/abcd
diff --git a/go/src/github.com/bmatcuk/doublestar/test/abcde b/go/src/github.com/bmatcuk/doublestar/test/abcde
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/abcde
diff --git a/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzx b/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzx
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzx
diff --git a/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzy b/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/abxbbxdbxebxczzy
diff --git a/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/f b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/f
diff --git a/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/xxx/f b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/xxx/f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxe/xxx/f
diff --git a/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/f b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/f
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/f
diff --git a/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/fff b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/fff
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/axbxcxdxexxx/fff
diff --git "a/go/src/github.com/bmatcuk/doublestar/test/a\342\230\272b" "b/go/src/github.com/bmatcuk/doublestar/test/a\342\230\272b"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/go/src/github.com/bmatcuk/doublestar/test/a\342\230\272b"
diff --git a/go/src/github.com/bmatcuk/doublestar/test/b/c b/go/src/github.com/bmatcuk/doublestar/test/b/c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/b/c
diff --git a/go/src/github.com/bmatcuk/doublestar/test/c b/go/src/github.com/bmatcuk/doublestar/test/c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/c
diff --git a/go/src/github.com/bmatcuk/doublestar/test/x b/go/src/github.com/bmatcuk/doublestar/test/x
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/x
diff --git a/go/src/github.com/bmatcuk/doublestar/test/xxx b/go/src/github.com/bmatcuk/doublestar/test/xxx
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/xxx
diff --git a/go/src/github.com/bmatcuk/doublestar/test/z b/go/src/github.com/bmatcuk/doublestar/test/z
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/go/src/github.com/bmatcuk/doublestar/test/z
diff --git "a/go/src/github.com/bmatcuk/doublestar/test/\316\261" "b/go/src/github.com/bmatcuk/doublestar/test/\316\261"
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ "b/go/src/github.com/bmatcuk/doublestar/test/\316\261"