mirror of https://github.com/golang/go.git
cmd/go: refactor modload.InitMod
InitMod is split into two functions. LoadModFile parses an existing go.mod file and loads the build list (or checks vendor/modules.txt for consistency in vendor mode). CreateModFile creates a new go.mod file, possibly inferring the module path and importing a vendor configuration file. Some logic is moved from runInit to CreateModFile. init-specific logic is removed from other functions. This CL shouldn't cause substantial differences in behavior, though some error messages are slightly different. For #41712 Change-Id: Ia684945cfcf5beca30bbb81e7144fc246c4f27ed Reviewed-on: https://go-review.googlesource.com/c/go/+/264621 Trust: Jay Conrod <jayconrod@google.com> Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
c8c3c29daa
commit
d05e89a8fd
|
|
@ -415,7 +415,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
base.Fatalf("go list -m: not using modules")
|
base.Fatalf("go list -m: not using modules")
|
||||||
}
|
}
|
||||||
|
|
||||||
modload.InitMod(ctx) // Parses go.mod and sets cfg.BuildMod.
|
modload.LoadModFile(ctx) // Parses go.mod and sets cfg.BuildMod.
|
||||||
if cfg.BuildMod == "vendor" {
|
if cfg.BuildMod == "vendor" {
|
||||||
const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
|
const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
args = []string{"all"}
|
args = []string{"all"}
|
||||||
} else if modload.HasModRoot() {
|
} else if modload.HasModRoot() {
|
||||||
modload.InitMod(ctx) // to fill Target
|
modload.LoadModFile(ctx) // to fill Target
|
||||||
targetAtLatest := modload.Target.Path + "@latest"
|
targetAtLatest := modload.Target.Path + "@latest"
|
||||||
targetAtUpgrade := modload.Target.Path + "@upgrade"
|
targetAtUpgrade := modload.Target.Path + "@upgrade"
|
||||||
targetAtPatch := modload.Target.Path + "@patch"
|
targetAtPatch := modload.Target.Path + "@patch"
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ import (
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
"cmd/go/internal/modload"
|
"cmd/go/internal/modload"
|
||||||
"context"
|
"context"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmdInit = &base.Command{
|
var cmdInit = &base.Command{
|
||||||
|
|
@ -33,21 +31,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runInit(ctx context.Context, cmd *base.Command, args []string) {
|
func runInit(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
modload.CmdModInit = true
|
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
base.Fatalf("go mod init: too many arguments")
|
base.Fatalf("go mod init: too many arguments")
|
||||||
}
|
}
|
||||||
|
var modPath string
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
modload.CmdModModule = args[0]
|
modPath = args[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
modload.ForceUseModules = true
|
modload.ForceUseModules = true
|
||||||
modFilePath := modload.ModFilePath()
|
modload.CreateModFile(ctx, modPath) // does all the hard work
|
||||||
if _, err := os.Stat(modFilePath); err == nil {
|
|
||||||
base.Fatalf("go mod init: go.mod already exists")
|
|
||||||
}
|
|
||||||
if strings.Contains(modload.CmdModModule, "@") {
|
|
||||||
base.Fatalf("go mod init: module path must not contain '@'")
|
|
||||||
}
|
|
||||||
modload.InitMod(ctx) // does all the hard work
|
|
||||||
modload.WriteGoMod()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ var buildList []module.Version
|
||||||
//
|
//
|
||||||
// The caller must not modify the returned list.
|
// The caller must not modify the returned list.
|
||||||
func LoadAllModules(ctx context.Context) []module.Version {
|
func LoadAllModules(ctx context.Context) []module.Version {
|
||||||
InitMod(ctx)
|
LoadModFile(ctx)
|
||||||
ReloadBuildList()
|
ReloadBuildList()
|
||||||
WriteGoMod()
|
WriteGoMod()
|
||||||
return buildList
|
return buildList
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,6 @@ var (
|
||||||
|
|
||||||
gopath string
|
gopath string
|
||||||
|
|
||||||
CmdModInit bool // running 'go mod init'
|
|
||||||
CmdModModule string // module argument for 'go mod init'
|
|
||||||
|
|
||||||
// RootMode determines whether a module root is needed.
|
// RootMode determines whether a module root is needed.
|
||||||
RootMode Root
|
RootMode Root
|
||||||
|
|
||||||
|
|
@ -163,9 +160,9 @@ func Init() {
|
||||||
os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
|
os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
|
||||||
}
|
}
|
||||||
|
|
||||||
if CmdModInit {
|
if modRoot != "" {
|
||||||
// Running 'go mod init': go.mod will be created in current directory.
|
// modRoot set before Init was called ("go mod init" does this).
|
||||||
modRoot = base.Cwd
|
// No need to search for go.mod.
|
||||||
} else if RootMode == NoRoot {
|
} else if RootMode == NoRoot {
|
||||||
if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") {
|
if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") {
|
||||||
base.Fatalf("go: -modfile cannot be used with commands that ignore the current module")
|
base.Fatalf("go: -modfile cannot be used with commands that ignore the current module")
|
||||||
|
|
@ -202,8 +199,7 @@ func Init() {
|
||||||
base.Fatalf("go: -modfile=%s: file does not have .mod extension", cfg.ModFile)
|
base.Fatalf("go: -modfile=%s: file does not have .mod extension", cfg.ModFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're in module mode. Install the hooks to make it work.
|
// We're in module mode. Set any global variables that need to be set.
|
||||||
|
|
||||||
list := filepath.SplitList(cfg.BuildContext.GOPATH)
|
list := filepath.SplitList(cfg.BuildContext.GOPATH)
|
||||||
if len(list) == 0 || list[0] == "" {
|
if len(list) == 0 || list[0] == "" {
|
||||||
base.Fatalf("missing $GOPATH")
|
base.Fatalf("missing $GOPATH")
|
||||||
|
|
@ -270,10 +266,6 @@ func WillBeEnabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if CmdModInit {
|
|
||||||
// Running 'go mod init': go.mod will be created in current directory.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if modRoot := findModuleRoot(base.Cwd); modRoot == "" {
|
if modRoot := findModuleRoot(base.Cwd); modRoot == "" {
|
||||||
// GO111MODULE is 'auto', and we can't find a module root.
|
// GO111MODULE is 'auto', and we can't find a module root.
|
||||||
// Stay in GOPATH mode.
|
// Stay in GOPATH mode.
|
||||||
|
|
@ -347,16 +339,16 @@ func die() {
|
||||||
base.Fatalf("go: cannot find main module; see 'go help modules'")
|
base.Fatalf("go: cannot find main module; see 'go help modules'")
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitMod sets Target and, if there is a main module, parses the initial build
|
// LoadModFile sets Target and, if there is a main module, parses the initial
|
||||||
// list from its go.mod file. If InitMod is called by 'go mod init', InitMod
|
// build list from its go.mod file.
|
||||||
// will populate go.mod in memory, possibly importing dependencies from a
|
|
||||||
// legacy configuration file. For other commands, InitMod may make other
|
|
||||||
// adjustments in memory, like adding a go directive. WriteGoMod should be
|
|
||||||
// called later to write changes out to disk.
|
|
||||||
//
|
//
|
||||||
// As a side-effect, InitMod sets a default for cfg.BuildMod if it does not
|
// LoadModFile may make changes in memory, like adding a go directive and
|
||||||
|
// ensuring requirements are consistent. WriteGoMod should be called later to
|
||||||
|
// write changes out to disk or report errors in readonly mode.
|
||||||
|
//
|
||||||
|
// As a side-effect, LoadModFile sets a default for cfg.BuildMod if it does not
|
||||||
// already have an explicit value.
|
// already have an explicit value.
|
||||||
func InitMod(ctx context.Context) {
|
func LoadModFile(ctx context.Context) {
|
||||||
if len(buildList) > 0 {
|
if len(buildList) > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -369,13 +361,6 @@ func InitMod(ctx context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if CmdModInit {
|
|
||||||
// Running go mod init: do legacy module conversion
|
|
||||||
legacyModInit()
|
|
||||||
modFileToBuildList()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gomod := ModFilePath()
|
gomod := ModFilePath()
|
||||||
data, err := lockedfile.Read(gomod)
|
data, err := lockedfile.Read(gomod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -408,6 +393,50 @@ func InitMod(ctx context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateModFile initializes a new module by creating a go.mod file.
|
||||||
|
//
|
||||||
|
// If modPath is empty, CreateModFile will attempt to infer the path from the
|
||||||
|
// directory location within GOPATH.
|
||||||
|
//
|
||||||
|
// If a vendoring configuration file is present, CreateModFile will attempt to
|
||||||
|
// translate it to go.mod directives. The resulting build list may not be
|
||||||
|
// exactly the same as in the legacy configuration (for example, we can't get
|
||||||
|
// packages at multiple versions from the same module).
|
||||||
|
func CreateModFile(ctx context.Context, modPath string) {
|
||||||
|
modRoot = base.Cwd
|
||||||
|
Init()
|
||||||
|
modFilePath := ModFilePath()
|
||||||
|
if _, err := os.Stat(modFilePath); err == nil {
|
||||||
|
base.Fatalf("go: %s already exists", modFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if modPath == "" {
|
||||||
|
var err error
|
||||||
|
modPath, err = findModulePath(modRoot)
|
||||||
|
if err != nil {
|
||||||
|
base.Fatalf("go: %v", err)
|
||||||
|
}
|
||||||
|
} else if err := checkModulePathLax(modPath); err != nil {
|
||||||
|
base.Fatalf("go: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
|
||||||
|
modFile = new(modfile.File)
|
||||||
|
modFile.AddModuleStmt(modPath)
|
||||||
|
addGoStmt() // Add the go directive before converted module requirements.
|
||||||
|
|
||||||
|
convertedFrom, err := convertLegacyConfig(modPath)
|
||||||
|
if convertedFrom != "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
base.Fatalf("go: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modFileToBuildList()
|
||||||
|
WriteGoMod()
|
||||||
|
}
|
||||||
|
|
||||||
// checkModulePathLax checks that the path meets some minimum requirements
|
// checkModulePathLax checks that the path meets some minimum requirements
|
||||||
// to avoid confusing users or the module cache. The requirements are weaker
|
// to avoid confusing users or the module cache. The requirements are weaker
|
||||||
// than those of module.CheckPath to allow room for weakening module path
|
// than those of module.CheckPath to allow room for weakening module path
|
||||||
|
|
@ -574,34 +603,23 @@ func setDefaultBuildMod() {
|
||||||
cfg.BuildMod = "readonly"
|
cfg.BuildMod = "readonly"
|
||||||
}
|
}
|
||||||
|
|
||||||
func legacyModInit() {
|
// convertLegacyConfig imports module requirements from a legacy vendoring
|
||||||
if modFile == nil {
|
// configuration file, if one is present.
|
||||||
path, err := findModulePath(modRoot)
|
func convertLegacyConfig(modPath string) (from string, err error) {
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("go: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", path)
|
|
||||||
modFile = new(modfile.File)
|
|
||||||
modFile.AddModuleStmt(path)
|
|
||||||
addGoStmt() // Add the go directive before converted module requirements.
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range altConfigs {
|
for _, name := range altConfigs {
|
||||||
cfg := filepath.Join(modRoot, name)
|
cfg := filepath.Join(modRoot, name)
|
||||||
data, err := ioutil.ReadFile(cfg)
|
data, err := ioutil.ReadFile(cfg)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
convert := modconv.Converters[name]
|
convert := modconv.Converters[name]
|
||||||
if convert == nil {
|
if convert == nil {
|
||||||
return
|
return "", nil
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(cfg))
|
|
||||||
cfg = filepath.ToSlash(cfg)
|
cfg = filepath.ToSlash(cfg)
|
||||||
if err := modconv.ConvertLegacyConfig(modFile, cfg, data); err != nil {
|
err := modconv.ConvertLegacyConfig(modFile, cfg, data)
|
||||||
base.Fatalf("go: %v", err)
|
return name, err
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addGoStmt adds a go directive to the go.mod file if it does not already include one.
|
// addGoStmt adds a go directive to the go.mod file if it does not already include one.
|
||||||
|
|
@ -681,14 +699,6 @@ func findAltConfig(dir string) (root, name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func findModulePath(dir string) (string, error) {
|
func findModulePath(dir string) (string, error) {
|
||||||
if CmdModModule != "" {
|
|
||||||
// Running go mod init x/y/z; return x/y/z.
|
|
||||||
if err := module.CheckImportPath(CmdModModule); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return CmdModModule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(bcmills): once we have located a plausible module path, we should
|
// TODO(bcmills): once we have located a plausible module path, we should
|
||||||
// query version control (if available) to verify that it matches the major
|
// query version control (if available) to verify that it matches the major
|
||||||
// version of the most recent tag.
|
// version of the most recent tag.
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ type PackageOpts struct {
|
||||||
// LoadPackages identifies the set of packages matching the given patterns and
|
// LoadPackages identifies the set of packages matching the given patterns and
|
||||||
// loads the packages in the import graph rooted at that set.
|
// loads the packages in the import graph rooted at that set.
|
||||||
func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
|
func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
|
||||||
InitMod(ctx)
|
LoadModFile(ctx)
|
||||||
if opts.Tags == nil {
|
if opts.Tags == nil {
|
||||||
opts.Tags = imports.Tags()
|
opts.Tags = imports.Tags()
|
||||||
}
|
}
|
||||||
|
|
@ -494,7 +494,7 @@ func pathInModuleCache(dir string) string {
|
||||||
// ImportFromFiles adds modules to the build list as needed
|
// ImportFromFiles adds modules to the build list as needed
|
||||||
// to satisfy the imports in the named Go source files.
|
// to satisfy the imports in the named Go source files.
|
||||||
func ImportFromFiles(ctx context.Context, gofiles []string) {
|
func ImportFromFiles(ctx context.Context, gofiles []string) {
|
||||||
InitMod(ctx)
|
LoadModFile(ctx)
|
||||||
|
|
||||||
tags := imports.Tags()
|
tags := imports.Tags()
|
||||||
imports, testImports, err := imports.ScanFiles(gofiles, tags)
|
imports, testImports, err := imports.ScanFiles(gofiles, tags)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
|
|
||||||
! go mod init .
|
! go mod init .
|
||||||
stderr 'malformed import path'
|
stderr '^go: invalid module path "\.": is a local import path$'
|
||||||
|
|
||||||
cd x
|
cd x
|
||||||
go mod init example.com/x
|
go mod init example.com/x
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue