Skip to content

path/filepath: document that filepath.Join("c:", "a") returns c:\a not c:a on Windows #11551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexbrainman opened this issue Jul 3, 2015 · 20 comments

Comments

@alexbrainman
Copy link
Member

This program:

package main

import (
    "fmt"
    "path/filepath"
)

func main() {
    fmt.Println(filepath.Join("a"))
    fmt.Println(filepath.Join("c:", "a"))
}

displays:

C:\dev\src\foo>go run main.go
a
c:\a

C:\dev\src\foo>

but should display:

C:\dev\src\foo>go run main.go
a
c:a

C:\dev\src\foo>

or

C:\dev\src\foo>go run main.go
a
c:.\a

C:\dev\src\foo>

Alex

@jhoonb
Copy link

jhoonb commented Jul 3, 2015

No...
the doc says:
"The returned path ends in a slash only if it represents a root directory, such as "/" on Unix or C:\ on Windows."
http://golang.org/pkg/path/filepath/#Clean

See code:
http://golang.org/src/path/filepath/path.go?s=2213:2243#L71

@akavel
Copy link
Contributor

akavel commented Jul 5, 2015

Related discussion with more details: https://groups.google.com/forum/#!topic/golang-nuts/xFWpetTOPp4

@alexbrainman
Copy link
Member Author

@xiofen I am no good at writing documentation. So, if you feel strongly about it, suggest you own change - http://golang.org/doc/contribute.html

Thank you.

Alex

@jhoonb
Copy link

jhoonb commented Jul 5, 2015

I agree

@ianlancetaylor ianlancetaylor added the Documentation Issues describing a change to documentation. label Jul 11, 2015
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Jul 11, 2015
@nerdatmath
Copy link
Contributor

Perhaps "adding a separator if one is not already present"

@alexbrainman alexbrainman removed the Documentation Issues describing a change to documentation. label Aug 26, 2015
@alexbrainman alexbrainman modified the milestones: Go1.6, Unplanned Aug 26, 2015
@alexbrainman
Copy link
Member Author

@minux and me disagree about https://go-review.googlesource.com/#/c/11882 change. We need more reviewers to lean us one way or the other. Please help. Thank you.

Alex

@Thomasdezeeuw
Copy link
Contributor

Although I do think the new behaviour is better, I also think this is a breaking change. So this should be a no-go for Go1.x.

@ianlancetaylor
Copy link
Member

I don't see a clear justification for the change in CL 11882. I see the logic in it, but the function was never documented to work that way, and it could clearly break existing programs. I think we should document the current behavior, as this issue suggests.

@nerdatmath
Copy link
Contributor

Intuitively, I see filepath.Join as giving the path you would get if you did a Chdir to each path in sequence (without looking at the filesystem, so you could end up with a relative path). On Windows if I Chdir("c:") and then Chdir("abc") I end up in the same place as if I did Chdir("c:abc"). This is different from Chdir("c:\abc") because on Windows you have a working directory for each drive letter.

I don't have any valid intuition about the current behavior. It strikes me as just a symbol manipulation that makes Unix-specific assumptions even though filepath is supposed to be a cross platform module.

Although it could break existing code, I suspect any such existing code is already buggy, and this change would make it less buggy.

@minux
Copy link
Member

minux commented Sep 9, 2015 via email

@alexbrainman
Copy link
Member Author

Thanks to everyone for their input. It seems to me I don't have support for my change. I just want to clarify my reasoning (before I abandon my change). With this code:

a := ...
b := filepath.Join(a, ...)

If "a" contains absolute path (filepath.IsAbd(a) returns true), should I expect "b" to contain absolute path?

If "a" contains relative path (filepath.IsAbd(a) returns false), should I expect "b" to contain relative path?

The answers to these questions are "yes" on unix. Not so on windows. This program http://play.golang.org/p/_DOiToc8cD prints:


a is "c:\\" and filepath.IsAbs(a) is true
b is "c:\\file.txt" and filepath.IsAbs(b) is true

a is "c:" and filepath.IsAbs(a) is false
b is "c:\\file.txt" and filepath.IsAbs(b) is true

I think that this invariant is important. If only because Go team developers (none of who use windows) assume that invariant is there. So no amount of documenting will stop them (and others) from making mistakes.

Alex

@ianlancetaylor
Copy link
Member

@alexbrainman To be clear, I agree with your rationale, and if we were designing this function now, that is how it should work.

But that's not the question we are facing. The question is: given that the function has behaved as it presently does since before the Go 1 release, should we change it? The current behaviour is meaningful, is not always wrong, and is easy to avoid if you know about it. Given that, it's hard for me to support a change that may silently break some currently working programs.

@mattn
Copy link
Member

mattn commented Sep 10, 2015

If the interface is like below, I agree with your opinion.

func MakePath(drive string, elems... string) string

But this is Join that mean joining the given path and path independently.

C:\dev\src\foo>go run main.go
a
c:\a

C:\dev\src\foo>

So I'm thinking this is right.

@rsc rsc changed the title path/filepath: filepath.Join("c:", "a") returns wrong result path/filepath: document that filepath.Join("c:", "a") returns c:\a not c:a on Windows Nov 25, 2015
@gopherbot
Copy link
Contributor

CL https://golang.org/cl/17198 mentions this issue.

@gopherbot
Copy link
Contributor

CL https://golang.org/cl/17470 mentions this issue.

@gopherbot
Copy link
Contributor

CL https://golang.org/cl/17620 mentions this issue.

alexbrainman added a commit that referenced this issue Dec 9, 2015
EvalSymlinks code assumes that Join has a bug
(see issue #11551 for details). But issue #11551 has
been fixed. Remove the workaround so it does not
confuses us when we read code next time.

Change-Id: I06bea20189f01f9922237c05516847353d8e4736
Reviewed-on: https://go-review.googlesource.com/17620
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
@golang golang locked and limited conversation to collaborators Dec 14, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants