Skip to content

cmd/go: install: respect replace directive if the replaced module is in the same repository #69762

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

Closed
metakeule opened this issue Oct 3, 2024 · 9 comments
Labels
GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@metakeule
Copy link

metakeule commented Oct 3, 2024

Go version

go 1.23.0

Output of go env in your module/workspace:

set GO111MODULE=on
set GOARCH=amd64
set GOEXE=.exe
set GOEXPERIMENT=loopvar
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\xxxx\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLCHAIN=local
set GOVCS=
set GOVERSION=go1.23.0
set GODEBUG=
set GCCGO=gccgo
set GOAMD64=v1

What did you do?

go install gitlab.com/metakeule/[email protected]
go install gitlab.com/metakeule/cmdlibprob2/cmd/[email protected]
go install gitlab.com/metakeule/cmdlibprob3/cmd/[email protected]

What did you see happen?

go install gitlab.com/metakeule/[email protected]
go: downloading gitlab.com/metakeule/cmdlibprob1 v0.0.2
go: gitlab.com/metakeule/[email protected] (in gitlab.com/metakeule/[email protected]):
        The go.mod file for the module providing named packages contains one or
        more replace directives. It must not contain directives that would cause
        it to be interpreted differently than if it were the main module.
go install gitlab.com/metakeule/cmdlibprob2/cmd/[email protected]
go: downloading gitlab.com/metakeule/cmdlibprob2 v0.0.1
go: gitlab.com/metakeule/cmdlibprob2/cmd/[email protected]: module gitlab.com/metakeule/[email protected] found, but does not contain package gitlab.com/metakeule/cmdlibprob2/cmd/cmdlibprob2
go install gitlab.com/metakeule/cmdlibprob3/cmd/[email protected]
go: downloading gitlab.com/metakeule/cmdlibprob3 v0.0.1
go: gitlab.com/metakeule/cmdlibprob3/cmd/[email protected]: module gitlab.com/metakeule/[email protected] found, but does not contain package gitlab.com/metakeule/cmdlibprob3/cmd/cmdlibprob3

What did you expect to see?

nothing, it should just install

Context

We have a repository with a library and a command that uses the library. This is pretty common and was never a problem in the pre go modules era.

This allows in principle for a library and a command to be released in sync with the same version number and the same behaviour.

An additional reasonable requirement is, that the command should be able to have more dependencies than the library. And therefor the library and the command are two different go modules (each has its own go.mod file with its own path).

In our case, there are other libraries depending on the library. These other libraries are used by the command. This is not possible without having two separate go modules in this repository.

I have set up three repositories to reflect the three different strategies for combining a command and a library here:

The problem is, that without a replace directive inside the go.mod file of the command, there is no way to release the command and the library at the same time, because the command depending on the library needs to find it first.

However, having a replace directive, even if it is pointing to the same repository, is not supported by go install yet (see above).

Changing this would help a lot and I can't see a reason, why it should not be supported in this case, because the repository needs to be downloaded anyway to compile.

As it is, we need to make double releases all the time: first for the library and then for the command. But before the release of the command we first need to update the version of the library that the command depends on, although it is in the same repo! This is error prone, unnecessary work and confusing for the users, since the same version of library and command might behave differently.

Maybe this should be changed to be a proposal, since another request was closed as "works as intended". But I would say, that this is a very reasonable and useful request with minimal implementation impact.

So it is not about allowing replace directives in general to be used by go install, but only in the very specific case, when:

  • the original path of the module that is to be replaced is within the same repository
  • the target path is relative and in such a way that it is reachable within the repository

Example

module gitlab.com/metakeule/cmdlibprob3/cmd/cmdlibprob3
replace gitlab.com/metakeule/cmdlibprob3/lib/cmdlibprob3 => ../../lib/cmdlibprob3

would be valid

module gitlab.com/metakeule/cmdlibprob3/cmd/cmdlibprob3
replace gitlab.com/metakeule/cmdlibprob3/lib/cmdlibprob3 => ../../../lib/cmdlibprob3

would not be valid.

From resolving the paths it is actually very easy to check, that

from gitlab.com/metakeule/cmdlibprob3/cmd/cmdlibprob3
to ../../lib/cmdlibprob3 is resulting in gitlab.com/metakeule/cmdlibprob3/lib/cmdlibprob3 so this, is exacly the same as the original path and should be allowed.

go.sum Problem

Tagging both versions at the same time is possible. But the go.sum file of the dependant package is always one commit behind.

@metakeule metakeule changed the title go install: following replace directive if it points to the same repository go install: respect replace directive if it points to the same repository Oct 3, 2024
@metakeule
Copy link
Author

Before considering closing this request, like #44840 and #40276 please answer the question, how a repo can be organized in a way that allows the above behavior with the way go install currently works. It is not (only) about replace directives and go install, but about being able to have a repo with two modules where one uses the other and they can be released together.

@metakeule metakeule changed the title go install: respect replace directive if it points to the same repository go install: respect replace directive if the replace module is in the same repository Oct 3, 2024
@metakeule metakeule changed the title go install: respect replace directive if the replace module is in the same repository go install: respect replace directive if the replaced module is in the same repository Oct 3, 2024
@mknyszek mknyszek changed the title go install: respect replace directive if the replaced module is in the same repository cmd/go: install: respect replace directive if the replaced module is in the same repository Oct 3, 2024
@mknyszek mknyszek added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. GoCommand cmd/go labels Oct 3, 2024
@mknyszek mknyszek added this to the Backlog milestone Oct 3, 2024
@mknyszek
Copy link
Contributor

mknyszek commented Oct 3, 2024

CC @matloob @samthanawalla

@metakeule
Copy link
Author

metakeule commented Oct 3, 2024

It is obviously for using go install outside of a go module. For end users.

@seankhliao
Copy link
Member

Duplicate of #50698

there's no reason why you can't tag and update both in the same commit.

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Oct 4, 2024
@metakeule
Copy link
Author

Duplicate of #50698

there's no reason why you can't tag and update both in the same commit.

Yes, there is a reason: The dependent can only get the correct go.sum entry when the repo is tagged and pushed. So when tagging in the same commit, the go.sum would be outdated.

@metakeule
Copy link
Author

Duplicate of #50698

Since there the go.sum problem was not mentioned, can you please reopen this issue?

@seankhliao
Copy link
Member

That's not really an issue that prevents the code from working, and as mentioned in #50698 , this is in general infeasible.

@metakeule
Copy link
Author

It defeats the purpose of go.sum. It would be feasible, if go install would allow the replace directive in this cases. We are running in circles.

It is not really an argument so say, it does not work. Then nothing would ever happen. It is totally ignorant to the problem and the community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants