golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/cmd/gorelease/path.go (about) 1 // Copyright 2020 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 main 6 7 import ( 8 "path/filepath" 9 "strings" 10 ) 11 12 // hasPathPrefix reports whether the slash-separated path s 13 // begins with the elements in prefix. 14 // Copied from cmd/go/internal/str.HasPathPrefix. 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 // Copied from cmd/go/internal/str.HasFilePathPrefix. 33 func hasFilePathPrefix(s, prefix string) bool { 34 sv := strings.ToUpper(filepath.VolumeName(s)) 35 pv := strings.ToUpper(filepath.VolumeName(prefix)) 36 s = s[len(sv):] 37 prefix = prefix[len(pv):] 38 switch { 39 default: 40 return false 41 case pv != "" && sv != pv: 42 return false 43 case len(s) == len(prefix): 44 return s == prefix 45 case prefix == "": 46 return true 47 case len(s) > len(prefix): 48 if prefix[len(prefix)-1] == filepath.Separator { 49 return strings.HasPrefix(s, prefix) 50 } 51 return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix 52 } 53 } 54 55 // trimFilePathPrefix returns the given filesystem path s without the leading 56 // prefix. 57 func trimFilePathPrefix(s, prefix string) string { 58 sv := strings.ToUpper(filepath.VolumeName(s)) 59 pv := strings.ToUpper(filepath.VolumeName(prefix)) 60 s = s[len(sv):] 61 prefix = prefix[len(pv):] 62 63 if !hasFilePathPrefix(s, prefix) || len(prefix) == 0 { 64 return s 65 } 66 if len(s) == len(prefix) { 67 return "" 68 } 69 if prefix[len(prefix)-1] == filepath.Separator { 70 return strings.TrimPrefix(s, prefix) 71 } 72 return s[len(prefix)+1:] 73 } 74 75 // trimPathPrefix returns p without the leading prefix. Unlike 76 // strings.TrimPrefix, the prefix will only match on slash-separted component 77 // boundaries, so trimPathPrefix("aa/b", "aa") returns "b", but 78 // trimPathPrefix("aa/b", "a") returns "aa/b". 79 func trimPathPrefix(p, prefix string) string { 80 if prefix == "" { 81 return p 82 } 83 if prefix == p { 84 return "" 85 } 86 return strings.TrimPrefix(p, prefix+"/") 87 }