diff --git a/pkg/locspec/locations.go b/pkg/locspec/locations.go index 7ae05c4e72..9832ffb13f 100644 --- a/pkg/locspec/locations.go +++ b/pkg/locspec/locations.go @@ -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 diff --git a/pkg/locspec/locations_test.go b/pkg/locspec/locations_test.go index cc10beb33d..617126a10f 100644 --- a/pkg/locspec/locations_test.go +++ b/pkg/locspec/locations_test.go @@ -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 }