mirror of https://github.com/golang/go.git
path/filepath: fix globbing of c:\*dir\... pattern
The problem was introduced by the recent filepath.Join change. Fixes #14949 Change-Id: I7ee52f210e12bbb1369e308e584ddb2c7766e095 Reviewed-on: https://go-review.googlesource.com/23240 TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
b5d18b50ac
commit
99d29d5a43
|
|
@ -240,13 +240,10 @@ func Glob(pattern string) (matches []string, err error) {
|
|||
}
|
||||
|
||||
dir, file := Split(pattern)
|
||||
switch dir {
|
||||
case "":
|
||||
dir = "."
|
||||
case string(Separator):
|
||||
// nothing
|
||||
default:
|
||||
dir = dir[0 : len(dir)-1] // chop off trailing separator
|
||||
if runtime.GOOS == "windows" {
|
||||
dir = cleanGlobPathWindows(dir)
|
||||
} else {
|
||||
dir = cleanGlobPath(dir)
|
||||
}
|
||||
|
||||
if !hasMeta(dir) {
|
||||
|
|
@ -267,6 +264,35 @@ func Glob(pattern string) (matches []string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// cleanGlobPath prepares path for glob matching.
|
||||
func cleanGlobPath(path string) string {
|
||||
switch path {
|
||||
case "":
|
||||
return "."
|
||||
case string(Separator):
|
||||
// do nothing to the path
|
||||
return path
|
||||
default:
|
||||
return path[0 : len(path)-1] // chop off trailing separator
|
||||
}
|
||||
}
|
||||
|
||||
// cleanGlobPathWindows is windows version of cleanGlobPath.
|
||||
func cleanGlobPathWindows(path string) string {
|
||||
vollen := volumeNameLen(path)
|
||||
switch {
|
||||
case path == "":
|
||||
return "."
|
||||
case vollen+1 == len(path) && os.IsPathSeparator(path[len(path)-1]): // /, \, C:\ and C:/
|
||||
// do nothing to the path
|
||||
return path
|
||||
case vollen == len(path) && len(path) == 2: // C:
|
||||
return path + "." // convert C: into C:.
|
||||
default:
|
||||
return path[0 : len(path)-1] // chop off trailing separator
|
||||
}
|
||||
}
|
||||
|
||||
// glob searches for files matching pattern in the directory dir
|
||||
// and appends them to matches. If the directory cannot be
|
||||
// opened, it returns the existing matches. New matches are
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@
|
|||
package filepath_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
. "path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
|
@ -209,3 +211,164 @@ func TestGlobSymlink(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
type globTest struct {
|
||||
pattern string
|
||||
matches []string
|
||||
}
|
||||
|
||||
func (test *globTest) buildWant(root string) []string {
|
||||
want := make([]string, 0)
|
||||
for _, m := range test.matches {
|
||||
want = append(want, root+FromSlash(m))
|
||||
}
|
||||
sort.Strings(want)
|
||||
return want
|
||||
}
|
||||
|
||||
func (test *globTest) globAbs(root, rootPattern string) error {
|
||||
p := FromSlash(rootPattern + `\` + test.pattern)
|
||||
have, err := Glob(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(have)
|
||||
want := test.buildWant(root + `\`)
|
||||
if strings.Join(want, "_") == strings.Join(have, "_") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Glob(%q) returns %q, but %q expected", p, have, want)
|
||||
}
|
||||
|
||||
func (test *globTest) globRel(root string) error {
|
||||
p := root + FromSlash(test.pattern)
|
||||
have, err := Glob(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(have)
|
||||
want := test.buildWant(root)
|
||||
if strings.Join(want, "_") == strings.Join(have, "_") {
|
||||
return nil
|
||||
}
|
||||
// try also matching version without root prefix
|
||||
wantWithNoRoot := test.buildWant("")
|
||||
if strings.Join(wantWithNoRoot, "_") == strings.Join(have, "_") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Glob(%q) returns %q, but %q expected", p, have, want)
|
||||
}
|
||||
|
||||
func TestWindowsGlob(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skipf("skipping windows specific test")
|
||||
}
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "TestWindowsGlob")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// /tmp may itself be a symlink
|
||||
tmpDir, err = EvalSymlinks(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatal("eval symlink for tmp dir:", err)
|
||||
}
|
||||
|
||||
if len(tmpDir) < 3 {
|
||||
t.Fatalf("tmpDir path %q is too short", tmpDir)
|
||||
}
|
||||
if tmpDir[1] != ':' {
|
||||
t.Fatalf("tmpDir path %q must have drive letter in it", tmpDir)
|
||||
}
|
||||
|
||||
dirs := []string{
|
||||
"a",
|
||||
"b",
|
||||
"dir/d/bin",
|
||||
}
|
||||
files := []string{
|
||||
"dir/d/bin/git.exe",
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
err := os.MkdirAll(Join(tmpDir, dir), 0777)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, file := range files {
|
||||
err := ioutil.WriteFile(Join(tmpDir, file), nil, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
tests := []globTest{
|
||||
{"a", []string{"a"}},
|
||||
{"b", []string{"b"}},
|
||||
{"c", []string{}},
|
||||
{"*", []string{"a", "b", "dir"}},
|
||||
{"d*", []string{"dir"}},
|
||||
{"*i*", []string{"dir"}},
|
||||
{"*r", []string{"dir"}},
|
||||
{"?ir", []string{"dir"}},
|
||||
{"?r", []string{}},
|
||||
{"d*/*/bin/git.exe", []string{"dir/d/bin/git.exe"}},
|
||||
}
|
||||
|
||||
// test absolute paths
|
||||
for _, test := range tests {
|
||||
var p string
|
||||
err = test.globAbs(tmpDir, tmpDir)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// test C:\*Documents and Settings\...
|
||||
p = tmpDir
|
||||
p = strings.Replace(p, `:\`, `:\*`, 1)
|
||||
err = test.globAbs(tmpDir, p)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// test C:\Documents and Settings*\...
|
||||
p = tmpDir
|
||||
p = strings.Replace(p, `:\`, `:`, 1)
|
||||
p = strings.Replace(p, `\`, `*\`, 1)
|
||||
p = strings.Replace(p, `:`, `:\`, 1)
|
||||
err = test.globAbs(tmpDir, p)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// test relative paths
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = os.Chdir(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := os.Chdir(wd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
for _, test := range tests {
|
||||
err := test.globRel("")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = test.globRel(`.\`)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = test.globRel(tmpDir[:2]) // C:
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue