"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modinfo"
+ "cmd/go/internal/modload"
"cmd/go/internal/par"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/trace"
)
-var (
- // module initialization hook; never nil, no-op if module use is disabled
- ModInit func()
-
- // module hooks; nil if module use is disabled
- ModBinDir func() string // return effective bin directory
- ModLookup func(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) // lookup effective meaning of import
- ModPackageModuleInfo func(path string) *modinfo.ModulePublic // return module info for Package struct
- ModImportPaths func(ctx context.Context, args []string) []*search.Match // expand import paths
- ModPackageBuildInfo func(main string, deps []string) string // return module info to embed in binary
- ModInfoProg func(info string, isgccgo bool) []byte // wrap module info in .go code for binary
- ModImportFromFiles func(context.Context, []string) // update go.mod to add modules for imports in these files
- ModDirImportPath func(string) string // return effective import path for directory
-)
-
var IgnoreImports bool // control whether we ignore imports in packages
// A Package describes a single package found in a directory.
r.dir = filepath.Join(parentDir, path)
r.path = dirToImportPath(r.dir)
} else if cfg.ModulesEnabled {
- r.dir, r.path, r.err = ModLookup(parentPath, parentIsStd, path)
+ r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
} else if mode&ResolveImport != 0 {
// We do our own path resolution, because we want to
// find out the key to use in packageCache without the
}
data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
if data.p.Root == "" && cfg.ModulesEnabled {
- if info := ModPackageModuleInfo(path); info != nil {
+ if info := modload.PackageModuleInfo(path); info != nil {
data.p.Root = info.Dir
}
}
if cfg.GOBIN != "" {
data.p.BinDir = cfg.GOBIN
} else if cfg.ModulesEnabled {
- data.p.BinDir = ModBinDir()
+ data.p.BinDir = modload.BinDir()
}
}
// to ensure preload goroutines are no longer active. This is necessary
// because of global mutable state that cannot safely be read and written
// concurrently. In particular, packageDataCache may be cleared by "go get"
-// in GOPATH mode, and modload.loaded (accessed via ModLookup) may be
-// modified by modload.ImportPaths (ModImportPaths).
+// in GOPATH mode, and modload.loaded (accessed via modload.Lookup) may be
+// modified by modload.ImportPaths (modload.ImportPaths).
type preload struct {
cancel chan struct{}
sema chan struct{}
func resolveImportPath(path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
if cfg.ModulesEnabled {
- if _, p, e := ModLookup(parentPath, parentIsStd, path); e == nil {
+ if _, p, e := modload.Lookup(parentPath, parentIsStd, path); e == nil {
return p
}
return path
// directory containing them.
// If the directory is outside the main module, this will resolve to ".",
// which is not a prefix of any valid module.
- importerPath = ModDirImportPath(importer.Dir)
+ importerPath = modload.DirImportPath(importer.Dir)
}
parentOfInternal := p.ImportPath[:i]
if str.HasPathPrefix(importerPath, parentOfInternal) {
elem = full
}
if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled {
- p.Internal.Build.BinDir = ModBinDir()
+ p.Internal.Build.BinDir = modload.BinDir()
}
if p.Internal.Build.BinDir != "" {
// Install to GOBIN or bin of GOPATH entry.
if p.Internal.CmdlineFiles {
mainPath = "command-line-arguments"
}
- p.Module = ModPackageModuleInfo(mainPath)
+ p.Module = modload.PackageModuleInfo(mainPath)
if p.Name == "main" && len(p.DepsErrors) == 0 {
- p.Internal.BuildInfo = ModPackageBuildInfo(mainPath, p.Deps)
+ p.Internal.BuildInfo = modload.PackageBuildInfo(mainPath, p.Deps)
}
}
}
}
func ImportPaths(ctx context.Context, args []string) []*search.Match {
- if ModInit(); cfg.ModulesEnabled {
- return ModImportPaths(ctx, args)
+ if modload.Init(); cfg.ModulesEnabled {
+ return modload.ImportPaths(ctx, args)
}
return search.ImportPaths(args)
}
// (typically named on the command line). The target is named p.a for
// package p or named after the first Go file for package main.
func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
- ModInit()
+ modload.Init()
for _, f := range gofiles {
if !strings.HasSuffix(f, ".go") {
ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
if cfg.ModulesEnabled {
- ModImportFromFiles(ctx, gofiles)
+ modload.ImportFromFiles(ctx, gofiles)
}
var err error
if cfg.GOBIN != "" {
pkg.Target = filepath.Join(cfg.GOBIN, exe)
} else if cfg.ModulesEnabled {
- pkg.Target = filepath.Join(ModBinDir(), exe)
+ pkg.Target = filepath.Join(modload.BinDir(), exe)
}
}
"cmd/go/internal/base"
"cmd/go/internal/cfg"
- "cmd/go/internal/load"
"cmd/go/internal/web"
)
if err == errUnknownSite {
rr, err = repoRootForImportDynamic(importPath, mod, security)
if err != nil {
- err = load.ImportErrorf(importPath, "unrecognized import path %q: %v", importPath, err)
+ err = importErrorf(importPath, "unrecognized import path %q: %v", importPath, err)
}
}
if err != nil {
if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {
// Do not allow wildcards in the repo root.
rr = nil
- err = load.ImportErrorf(importPath, "cannot expand ... in %q", importPath)
+ err = importErrorf(importPath, "cannot expand ... in %q", importPath)
}
return rr, err
}
m := srv.regexp.FindStringSubmatch(importPath)
if m == nil {
if srv.prefix != "" {
- return nil, load.ImportErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath)
+ return nil, importErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath)
}
continue
}
}
return nil
}
+
+// importError is a copy of load.importError, made to avoid a dependency cycle
+// on cmd/go/internal/load. It just needs to satisfy load.ImportPathError.
+type importError struct {
+ importPath string
+ err error
+}
+
+func importErrorf(path, format string, args ...interface{}) error {
+ err := &importError{importPath: path, err: fmt.Errorf(format, args...)}
+ if errStr := err.Error(); !strings.Contains(errStr, path) {
+ panic(fmt.Sprintf("path %q not in error %q", path, errStr))
+ }
+ return err
+}
+
+func (e *importError) Error() string {
+ return e.err.Error()
+}
+
+func (e *importError) Unwrap() error {
+ // Don't return e.err directly, since we're only wrapping an error if %w
+ // was passed to ImportErrorf.
+ return errors.Unwrap(e.err)
+}
+
+func (e *importError) ImportPath() string {
+ return e.importPath
+}