1
0
mirror of https://github.com/golang/go synced 2024-09-30 09:18:35 -06:00

path/filepath: make Join("c:", "/a") return "c:/a" again

Historically, on Windows filepath.Join("c:", elt) does not insert
a path separator between "c:" and elt, but preserves leading slashes
in elt. Restore this behavior, which was inadvertently changed by
CL 444280.

Fixes #56988

Change-Id: Id728bf311f4093264f8c067d8b801ea9ebef5b5f
Reviewed-on: https://go-review.googlesource.com/c/go/+/453497
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
This commit is contained in:
Damien Neil 2022-11-29 20:07:02 -05:00 committed by Gopher Robot
parent a79b55bb9a
commit 79559c1e7e
2 changed files with 30 additions and 23 deletions

View File

@ -353,7 +353,8 @@ var winjointests = []JoinTest{
{[]string{`C:`, ``, ``, `b`}, `C:b`},
{[]string{`C:`, ``}, `C:.`},
{[]string{`C:`, ``, ``}, `C:.`},
{[]string{`C:`, ``, `\a`}, `C:a`},
{[]string{`C:`, `\a`}, `C:\a`},
{[]string{`C:`, ``, `\a`}, `C:\a`},
{[]string{`C:.`, `a`}, `C:a`},
{[]string{`C:a`, `b`}, `C:a\b`},
{[]string{`C:a`, `b`, `d`}, `C:a\b\d`},

View File

@ -222,31 +222,37 @@ func abs(path string) (string, error) {
func join(elem []string) string {
var b strings.Builder
appendSep := false
var lastChar byte
for _, e := range elem {
// Strip leading slashes from everything after the first element,
// to avoid creating a UNC path (any path starting with "\\") from
// non-UNC elements.
switch {
case b.Len() == 0:
// Add the first non-empty path element unchanged.
case isSlash(lastChar):
// If the path ends in a slash, strip any leading slashes from the next
// path element to avoid creating a UNC path (any path starting with "\\")
// from non-UNC elements.
//
// The correct behavior for Join when the first element is an incomplete UNC
// path (for example, "\\") is underspecified. We currently join subsequent
// elements so Join("\\", "host", "share") produces "\\host\share".
for b.Len() > 0 && len(e) > 0 && isSlash(e[0]) {
for len(e) > 0 && isSlash(e[0]) {
e = e[1:]
}
if e == "" {
continue
}
if appendSep {
case lastChar == ':':
// If the path ends in a colon, keep the path relative to the current directory
// on a drive and don't add a separator. Preserve leading slashes in the next
// path element, which may make the path absolute.
//
// Join(`C:`, `f`) = `C:f`
// Join(`C:`, `\f`) = `C:\f`
default:
// In all other cases, add a separator between elements.
b.WriteByte('\\')
lastChar = '\\'
}
if len(e) > 0 {
b.WriteString(e)
appendSep = !isSlash(e[len(e)-1])
if b.Len() == 2 && volumeNameLen(b.String()) == 2 {
// If the string is two characters long and consists of nothing but
// a volume name, this is either a drive ("C:") or the start of an
// incomplete UNC path ("\\"). In either case, don't append a separator.
appendSep = false
lastChar = e[len(e)-1]
}
}
if b.Len() == 0 {