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  }