Repository: go
Issue: proposal: cmd/go: configurable extra vcs paths
Labels: Proposal,Proposal-Hold,modules

Go module vcs identification is currently based on an array of regular expressions (vcsPaths) for known hosting platforms. https://github.com/golang/go/blob/98d20fb23551a7ab900fcfe9d25fd9cb6a98a07f/src/cmd/go/internal/get/vcs.go#L1026-L1083 There is a generic fallback regular expression that requires the vcs name be included as a suffix (.git) in the module path. Otherwise Go falls back to a dynamic check that fails if the server doesn't allow HTTPS access or else has non-standard connection/authentication requirements associated with HTTPS access that can't be negotiated. https://github.com/golang/go/blob/98d20fb23551a7ab900fcfe9d25fd9cb6a98a07f/src/cmd/go/internal/get/vcs.go#L788-L800

This proposal is to add support for cmd/go configuration to provide extra vcsPaths for use in mapping servers to vcs. The goal is to provide more flexibility for using go modules with smaller/internal repository servers while adding minimal complexity to the go command. By providing users with an option to specify the vcs for a module Go can delegate all further module download operations to the relevant client (git) and bypass the dynamic fallback function that is problematic for SSH-only and some HTTPS repository server deployments.

### Example: Current behavior

Module: some.internal.com/agroup/depmod
VCS: Git (prefer ssh)

#### Attempt 1
```
git config --global url."git@some.internal.com:".insteadOf "https://some.internal.com"
export GOPRIVATE="some.internal.com"
# if applicable, add the following to $HOME/.netrc
# machine some.internal.com login YOU password APIKEY
go get some.internal.com/agroup/depmod
```
- repo is not identified as git through vcsPaths
- dynamic fallback fails with "[unrecognized import path](https://github.com/golang/go/blob/98d20fb23551a7ab900fcfe9d25fd9cb6a98a07f/src/cmd/go/internal/get/vcs.go#L665)...[https fetch](https://github.com/golang/go/blob/98d20fb23551a7ab900fcfe9d25fd9cb6a98a07f/src/cmd/go/internal/get/vcs.go#L795-L799)" if the server only allows SSH access or otherwise uses a more custom HTTPS access/authentication implementation

#### Attempt 2
```
git config --global url."git@some.internal.com:".insteadOf "https://some.internal.com"
export GOPRIVATE="some.internal.com"
# add login credentials to $HOME/.netrc, if applicable
go get some.internal.com/agroup/depmod.git
```
- repo is identified as git through vcsPaths
- all download requests are delegated to git client, which is configured to use SSH as above -> download succeeds
- parsing fails unless module path also includes .git suffix

#### Attempt 3 (hack)
```
# configure git to map fake github.com/some-group prefix to git@some.internal.com
git config --global url."git@some.internal.com:".insteadOf "https://github.com/some-group"
export GOPRIVATE="github.com/some*"
# module path includes fake github.com/some-group prefix
go get github.com/some-group/depmod
```
- repo is identified as git through vcsPaths
- download requests delegated to git client -> download succeeds
- parsing succeeds as long as module path is consistent but this requires using a fake path prefix

### Example: Proposed

```
git config --global url."git@some.internal.com:".insteadOf "https://some.internal.com"
export GOPRIVATE="some.internal.com"
export GOVCSEXT="root:some.internal.com:vcs:git"
go get some.internal.com/agroup/depmod
```
- repo is identified as git through vcsPaths
- download requests delegated to git client -> download succeeds
- no module path mismatch -> parsing succeeds

#### Alternatives

Local go get config
- See https://github.com/golang/go/issues/30304#issuecomment-465134045

VCS as protocol prefix in GOPRIVATE
- `export GOPRIVATE="git://some.internal.com"`