mirror of
https://github.com/golang/go
synced 2024-11-25 07:07:57 -07:00
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
This commit is contained in:
parent
6230569e84
commit
2ef4a84022
@ -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")
|
|||||||
// 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,9 +99,11 @@ Scan:
|
|||||||
for i = 0; i < len(pattern); i++ {
|
for i = 0; i < len(pattern); i++ {
|
||||||
switch pattern[i] {
|
switch pattern[i] {
|
||||||
case '\\':
|
case '\\':
|
||||||
// error check handled in matchChunk: bad pattern.
|
if runtime.GOOS != "windows" {
|
||||||
if i+1 < len(pattern) {
|
// error check handled in matchChunk: bad pattern.
|
||||||
i++
|
if i+1 < len(pattern) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
inrange = true
|
inrange = true
|
||||||
@ -167,10 +173,12 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) {
|
|||||||
chunk = chunk[1:]
|
chunk = chunk[1:]
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
chunk = chunk[1:]
|
if runtime.GOOS != "windows" {
|
||||||
if len(chunk) == 0 {
|
chunk = chunk[1:]
|
||||||
err = ErrBadPattern
|
if len(chunk) == 0 {
|
||||||
return
|
err = ErrBadPattern
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
@ -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
|
|||||||
import (
|
import (
|
||||||
. "path/filepath"
|
. "path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,21 +77,26 @@ func errp(e error) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMatch(t *testing.T) {
|
func TestMatch(t *testing.T) {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// XXX: Don't pass for windows.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, tt := range matchTests {
|
for _, tt := range matchTests {
|
||||||
ok, err := Match(tt.pattern, tt.s)
|
pattern := tt.pattern
|
||||||
|
s := tt.s
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if strings.Index(pattern, "\\") >= 0 {
|
||||||
|
// no escape allowed on windows.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pattern = Clean(pattern)
|
||||||
|
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGlob(t *testing.T) {
|
func TestGlob(t *testing.T) {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// XXX: Don't pass for windows.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, tt := range globTests {
|
for _, tt := range globTests {
|
||||||
matches, err := Glob(tt.pattern)
|
pattern := tt.pattern
|
||||||
|
result := tt.result
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
pattern = Clean(pattern)
|
||||||
|
result = Clean(result)
|
||||||
|
}
|
||||||
|
matches, err := Glob(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"} {
|
||||||
|
Loading…
Reference in New Issue
Block a user