Description
Problem
Git supports multiple transports. The built-in transports are git://
, ssh://
, https://
, but it can support a custom transport, such as persistent-https://
. Git repository hosting services typically support multiple transports.
With #26232, it will become possible to support private Git repositories with go-get
. A server that supports ?go-get=1
URLs needs to return one <meta name="go-import">
tag. However, the server cannot tell which Git transport URL it should return.
For example, https://git.mycompany.com/private-repo
is a Git repository that can be accessed with git clone https://...
and git clone ssh://...
. Both require an authentication. A user may choose to use https://
or ssh://
for git clone
. When https://git.mycompany.com/private-repo?go-get=1
returns a tag <meta name="go-import" content="git.mycompany.com/private-repo git https://git.mycompany.com/private-repo">
, users who set up credentials only for SSH cannot run go get
because it internally tries to run git clone https://git.mycompany.com/private-repo
and it fails because of the lack of credentials. The opposite is also true. If the server returns a tag with ssh://...
, users who use https://...
cannot run go get
.
Multiple workarounds exist for this problem.
- Use Git's url.insteadOf
- Use a different go-import URL for a different transport (like golang.org for go.googlesource.com. Though, probably with cmd/go: define HTTP authentication extension mechanism #26232, we can support
go-get=1
directly on googlesource.com.) - Encourage users to set up credentials for the transport that
go-get=1
URL returns - Abuse GOAUTH so that it sends an indicator for the transport preference, assuming that the user can change the server side
Because of these workarounds, this problem is not critical. But it's nice if it's addressed.
Goal
Let users choose a VCS transport for go get git.mycompany.com/private-repo
.
Idea 1 (add a query param for selecting a transport)
In addition to go-get=1
, go get
will add another query parameter so that the server can decide which go-import URL it returns. A user specifies GOGET_VCS_TRANSPORT=git-ssh
in the environment variables, then go get
will fetch "https://git.mycompany.com/private-repo?go-get=1&vcs-transport=git-ssh". The server returns a different URL based on the added query param.
A nice part of this option is that this is compatible with old/new client/server. A new server that supports this new query param can be compatible with the old go toolchains. When the new go toolchains that support GOGET_VCS_TRANSPORT
fetch a URL with a new query param, as long as the server ignore unknown params, it's compatible with old servers.
We can abuse GOAUTH mechanism for this purpose. GOAUTH is meant for auth, but users can add any HTTP header that is not related to auth. A user can write a GOAUTH program that adds a special HTTP header that specifies their VCS transport preference and a supported server can return a different go-import URL based on that.
Idea 2 (let the server return multiple go-import URLs)
Let servers return multiple go-import tags with a different transport. The go toolchains need to choose which one it uses.
This might lose the backward compatibility, so I'm not sure if this is a good option.