Skip to content

Commit 5522f8c

Browse files
author
Bryan C. Mills
committed
cmd/go: fix relative-path normalization in go.work files
We had been statting 'dir' instead of 'absDir', which statted the wrong directory if 'dir' was made relative to the location of the go.work file and that location was different from the current working directory. While we're here, I also noticed some other dir-vs.-absDir discrepancies. The haveDirs map had assumed relative, slash-separated filesystem paths, but absolute paths on Windows are not slash-separated and we do retain those. Moreover, if users hand-edit the go.work file they may introduce non-canonical paths. I have changed the haveDirs logic to retain absolute paths in their platform-specific forms, and to call DropUse with the original path from the go.work file instead of the newly-resolved path. Fixes #50931 Updates #48257 Change-Id: Ib0a46179aa20c99f045aac5c7c02dbb55da455c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/382240 Trust: Bryan Mills <[email protected]> Run-TryBot: Bryan Mills <[email protected]> Reviewed-by: Michael Matloob <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent e22a14b commit 5522f8c

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

src/cmd/go/internal/workcmd/use.go

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ func init() {
4343
}
4444

4545
func runUse(ctx context.Context, cmd *base.Command, args []string) {
46-
modload.InitWorkfile()
47-
4846
modload.ForceUseModules = true
4947

5048
var gowork string
@@ -56,29 +54,42 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
5654
base.Fatalf("go: %v", err)
5755
}
5856

59-
haveDirs := make(map[string]bool)
60-
for _, dir := range workFile.Use {
61-
haveDirs[filepath.Join(filepath.Dir(gowork), filepath.FromSlash(dir.Path))] = true
57+
haveDirs := make(map[string][]string) // absolute → original(s)
58+
for _, use := range workFile.Use {
59+
var absDir string
60+
if filepath.IsAbs(use.Path) {
61+
absDir = filepath.Clean(use.Path)
62+
} else {
63+
absDir = filepath.Join(filepath.Dir(gowork), use.Path)
64+
}
65+
haveDirs[absDir] = append(haveDirs[absDir], use.Path)
6266
}
6367

6468
addDirs := make(map[string]bool)
6569
removeDirs := make(map[string]bool)
6670
lookDir := func(dir string) {
67-
absDir := filepath.Join(base.Cwd(), dir)
68-
// If the path is absolute, keep it absolute. If it's relative,
71+
// If the path is absolute, try to keep it absolute. If it's relative,
6972
// make it relative to the go.work file rather than the working directory.
73+
absDir := dir
7074
if !filepath.IsAbs(dir) {
75+
absDir = filepath.Join(base.Cwd(), dir)
7176
rel, err := filepath.Rel(filepath.Dir(gowork), absDir)
7277
if err == nil {
73-
dir = rel
78+
// Normalize relative paths to use slashes, so that checked-in go.work
79+
// files with relative paths within the repo are platform-independent.
80+
dir = filepath.ToSlash(rel)
81+
} else {
82+
// The path can't be made relative to the go.work file,
83+
// so it must be kept absolute instead.
84+
dir = absDir
7485
}
7586
}
76-
fi, err := os.Stat(filepath.Join(dir, "go.mod"))
87+
88+
fi, err := os.Stat(filepath.Join(absDir, "go.mod"))
7789
if err != nil {
7890
if os.IsNotExist(err) {
79-
80-
if haveDirs[absDir] {
81-
removeDirs[dir] = true
91+
for _, origDir := range haveDirs[absDir] {
92+
removeDirs[origDir] = true
8293
}
8394
return
8495
}
@@ -89,7 +100,7 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
89100
base.Errorf("go: %v is not regular", filepath.Join(dir, "go.mod"))
90101
}
91102

92-
if !haveDirs[absDir] {
103+
if len(haveDirs[absDir]) == 0 {
93104
addDirs[dir] = true
94105
}
95106
}
@@ -109,10 +120,10 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
109120
}
110121

111122
for dir := range removeDirs {
112-
workFile.DropUse(filepath.ToSlash(dir))
123+
workFile.DropUse(dir)
113124
}
114125
for dir := range addDirs {
115-
workFile.AddUse(filepath.ToSlash(dir), "")
126+
workFile.AddUse(dir, "")
116127
}
117128
modload.UpdateWorkFile(workFile)
118129
modload.WriteWorkFile(gowork, workFile)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
cp go.work go.work.orig
2+
3+
# 'go work use .' should add an entry for the current directory.
4+
cd bar/baz
5+
go work use .
6+
cmp ../../go.work ../../go.work.rel
7+
8+
# If the current directory lacks a go.mod file, 'go work use .'
9+
# should remove its entry.
10+
mv go.mod go.mod.bak
11+
go work use .
12+
cmp ../../go.work ../../go.work.orig
13+
14+
mv go.mod.bak go.mod
15+
go work use $PWD
16+
cmpenv ../../go.work ../../go.work.abs
17+
18+
-- go.mod --
19+
module example
20+
go 1.18
21+
-- go.work --
22+
go 1.18
23+
-- go.work.rel --
24+
go 1.18
25+
26+
use bar/baz
27+
-- go.work.abs --
28+
go 1.18
29+
30+
use $PWD
31+
-- bar/baz/go.mod --
32+
module example/bar/baz
33+
go 1.18

0 commit comments

Comments
 (0)