github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/str/path.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package str 6 7 import ( 8 "path" 9 "path/filepath" 10 "strings" 11 ) 12 13 // HasPath reports whether the slash-separated path s 14 // begins with the elements in prefix. 15 func HasPathPrefix(s, prefix string) bool { 16 if len(s) == len(prefix) { 17 return s == prefix 18 } 19 if prefix == "" { 20 return true 21 } 22 if len(s) > len(prefix) { 23 if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' { 24 return s[:len(prefix)] == prefix 25 } 26 } 27 return false 28 } 29 30 // HasFilePathPrefix reports whether the filesystem path s 31 // begins with the elements in prefix. 32 func HasFilePathPrefix(s, prefix string) bool { 33 sv := strings.ToUpper(filepath.VolumeName(s)) 34 pv := strings.ToUpper(filepath.VolumeName(prefix)) 35 s = s[len(sv):] 36 prefix = prefix[len(pv):] 37 switch { 38 default: 39 return false 40 case sv != pv: 41 return false 42 case len(s) == len(prefix): 43 return s == prefix 44 case prefix == "": 45 return true 46 case len(s) > len(prefix): 47 if prefix[len(prefix)-1] == filepath.Separator { 48 return strings.HasPrefix(s, prefix) 49 } 50 return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix 51 } 52 } 53 54 // GlobsMatchPath reports whether any path prefix of target 55 // matches one of the glob patterns (as defined by path.Match) 56 // in the comma-separated globs list. 57 // It ignores any empty or malformed patterns in the list. 58 func GlobsMatchPath(globs, target string) bool { 59 for globs != "" { 60 // Extract next non-empty glob in comma-separated list. 61 var glob string 62 if i := strings.Index(globs, ","); i >= 0 { 63 glob, globs = globs[:i], globs[i+1:] 64 } else { 65 glob, globs = globs, "" 66 } 67 if glob == "" { 68 continue 69 } 70 71 // A glob with N+1 path elements (N slashes) needs to be matched 72 // against the first N+1 path elements of target, 73 // which end just before the N+1'th slash. 74 n := strings.Count(glob, "/") 75 prefix := target 76 // Walk target, counting slashes, truncating at the N+1'th slash. 77 for i := 0; i < len(target); i++ { 78 if target[i] == '/' { 79 if n == 0 { 80 prefix = target[:i] 81 break 82 } 83 n-- 84 } 85 } 86 if n > 0 { 87 // Not enough prefix elements. 88 continue 89 } 90 matched, _ := path.Match(glob, prefix) 91 if matched { 92 return true 93 } 94 } 95 return false 96 }