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

cmd/go: allow replacement version to be omitted if the target module has a required version #28176

Open
dmitris opened this Issue Oct 12, 2018 · 5 comments

Comments

Projects
None yet
3 participants
@dmitris
Contributor

dmitris commented Oct 12, 2018

Currently you must add a version when entering a non-filesystem (remote) replacement for a module. A foolish attempt to put replace github.com/fsnotify/fsnotify => gitmirror.corp.xyz.com/fsnotify/fsnotify provokes a rebuke from go mod verify:
go.mod:42: replacement module without version must be directory path (rooted or starting with ./ or ../)

  • so you have to fix it to be: replace github.com/fsnotify/fsnotify => gitmirror.corp.xyz.com/fsnotify/fsnotify v1.4.7.

However, there is already a version specification for that package in go.mod the require statement, for example:
require github.com/fsnotify/fsnotify v1.4.7
This seems to be the reasonable default value for the missing version in the replace directive for the same package - "if no replacement version is given, use the same as in the require directive for that specific package`.

What would be especially nice is when upgrading a package such as github.com/fsnotify/fsnotify to the future v1..4.8 version, one would not need to first run go get -u github.com/fsnotify/fsnotify and then have to look up the new version and manually update the old version to the new one in the replace section (or worse, forgetting to do it and ending up with the unintended replacement with the old version).

@thepudds said on Slack that he wanted to suggest this as well. @bcmills @rsc - does it seem reasonable to you?

@bcmills

This comment has been minimized.

Member

bcmills commented Oct 12, 2018

there is already a version specification for that package in go.mod [in a] require statement

I'm pretty sure that won't work at all right now: as a consequence of the fix for #26607, you cannot both require a module and use it as the target of a replace.

@bcmills

This comment has been minimized.

Member

bcmills commented Oct 12, 2018

This is certainly worth considering when we allow overlapping replacements, though. (That's #26904.)

@bcmills bcmills changed the title from modules - make the trailing version optional in the replace statement in go.mod to cmd/go: allow replacement version to be omitted if the target module has a required version Oct 12, 2018

@bcmills bcmills added this to the Go1.12 milestone Oct 12, 2018

@thepudds

This comment has been minimized.

thepudds commented Oct 12, 2018

Just expanding on the use case briefly:

Currently it is an error to not have a right-hand version in a replace directive if the replacement is a remote repo.

If the right-hand version in a replace was allowed to be optional when the replacement is a remote repo, it could be natural then to tell the go tooling how to obtain a copy from a mirror, for example:

replace github.com/foo/bar => gitmirror.corp.com/foo/bar

And then have the actual versions used could be automatically be resolved "normally" via MVS and the normal version picking rules, but hitting gitmirror.corp.com rather than github.com to get the VCS metadata (and actual source code, etc.). In other words, the replacement would apply to the repo, not the version.

That would be less fragile than something like a go.mod file with 15 replace lines that effectively hard code the versions (with sample here taken from a real-world example):

replace (
   github.com/ardielle/ardielle-go => mirror.foobar.com/ardielle/ardielle-go.git v1.5.1
   github.com/aws/aws-sdk-go => mirror.foobar.com/aws/aws-sdk-go.git v1.15.49 // indirect
   github.com/coreos/go-oidc => mirror.foobar.com/coreos/go-oidc.git v2.0.0+incompatible
   github.com/golang/protobuf => mirror.foobar.com/golang/protobuf.git v1.2.0
   ...

I suspect that would help make modules a better upgrade for users that previously relied on glide repo directives or dep source and similar.

Perhaps the ultimate answer might end up being "use Athens", or "roll your own GOPROXY", but seems at least worth considering including this in the core go tool.

@thepudds

This comment has been minimized.

thepudds commented Oct 12, 2018

@bcmills not the most urgent question, but could you expand slightly on what you meant here:

I'm pretty sure that won't work at all right now: as a consequence of the fix for #26607, you cannot both require a module and use it as the target of a replace.

In particular, what do you mean by a "target" there -- the left side module in the replace, or the right side module?

Going back to the first example from @dmitris above, I think this is what he was trying to say as a theoretical go.mod if this issue/suggestion here was implemented:

require github.com/fsnotify/fsnotify v1.4.7
replace github.com/fsnotify/fsnotify => gitmirror.corp.xyz.com/fsnotify/fsnotify

Which piece of that would violate the "forbid use of one module with two different paths" restriction from the fix for #26607?

(Of course, that is not a valid go.mod today because of there is no version on the right-hand side of the replace, but that's the topic of this issue/suggestion here).

@bcmills bcmills modified the milestones: Go1.12, Go1.13 Oct 25, 2018

@bcmills

This comment has been minimized.

Member

bcmills commented Nov 15, 2018

In particular, what do you mean by a "target" there -- the left side module in the replace, or the right side module?

The right side module.

Which piece of that would violate the "forbid use of one module with two different paths" restriction from the fix for #26607?

I'm not sure. I think I misunderstood the original report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment