Skip to content

Commit

Permalink
Escape with backslash
Browse files Browse the repository at this point in the history
Fixes #33
  • Loading branch information
mattn committed Oct 12, 2020
1 parent 61bc16a commit 2fcc2a7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 18 deletions.
49 changes: 42 additions & 7 deletions zglob.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package zglob

import (
"bytes"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
Expand All @@ -25,15 +27,35 @@ type zenv struct {
root string
}

func toSlash(path string) string {
if filepath.Separator == '/' {
return path
}
var buf bytes.Buffer
cc := []rune(path)
for i := 0; i < len(cc); i++ {
if i < len(cc)-2 && cc[i] == '\\' && (cc[i+1] == '{' || cc[i+1] == '}') {
buf.WriteRune(cc[i])
buf.WriteRune(cc[i+1])
i++
} else if cc[i] == '\\' {
buf.WriteRune('/')
} else {
buf.WriteRune(cc[i])
}
}
return buf.String()
}

func New(pattern string) (*zenv, error) {
globmask := ""
root := ""
for n, i := range strings.Split(filepath.ToSlash(pattern), "/") {
for n, i := range strings.Split(toSlash(pattern), "/") {
if root == "" && (strings.Index(i, "*") != -1 || strings.Index(i, "{") != -1) {
if globmask == "" {
root = "."
} else {
root = filepath.ToSlash(globmask)
root = toSlash(globmask)
}
}
if n == 0 && i == "~" {
Expand All @@ -47,7 +69,7 @@ func New(pattern string) (*zenv, error) {
i = strings.Trim(strings.Trim(os.Getenv(i[1:]), "()"), `"`)
}

globmask = filepath.Join(globmask, i)
globmask = path.Join(globmask, i)
if n == 0 {
if runtime.GOOS == "windows" && filepath.VolumeName(i) != "" {
globmask = i + "/"
Expand All @@ -67,14 +89,18 @@ func New(pattern string) (*zenv, error) {
if globmask == "" {
globmask = "."
}
globmask = filepath.ToSlash(filepath.Clean(globmask))
globmask = toSlash(path.Clean(globmask))

cc := []rune(globmask)
dirmask := ""
filemask := ""
braceDir := false
lastSlash := -1
for i := 0; i < len(cc); i++ {
if cc[i] == '*' {
if i < len(cc)-2 && cc[i] == '\\' {
i++
filemask += fmt.Sprintf("[\\x%02X]", cc[i])
} else if cc[i] == '*' {
if i < len(cc)-2 && cc[i+1] == '*' && cc[i+2] == '/' {
filemask += "(.*/)?"
if dirmask == "" {
Expand All @@ -96,7 +122,10 @@ func New(pattern string) (*zenv, error) {
break
} else {
c := cc[j]
if c == '/' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 255 < c {
if c == '/' {
pattern += string(c)
lastSlash = len(filemask)
} else if ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 255 < c {
pattern += string(c)
} else {
pattern += fmt.Sprintf("[\\x%02X]", c)
Expand All @@ -109,7 +138,10 @@ func New(pattern string) (*zenv, error) {
}
}
c := cc[i]
if c == '/' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 255 < c {
if c == '/' {
filemask += string(c)
lastSlash = len(filemask)
} else if ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 255 < c {
filemask += string(c)
} else {
filemask += fmt.Sprintf("[\\x%02X]", c)
Expand All @@ -121,6 +153,9 @@ func New(pattern string) (*zenv, error) {
}
if dirmask == "" {
dirmask = filemask
if lastSlash != -1 {
dirmask = dirmask[:lastSlash]
}
}
if len(filemask) > 0 && filemask[len(filemask)-1] == '/' {
if root == "" {
Expand Down
32 changes: 21 additions & 11 deletions zglob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package zglob
import (
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"sort"
Expand Down Expand Up @@ -42,6 +43,13 @@ var testGlobs = []testZGlob{
{`**/bar/**/*.{jpg,png}`, []string{`zzz/bar/baz/joo.png`, `zzz/bar/baz/zoo.jpg`}, nil},
{`zzz/bar/baz/zoo.{jpg,png}`, []string{`zzz/bar/baz/zoo.jpg`}, nil},
{`zzz/bar/{baz,z}/zoo.jpg`, []string{`zzz/bar/baz/zoo.jpg`}, nil},
{`zzz/nar/\{noo,x\}/joo.png`, []string{`zzz/nar/{noo,x}/joo.png`}, nil},
}

func fatalIf(err error) {
if err != nil {
panic(err.Error())
}
}

func setup(t *testing.T) string {
Expand All @@ -50,16 +58,18 @@ func setup(t *testing.T) string {
t.Fatal(err)
}

os.MkdirAll(filepath.Join(tmpdir, "foo/baz"), 0755)
os.MkdirAll(filepath.Join(tmpdir, "foo/bar"), 0755)
ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz.txt"), []byte{}, 0644)
os.MkdirAll(filepath.Join(tmpdir, "foo/bar/baz"), 0755)
ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz/noo.txt"), []byte{}, 0644)
os.MkdirAll(filepath.Join(tmpdir, "hoo/bar"), 0755)
ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz.txt"), []byte{}, 0644)
os.MkdirAll(filepath.Join(tmpdir, "zzz/bar/baz"), 0755)
ioutil.WriteFile(filepath.Join(tmpdir, "zzz/bar/baz/zoo.jpg"), []byte{}, 0644)
ioutil.WriteFile(filepath.Join(tmpdir, "zzz/bar/baz/joo.png"), []byte{}, 0644)
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "foo/baz"), 0755))
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "foo/bar"), 0755))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz.txt"), []byte{}, 0644))
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "foo/bar/baz"), 0755))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz/noo.txt"), []byte{}, 0644))
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "hoo/bar"), 0755))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "foo/bar/baz.txt"), []byte{}, 0644))
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "zzz/bar/baz"), 0755))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "zzz/bar/baz/zoo.jpg"), []byte{}, 0644))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "zzz/bar/baz/joo.png"), []byte{}, 0644))
fatalIf(os.MkdirAll(filepath.Join(tmpdir, "zzz/nar/{noo,x}"), 0755))
fatalIf(ioutil.WriteFile(filepath.Join(tmpdir, "zzz/nar/{noo,x}/joo.png"), []byte{}, 0644))

return tmpdir
}
Expand Down Expand Up @@ -112,7 +122,7 @@ func TestGlobAbs(t *testing.T) {
defer os.Chdir(curdir)

for _, test := range testGlobs {
pattern := filepath.ToSlash(filepath.Join(tmpdir, test.pattern))
pattern := toSlash(path.Join(tmpdir, test.pattern))
expected := make([]string, len(test.expected))
for i, e := range test.expected {
expected[i] = filepath.ToSlash(filepath.Join(tmpdir, e))
Expand Down

0 comments on commit 2fcc2a7

Please sign in to comment.