Go 1.4 Custom Import Path Checking

Russ Cox

June 2014

Abstract

We propose a mechanism to enforce use of custom import paths: a specific end-of-line comment on the package statement.

Note: comments disabled. Use the golang-dev “proposal: custom import path checking” thread.

Background

Go 1 introduced a mechanism for defining custom import paths: by serving HTML meta tags with repository information at a given URL, that URL can be used to import code from that repository. This mechanism allows the use of any source control server, not just the hosting services known to the go command (Bitbucket, GitHub, Google Code, Launchpad).

In addition to enabling the use of other servers, this redirect mechanism can be used to give a package a stable name even when the underlying version control server or version control system changes. For example, today "rsc.io/pdf" is a Git repository hosted at GitHub, but it could be moved to a Mercurial repository on Bitbucket without affecting users of 'go get', as long as the HTML meta tags at http://rsc.io/pdf are updated appropriately.

 

As in the example just given, a common target for the redirect is one of the known hosting sites. In this case, the code ends up being importable under two different paths: the custom path (in the example, rsc.io/pdf) and the path naming the redirected location directly (in the example, github.com/rsc/pdf). If the code is moved, even if the rsc.io/pdf redirect is updated, uses of the github.com import path will break. We would like to keep such breakable references from being created.

 

Another drawback of multiple import paths for a single package is that the package might be imported under both names in a single program. Because the import path is the unique identifier for a package, the two different imports bring in two distinct copies of the code. This is code bloat and may lead to incorrect behavior if clients expect to coordinate via the package.


Proposal

A package statement is said to have an “import comment” if it is immediately followed (before the next newline) by a comment of one of these two forms:

// import "path"

/* import "path" */

The go command will refuse to install a package with an import comment under any import path except the one named in the comment.

Continuing the example, as long as one file from package pdf contains

        package pdf // import "rsc.io/pdf"

the go command will reject "go get github.com/rsc/pdf", ensuring that the code can be moved without breaking users.

Implementation

The go command scans the header of each source file for package name and imports. It can record the canonical import path at the same time. If multiple files in a package give conflicting canonical import paths, the go command should report that as an error.

The go command will refuse to install a package if the default install path does not match the documented import path.

The go get command needs to download the code in order to read the source files, possibly finding out too late that the import path is wrong. In this case it will print an error and remove the directory it created, or (if it did not create the directory) print a command that could be used to move the code to the correct location.

 

Deployment

Go 1.4 will include support for these annotations in the go command.

Because the annotation is an ordinary comment (as opposed to new syntax), packages can use these annotations without fear of breaking users of older Go versions.

The Go subrepos may change their import paths to use a custom domain during the Go 1.4 cycle. We would wait at least six months from introducing the new domain to adding the annotations forcing its use.