...

Source file src/cmd/go/internal/str/path.go

     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	}
    97	

View as plain text