Repository: go
Issue: cmd/go: support for Git LFS via new VCS qualifier
Labels: Proposal,Proposal-Accepted

## Background

* When Git LFS is installed on the client machine, `cmd/go` can work well with Git LFS, but only when using modules not via GOPROXY and GOPATH packages (called "packages" hereon for brevity).

* When Git LFS is not installed, `go get` will download the repository but not smudge, so any files stored in Git LFS are left as text-file refs.  This can break builds when such files are required for the build (e.g. binary syso files).

* The Google-hosted `proxy.golang.org` uses `cmd/go` to download package contents.  That service does not have Git LFS installed, and so every module retrieved via the proxy lacks Git LFS content.  This can break builds, and can also result in checksum mismatches when a user tries to verify a module they previously downloaded using `cmd/go` in direct mode while having Git LFS installed.

* For further detailed background information, see #47241.

## Proposal

1. A new VCS named `git-lfs` that prescribes the use of Git LFS when fetching a Git repo.

2. New `cmd/go` support for the new VCS: using a built-in Git LFS client implementation, or one that relies on Git LFS installed on the client machine.  For the latter:

    * If not installed, `cmd/go` should inform the user that Git LFS is required before erroring out.  i.e. `cmd/go` should never leave un-smudged Git LFS ref files in a fetched package.
    
    * Have Git LFS installed on `proxy.golang.org`.

3. Module (package) owners opt-in to mandatory Git LFS package retrieval using the following:

    * Specifying `git-lfs` as the `vcs` argument in the `content` attribute of the [go-import meta tag](https://golang.org/ref/mod#vcs-find).

    * Using the new VCS qualifier,

        * in the `module` directive in a `go.mod` file, e.g. `module go.jpap.org/example.git-lfs`.

            Here the `.git-lfs` suffix forms part of the module path when used with the [GOPROXY protocol](https://golang.org/ref/mod#goproxy-protocol) and the local module caches (`$GOPATH/pkg/mod`).

        * in the import comment in a package, e.g. `package example // import "go.jpap.org/example.git-lfs"`.

        In both cases above, the `.git-lfs` suffix should be ignored when matching the module path (package import path) against an `import` statement in a Go source file.  With reference to the examples above, the Go source having import statement `import "go.jpap.org/example"` should match even though it does not specify the VCS qualifier.

4. Module (package) users can explicitly qualify a module path (package import path) using the proposed VCS so that Git LFS is used to access the repository.  This is helpful when there is no `go-import` HTTP server available to resolve the repository URL.

5. Where Git LFS is installed, explicitly disable smudging on `cmd/go` fetches of modules (packages) not opted into the `git-lfs` VCS qualifier as outlined in Item 3.  This prevents the checksum mismatch problem outlined in #47241.

6. Irrespective of whether Git LFS is installed, when fetching a module (package) `cmd/go` should error out when it detects that a package has opted into Git LFS and the VCS qualifier is not `git-lfs`.  This forces module (package) users to also opt-in to using Git LFS, and prevents broken builds due to files not being smudged appropriately when Git LFS is not installed.