Skip to content

go/build: ImportDir/Import no longer return os not found error for missing dir on local files #21923

@mattfarina

Description

@mattfarina

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

1.9

Does this issue reproduce with the latest release?

Yes. Was not present before latest release.

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/mfarina/Code/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.9/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.9/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/ml/55r2m1jd38x068q85txj8cvc0000gn/T/go-build428826794=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

I have code that uses ImportDir (from the go/build package) to look at the packages used by another package. If there is an error from ImportDir the automation acts on the error to try and fix the problem.

What did you expect to see?

I expected a missing directory to cause the returned error to be able to be detected by os.IsNotExist. This is how previous version of Go worked.

What did you see instead?

The returned error was in the form of

   fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)

In 1.8.3 (and before), the Import function would fall through to ctxt.readDir that used io.ReadDir...

go/src/go/build/build.go

Lines 171 to 177 in 352996a

// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir.
func (ctxt *Context) readDir(path string) ([]os.FileInfo, error) {
if f := ctxt.ReadDir; f != nil {
return f(path)
}
return ioutil.ReadDir(path)
}

In 1.9 The code is a little different for local files. Instead the code stops at...

go/src/go/build/build.go

Lines 687 to 695 in c8aec40

// If it's a local import path, by the time we get here, we still haven't checked
// that p.Dir directory exists. This is the right time to do that check.
// We can't do it earlier, because we want to gather partial information for the
// non-nil *Package returned when an error occurs.
// We need to do this before we return early on FindOnly flag.
if IsLocalImport(path) && !ctxt.isDir(p.Dir) {
// package was not found
return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
}

You can no longer rely on os.IsNotExist to detect missing package directories.

This change was not documented in the release notes, either.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsFixThe path to resolution is known, but the work has not been done.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions