Commit 2ef4a840 authored by Alex Brainman's avatar Alex Brainman

path/filepath: implement Match and Glob on windows

As discussed on golang-dev, windows will use
"\" as path separator. No escaping allowed.

R=golang-dev, r, mattn.jp, rsc, rogpeppe, bsiegert, r
CC=golang-dev
https://golang.org/cl/5825044
parent 6230569e
...@@ -7,6 +7,7 @@ package filepath ...@@ -7,6 +7,7 @@ package filepath
import ( import (
"errors" "errors"
"os" "os"
"runtime"
"sort" "sort"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
...@@ -37,6 +38,9 @@ var ErrBadPattern = errors.New("syntax error in pattern") ...@@ -37,6 +38,9 @@ var ErrBadPattern = errors.New("syntax error in pattern")
// The only possible returned error is ErrBadPattern, when pattern // The only possible returned error is ErrBadPattern, when pattern
// is malformed. // is malformed.
// //
// On Windows, escaping is disabled. Instead, '\\' is treated as
// path separator.
//
func Match(pattern, name string) (matched bool, err error) { func Match(pattern, name string) (matched bool, err error) {
Pattern: Pattern:
for len(pattern) > 0 { for len(pattern) > 0 {
...@@ -95,10 +99,12 @@ Scan: ...@@ -95,10 +99,12 @@ Scan:
for i = 0; i < len(pattern); i++ { for i = 0; i < len(pattern); i++ {
switch pattern[i] { switch pattern[i] {
case '\\': case '\\':
if runtime.GOOS != "windows" {
// error check handled in matchChunk: bad pattern. // error check handled in matchChunk: bad pattern.
if i+1 < len(pattern) { if i+1 < len(pattern) {
i++ i++
} }
}
case '[': case '[':
inrange = true inrange = true
case ']': case ']':
...@@ -167,11 +173,13 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) { ...@@ -167,11 +173,13 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) {
chunk = chunk[1:] chunk = chunk[1:]
case '\\': case '\\':
if runtime.GOOS != "windows" {
chunk = chunk[1:] chunk = chunk[1:]
if len(chunk) == 0 { if len(chunk) == 0 {
err = ErrBadPattern err = ErrBadPattern
return return
} }
}
fallthrough fallthrough
default: default:
...@@ -191,7 +199,7 @@ func getEsc(chunk string) (r rune, nchunk string, err error) { ...@@ -191,7 +199,7 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
err = ErrBadPattern err = ErrBadPattern
return return
} }
if chunk[0] == '\\' { if chunk[0] == '\\' && runtime.GOOS != "windows" {
chunk = chunk[1:] chunk = chunk[1:]
if len(chunk) == 0 { if len(chunk) == 0 {
err = ErrBadPattern err = ErrBadPattern
......
...@@ -7,6 +7,7 @@ package filepath_test ...@@ -7,6 +7,7 @@ package filepath_test
import ( import (
. "path/filepath" . "path/filepath"
"runtime" "runtime"
"strings"
"testing" "testing"
) )
...@@ -76,21 +77,26 @@ func errp(e error) string { ...@@ -76,21 +77,26 @@ func errp(e error) string {
} }
func TestMatch(t *testing.T) { func TestMatch(t *testing.T) {
for _, tt := range matchTests {
pattern := tt.pattern
s := tt.s
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// XXX: Don't pass for windows. if strings.Index(pattern, "\\") >= 0 {
return // no escape allowed on windows.
continue
} }
for _, tt := range matchTests { pattern = Clean(pattern)
ok, err := Match(tt.pattern, tt.s) s = Clean(s)
}
ok, err := Match(pattern, s)
if ok != tt.match || err != tt.err { if ok != tt.match || err != tt.err {
t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err)) t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
} }
} }
} }
// contains returns true if vector contains the string s. // contains returns true if vector contains the string s.
func contains(vector []string, s string) bool { func contains(vector []string, s string) bool {
s = ToSlash(s)
for _, elem := range vector { for _, elem := range vector {
if elem == s { if elem == s {
return true return true
...@@ -109,18 +115,20 @@ var globTests = []struct { ...@@ -109,18 +115,20 @@ var globTests = []struct {
} }
func TestGlob(t *testing.T) { func TestGlob(t *testing.T) {
for _, tt := range globTests {
pattern := tt.pattern
result := tt.result
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// XXX: Don't pass for windows. pattern = Clean(pattern)
return result = Clean(result)
} }
for _, tt := range globTests { matches, err := Glob(pattern)
matches, err := Glob(tt.pattern)
if err != nil { if err != nil {
t.Errorf("Glob error for %q: %s", tt.pattern, err) t.Errorf("Glob error for %q: %s", pattern, err)
continue continue
} }
if !contains(matches, tt.result) { if !contains(matches, result) {
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result) t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
} }
} }
for _, pattern := range []string{"no_match", "../*/no_match"} { for _, pattern := range []string{"no_match", "../*/no_match"} {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment