locspec: fix SubstitutePath when converting a Windows path to Linux (#3453)

Normalize separators when converting a Windows path into a Linux path.

Fixes #3447
This commit is contained in:
Alessandro Arzilli
2023-08-15 00:34:29 +02:00
committed by GitHub
parent 281f3920dd
commit 4ce596b9dd
2 changed files with 49 additions and 14 deletions

View File

@ -508,6 +508,49 @@ func hasPathSeparatorPrefix(path string) bool {
return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "\\")
}
func pickSeparator(to string) string {
var sep byte
for i := range to {
if to[i] == '/' || to[i] == '\\' {
if sep == 0 {
sep = to[i]
} else if sep != to[i] {
return ""
}
}
}
return string(sep)
}
func joinPath(to, rest string) string {
sep := pickSeparator(to)
switch sep {
case "/":
rest = strings.ReplaceAll(rest, "\\", sep)
case "\\":
rest = strings.ReplaceAll(rest, "/", sep)
default:
sep = "/"
}
toEndsWithSlash := hasPathSeparatorSuffix(to)
restStartsWithSlash := hasPathSeparatorPrefix(rest)
switch {
case toEndsWithSlash && restStartsWithSlash:
return to[:len(to)-1] + rest
case toEndsWithSlash && !restStartsWithSlash:
return to + rest
case !toEndsWithSlash && restStartsWithSlash:
return to + rest
case !toEndsWithSlash && !restStartsWithSlash:
fallthrough
default:
return to + sep + rest
}
}
// SubstitutePath applies the specified path substitution rules to path.
func SubstitutePath(path string, rules [][2]string) string {
// Look for evidence that we are dealing with windows somewhere, if we are use case-insensitive matching
@ -559,19 +602,7 @@ func SubstitutePath(path string, rules [][2]string) string {
return rest
}
toEndsWithSlash := hasPathSeparatorSuffix(to)
restStartsWithSlash := hasPathSeparatorPrefix(rest)
switch {
case toEndsWithSlash && restStartsWithSlash:
return to[:len(to)-1] + rest
case toEndsWithSlash && !restStartsWithSlash:
return to + rest
case !toEndsWithSlash && restStartsWithSlash:
return to + rest
case !toEndsWithSlash && !restStartsWithSlash:
return to + "/" + rest
}
return joinPath(to, rest)
}
}
return path

View File

@ -160,7 +160,7 @@ func platformCases() []tCase {
{[]tRule{{`c:\tmp\path`, `d:\new\path2`}}, `c:\tmp\path\file.go`, `d:\new\path2\file.go`},
{[]tRule{{`c:\tmp\path\`, `d:\new\path2\`}}, `c:\tmp\path\file.go`, `d:\new\path2\file.go`},
{[]tRule{{`c:\tmp\path`, `d:\new\path2\`}}, `c:\tmp\path\file.go`, `d:\new\path2\file.go`},
{[]tRule{{`c:\tmp\path\`, `d:\new\path2`}}, `c:\tmp\path\file.go`, `d:\new\path2/file.go`},
{[]tRule{{`c:\tmp\path\`, `d:\new\path2`}}, `c:\tmp\path\file.go`, `d:\new\path2\file.go`},
// Should apply to directory prefixes
{[]tRule{{`c:\tmp\path`, `d:\new\path2`}}, `c:\tmp\path-2\file.go`, `c:\tmp\path-2\file.go`},
// Should apply to exact matches
@ -168,11 +168,15 @@ func platformCases() []tCase {
// Should be case-insensitive
{[]tRule{{`c:\tmp\path`, `d:\new\path2`}}, `C:\TmP\PaTh\file.go`, `d:\new\path2\file.go`},
}
casesCross := []tCase{
{[]tRule{{"C:\\some\\repo", "/go/src/github.com/some/repo/"}}, `c:\some\repo\folder\file.go`, "/go/src/github.com/some/repo/folder/file.go"},
}
r := append(casesUnix, casesLinux...)
r = append(r, casesFreebsd...)
r = append(r, casesDarwin...)
r = append(r, casesWindows...)
r = append(r, casesCross...)
return r
}