-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
Go version
go version go1.25.1 darwin/arm64
Output of go env
in your module/workspace:
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE='on'
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/Users/abc/workspace/Projects/golang/bin'
GOCACHE='/Users/abc/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/abc/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/Users/abc/workspace/Projects/golang/cache'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/abc/workspace/Projects/golang'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.25.1/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/abc/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.25.1/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.25.1'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
There appears to be an issue with how go tool
interprets relative replace
statements when used in combination with -modfile
flag.
Here's an example, which can be used to reproduce the issue.
Create a new Go module.
mkdir go-tool-modfile-replace
cd go-tool-modfile-replace
go mod init go-tool-modfile-replace
Create a dummy tool, which we will use.
mkdir -p cmd/dummy
cd cmd/dummy
go mod init my/dummy/cmd
This is how cmd/dummy/main.go
looks like.
package main
import (
"fmt"
"os"
)
func main() {
pwd, err := os.Getwd()
if err != nil {
panic(err)
}
fmt.Printf("dummy was called. cwd is %s\n", pwd)
}
Next, create a dedicated tools
module, which will be used for tracking various tool dependencies. These tools may be related to anything the project uses as part of the lifecycle, e.g. linting, formatting, etc. It will also include our simple dummy
tool.
repo-root $ mkdir -p tools
tools $ cd tools
tools $ go mod init my/tools/mod
We can now add any tools we need using go get -tool
, and dependencies will be tracked correctly. However, we want to include our dummy
tool as well, so that we can call each utility tool via go tool <name>
.
This is what tools/go.mod
looks like, when it contains only our dummy
tool.
module my/tools/mod
go 1.25.1
tool my/dummy/cmd
replace my/dummy/cmd => ../cmd/dummy
require my/dummy/cmd v0.0.0-00010101000000-000000000000 // indirect
Now we can run our dummy
tool when we are within the tools/
directory (module).
tools $ go tool my/dummy/cmd
dummy was called. cwd is /Users/abc/go-tool-modfile-replace/tools
However, if we go back to the repo root and try to call the tool it would fail.
repo-root $ go tool -modfile tools/go.mod my/dummy/cmd
my/dummy/cmd: my/dummy/cmd@v0.0.0-00010101000000-000000000000: replacement directory ../cmd/dummy does not exist
The reason it fails here is (probably) because the relative path replace
in tools/go.mod
is relative to the current directory of the calling process, instead of being relative to the path where tools/go.mod
resides.
If we use go tool -C tools my/dummy/cmd
the command would work fine, but only because the current directory will already be set (via the -C
flag), and the replace
statement would be valid, because our current workdir is the same as the location for go.mod
as well.
go tool -C tools my/dummy/cmd
dummy was called. cwd is /Users/abc/go-tool-modfile-replace/tools
What did you see happen?
Please see details above.
What did you expect to see?
Calling go tool -modfile path/to/go.mod some-tool
should work fine when the path/to/go.mod
contains local relative replace
entries.
When using relative replace
entries with relative local paths, perhaps the paths should be relative to the directory of the go.mod file itself.
For example when calling go tool -modfile path/to/go.mod some-tool
any local relative replace
entries in path/to/go.mod
should be considered relative in regards to the path/to
directory, which contains the go.mod
file.