mirror of
https://github.com/golang/go
synced 2024-11-02 11:50:30 +00:00
cmd/go: improve the creation and editing of go.work files
This change changes go.work files so that directory paths are clearly distinguished from module paths by either being rooted absolute paths or starting with '.' or '..' path elements if they are relative paths. go mod initwork now checks that the go.work file doesn't already exist before creating it, and gomod initwork and gomod editwork look up the module path corresponding to a directory and write it to the directory directive's comment. For #45713 Change-Id: I6983779059b7de6fc83d359280ceffb263f6b641 Reviewed-on: https://go-review.googlesource.com/c/go/+/347591 Trust: Michael Matloob <matloob@golang.org> Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
parent
c8d4fe2adc
commit
37c9552e06
5 changed files with 83 additions and 40 deletions
|
@ -15,6 +15,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
|
@ -191,7 +192,13 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
|
|||
// flagEditworkDirectory implements the -directory flag.
|
||||
func flagEditworkDirectory(arg string) {
|
||||
workedits = append(workedits, func(f *modfile.WorkFile) {
|
||||
if err := f.AddDirectory(arg, ""); err != nil {
|
||||
_, mf, err := modload.ReadModFile(filepath.Join(arg, "go.mod"), nil)
|
||||
modulePath := ""
|
||||
if err == nil {
|
||||
modulePath = mf.Module.Mod.Path
|
||||
}
|
||||
f.AddDirectory(modload.ToDirectoryPath(arg), modulePath)
|
||||
if err := f.AddDirectory(modload.ToDirectoryPath(arg), ""); err != nil {
|
||||
base.Fatalf("go mod: -directory=%s: %v", arg, err)
|
||||
}
|
||||
})
|
||||
|
@ -200,7 +207,7 @@ func flagEditworkDirectory(arg string) {
|
|||
// flagEditworkDropDirectory implements the -dropdirectory flag.
|
||||
func flagEditworkDropDirectory(arg string) {
|
||||
workedits = append(workedits, func(f *modfile.WorkFile) {
|
||||
if err := f.DropDirectory(arg); err != nil {
|
||||
if err := f.DropDirectory(modload.ToDirectoryPath(arg)); err != nil {
|
||||
base.Fatalf("go mod: -dropdirectory=%s: %v", arg, err)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -634,31 +634,12 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
|||
var indices []*modFileIndex
|
||||
for _, modroot := range modRoots {
|
||||
gomod := modFilePath(modroot)
|
||||
var data []byte
|
||||
var err error
|
||||
if gomodActual, ok := fsys.OverlayPath(gomod); ok {
|
||||
// Don't lock go.mod if it's part of the overlay.
|
||||
// On Plan 9, locking requires chmod, and we don't want to modify any file
|
||||
// in the overlay. See #44700.
|
||||
data, err = os.ReadFile(gomodActual)
|
||||
} else {
|
||||
data, err = lockedfile.Read(gomodActual)
|
||||
}
|
||||
var fixed bool
|
||||
data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed))
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
|
||||
var fixed bool
|
||||
f, err := modfile.Parse(gomod, data, fixVersion(ctx, &fixed))
|
||||
if err != nil {
|
||||
// Errors returned by modfile.Parse begin with file:line.
|
||||
base.Fatalf("go: errors parsing go.mod:\n%s\n", err)
|
||||
}
|
||||
if f.Module == nil {
|
||||
// No module declaration. Must add module path.
|
||||
base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
|
||||
}
|
||||
|
||||
modFiles = append(modFiles, f)
|
||||
mainModule := f.Module.Mod
|
||||
mainModules = append(mainModules, mainModule)
|
||||
|
@ -819,7 +800,9 @@ func CreateModFile(ctx context.Context, modPath string) {
|
|||
|
||||
// CreateWorkFile initializes a new workspace by creating a go.work file.
|
||||
func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) {
|
||||
_ = TODOWorkspaces("Report an error if the file already exists.")
|
||||
if _, err := fsys.Stat(workFile); err == nil {
|
||||
base.Fatalf("go: %s already exists", workFile)
|
||||
}
|
||||
|
||||
goV := LatestGoVersion() // Use current Go version by default
|
||||
workF := new(modfile.WorkFile)
|
||||
|
@ -827,12 +810,18 @@ func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) {
|
|||
workF.AddGoStmt(goV)
|
||||
|
||||
for _, dir := range modDirs {
|
||||
_ = TODOWorkspaces("Add the module path of the module.")
|
||||
workF.AddDirectory(dir, "")
|
||||
_, f, err := ReadModFile(filepath.Join(dir, "go.mod"), nil)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
base.Fatalf("go: creating workspace file: no go.mod file exists in directory %v", dir)
|
||||
}
|
||||
base.Fatalf("go: error parsing go.mod in directory %s: %v", dir, err)
|
||||
}
|
||||
workF.AddDirectory(ToDirectoryPath(dir), f.Module.Mod.Path)
|
||||
}
|
||||
|
||||
data := modfile.Format(workF.Syntax)
|
||||
lockedfile.Write(workFile, bytes.NewReader(data), 0644)
|
||||
lockedfile.Write(workFile, bytes.NewReader(data), 0666)
|
||||
}
|
||||
|
||||
// fixVersion returns a modfile.VersionFixer implemented using the Query function.
|
||||
|
|
|
@ -47,6 +47,34 @@ const (
|
|||
separateIndirectVersionV = "v1.17"
|
||||
)
|
||||
|
||||
// ReadModFile reads and parses the mod file at gomod. ReadModFile properly applies the
|
||||
// overlay, locks the file while reading, and applies fix, if applicable.
|
||||
func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfile.File, err error) {
|
||||
if gomodActual, ok := fsys.OverlayPath(gomod); ok {
|
||||
// Don't lock go.mod if it's part of the overlay.
|
||||
// On Plan 9, locking requires chmod, and we don't want to modify any file
|
||||
// in the overlay. See #44700.
|
||||
data, err = os.ReadFile(gomodActual)
|
||||
} else {
|
||||
data, err = lockedfile.Read(gomodActual)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
f, err = modfile.Parse(gomod, data, fix)
|
||||
if err != nil {
|
||||
// Errors returned by modfile.Parse begin with file:line.
|
||||
return nil, nil, fmt.Errorf("errors parsing go.mod:\n%s\n", err)
|
||||
}
|
||||
if f.Module == nil {
|
||||
// No module declaration. Must add module path.
|
||||
return nil, nil, errors.New("no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
|
||||
}
|
||||
|
||||
return data, f, err
|
||||
}
|
||||
|
||||
// modFileGoVersion returns the (non-empty) Go version at which the requirements
|
||||
// in modFile are interpreted, or the latest Go version if modFile is nil.
|
||||
func modFileGoVersion(modFile *modfile.File) string {
|
||||
|
@ -739,3 +767,15 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la
|
|||
}
|
||||
|
||||
var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result
|
||||
|
||||
// ToDirectoryPath adds a prefix if necessary so that path in unambiguously
|
||||
// an absolute path or a relative path starting with a '.' or '..'
|
||||
// path component.
|
||||
func ToDirectoryPath(path string) string {
|
||||
if modfile.IsDirectoryPath(path) {
|
||||
return path
|
||||
}
|
||||
// The path is not a relative path or an absolute path, so make it relative
|
||||
// to the current directory.
|
||||
return "./" + filepath.ToSlash(filepath.Clean(path))
|
||||
}
|
||||
|
|
3
src/cmd/go/testdata/script/work.txt
vendored
3
src/cmd/go/testdata/script/work.txt
vendored
|
@ -1,3 +1,6 @@
|
|||
! go mod initwork doesnotexist
|
||||
stderr 'go: creating workspace file: no go.mod file exists in directory doesnotexist'
|
||||
|
||||
go mod initwork ./a ./b
|
||||
cmp go.work go.work.want
|
||||
|
||||
|
|
30
src/cmd/go/testdata/script/work_edit.txt
vendored
30
src/cmd/go/testdata/script/work_edit.txt
vendored
|
@ -33,32 +33,36 @@ cmp stdout go.work.want_json
|
|||
go mod editwork -print -fmt -workfile unformatted
|
||||
cmp stdout formatted
|
||||
|
||||
-- m/go.mod --
|
||||
module m
|
||||
|
||||
go 1.18
|
||||
-- go.work.want_initial --
|
||||
go 1.18
|
||||
|
||||
directory m
|
||||
directory ./m
|
||||
-- go.work.want_directory_n --
|
||||
go 1.18
|
||||
|
||||
directory (
|
||||
m
|
||||
n
|
||||
./m
|
||||
./n
|
||||
)
|
||||
-- go.work.want_go_118 --
|
||||
go 1.18
|
||||
|
||||
directory (
|
||||
m
|
||||
n
|
||||
./m
|
||||
./n
|
||||
)
|
||||
-- go.work.want_dropdirectory_m --
|
||||
go 1.18
|
||||
|
||||
directory n
|
||||
directory ./n
|
||||
-- go.work.want_add_replaces --
|
||||
go 1.18
|
||||
|
||||
directory n
|
||||
directory ./n
|
||||
|
||||
replace (
|
||||
x.1 v1.3.0 => y.1 v1.4.0
|
||||
|
@ -69,9 +73,9 @@ go 1.18
|
|||
|
||||
directory (
|
||||
../a
|
||||
./c
|
||||
./n
|
||||
/b
|
||||
c
|
||||
n
|
||||
)
|
||||
|
||||
replace (
|
||||
|
@ -83,7 +87,7 @@ go 1.18
|
|||
|
||||
directory (
|
||||
../a
|
||||
c
|
||||
./c
|
||||
)
|
||||
|
||||
replace (
|
||||
|
@ -95,7 +99,7 @@ go 1.18
|
|||
|
||||
directory (
|
||||
../a
|
||||
c
|
||||
./c
|
||||
)
|
||||
|
||||
replace x.1 v1.3.0 => y.1 v1.4.0
|
||||
|
@ -104,7 +108,7 @@ go 1.19
|
|||
|
||||
directory (
|
||||
../a
|
||||
b
|
||||
./b
|
||||
)
|
||||
|
||||
replace x.1 v1.4.0 => ../z
|
||||
|
@ -116,7 +120,7 @@ replace x.1 v1.4.0 => ../z
|
|||
"DiskPath": "../a"
|
||||
},
|
||||
{
|
||||
"DiskPath": "b"
|
||||
"DiskPath": "./b"
|
||||
}
|
||||
],
|
||||
"Replace": [
|
||||
|
|
Loading…
Reference in a new issue