// Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package str import ( "path" "path/filepath" "strings" ) // HasPath reports whether the slash-separated path s // begins with the elements in prefix. func HasPathPrefix(s, prefix string) bool { if len(s) == len(prefix) { return s == prefix } if prefix == "" { return true } if len(s) > len(prefix) { if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' { return s[:len(prefix)] == prefix } } return false } // HasFilePathPrefix reports whether the filesystem path s // begins with the elements in prefix. func HasFilePathPrefix(s, prefix string) bool { sv := strings.ToUpper(filepath.VolumeName(s)) pv := strings.ToUpper(filepath.VolumeName(prefix)) s = s[len(sv):] prefix = prefix[len(pv):] switch { default: return false case sv != pv: return false case len(s) == len(prefix): return s == prefix case prefix == "": return true case len(s) > len(prefix): if prefix[len(prefix)-1] == filepath.Separator { return strings.HasPrefix(s, prefix) } return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix } } // GlobsMatchPath reports whether any path prefix of target // matches one of the glob patterns (as defined by path.Match) // in the comma-separated globs list. // It ignores any empty or malformed patterns in the list. func GlobsMatchPath(globs, target string) bool { for globs != "" { // Extract next non-empty glob in comma-separated list. var glob string if i := strings.Index(globs, ","); i >= 0 { glob, globs = globs[:i], globs[i+1:] } else { glob, globs = globs, "" } if glob == "" { continue } // A glob with N+1 path elements (N slashes) needs to be matched // against the first N+1 path elements of target, // which end just before the N+1'th slash. n := strings.Count(glob, "/") prefix := target // Walk target, counting slashes, truncating at the N+1'th slash. for i := 0; i < len(target); i++ { if target[i] == '/' { if n == 0 { prefix = target[:i] break } n-- } } if n > 0 { // Not enough prefix elements. continue } matched, _ := path.Match(glob, prefix) if matched { return true } } return false }