Skip to content

Commit a0a5cf4

Browse files
committed
Test mergeReplaceDirectives with duplicate module
1 parent 2edc6c8 commit a0a5cf4

File tree

10 files changed

+121
-12
lines changed

10 files changed

+121
-12
lines changed

pkg/commands/internal/builder.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -168,29 +168,51 @@ func (b Builder) addReplaceDirective(ctx context.Context, plugin *Plugin) error
168168
return nil
169169
}
170170

171-
func (b Builder) mergeReplaceDirectives(ctx context.Context, pluginPath string) error {
171+
type goModReplace struct {
172+
Replace []struct {
173+
Old struct{ Path, Version string }
174+
New struct{ Path, Version string }
175+
}
176+
}
177+
178+
func readGoModReplace(ctx context.Context, dir string) (*goModReplace, error) {
172179
cmd := exec.CommandContext(ctx, "go", "mod", "edit", "-json")
173-
cmd.Dir = pluginPath
180+
cmd.Dir = dir
174181

175182
output, err := cmd.CombinedOutput()
176183
if err != nil {
177-
b.log.Warnf("%s", string(output))
184+
return nil, fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err)
185+
}
178186

179-
return fmt.Errorf("%s: %w", strings.Join(cmd.Args, " "), err)
187+
var goMod goModReplace
188+
err = json.Unmarshal(output, &goMod)
189+
if err != nil {
190+
return nil, fmt.Errorf("unmarshal go.mod json: %w", err)
180191
}
181192

182-
var goMod struct {
183-
Replace []struct {
184-
Old struct{ Path, Version string }
185-
New struct{ Path, Version string }
186-
}
193+
return &goMod, nil
194+
}
195+
196+
func (b Builder) mergeReplaceDirectives(ctx context.Context, pluginPath string) error {
197+
pluginGoMod, err := readGoModReplace(ctx, pluginPath)
198+
if err != nil {
199+
return err
187200
}
188-
err = json.Unmarshal(output, &goMod)
201+
202+
rootGoMod, err := readGoModReplace(ctx, b.repo)
189203
if err != nil {
190-
return fmt.Errorf("unmarshal go mod json: %w", err)
204+
return err
205+
}
206+
207+
for _, r := range pluginGoMod.Replace {
208+
for _, rr := range rootGoMod.Replace {
209+
if r.Old.Path == rr.Old.Path && r.Old.Version == rr.Old.Version {
210+
return fmt.Errorf("duplicate replace directive for %s@%s", r.Old.Path, r.Old.Version)
211+
}
212+
}
191213
}
192214

193-
for _, r := range goMod.Replace {
215+
for _, r := range pluginGoMod.Replace {
194216
abs, err := filepath.Abs(filepath.Join(pluginPath, r.New.Path))
195217
if err != nil {
196218
return fmt.Errorf("get absolute path: %w", err)

pkg/commands/internal/builder_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,62 @@ go 1.24.0
104104
require.Len(t, goMod.Replace, 1)
105105
assert.Contains(t, goMod.Replace[0].New.Path, "testdata/plugin/target")
106106
}
107+
108+
func TestMergeReplaceDirectives_DuplicateReplace(t *testing.T) {
109+
t.Parallel()
110+
111+
tmp := t.TempDir()
112+
require.NoError(t, os.WriteFile(filepath.Join(tmp, "go.mod"), []byte(`
113+
module github.com/golangci/golangci-lint/v2
114+
go 1.24.0
115+
`), 0o600))
116+
require.NoError(t, os.Mkdir(filepath.Join(tmp, "golangci-lint"), 0o700))
117+
118+
// Both plugins define a replace directive for example.com/target.
119+
b := NewBuilder(nil, &Configuration{Plugins: []*Plugin{
120+
{Module: "example.com/plugin", Path: "testdata/plugin"},
121+
{Module: "example.com/plugin2", Path: "testdata/plugin2"},
122+
}}, tmp)
123+
124+
err := b.mergeReplaceDirectives(t.Context(), filepath.Join("testdata", "plugin"))
125+
require.NoError(t, err)
126+
127+
err = b.mergeReplaceDirectives(t.Context(), filepath.Join("testdata", "plugin2"))
128+
assert.ErrorContains(t, err, "duplicate replace directive for example.com/target")
129+
}
130+
131+
func TestMergeReplaceDirectives_DuplicateButDifferentVersion(t *testing.T) {
132+
t.Parallel()
133+
134+
tmp := t.TempDir()
135+
require.NoError(t, os.WriteFile(filepath.Join(tmp, "go.mod"), []byte(`
136+
module github.com/golangci/golangci-lint/v2
137+
go 1.24.0
138+
`), 0o600))
139+
require.NoError(t, os.Mkdir(filepath.Join(tmp, "golangci-lint"), 0o700))
140+
141+
// Both plugins define a replace directive for example.com/target.
142+
b := NewBuilder(nil, &Configuration{Plugins: []*Plugin{
143+
{Module: "example.com/plugin", Path: "testdata/plugin"},
144+
{Module: "example.com/plugin3", Path: "testdata/plugin3"},
145+
}}, tmp)
146+
147+
err := b.mergeReplaceDirectives(t.Context(), filepath.Join("testdata", "plugin"))
148+
require.NoError(t, err)
149+
150+
err = b.mergeReplaceDirectives(t.Context(), filepath.Join("testdata", "plugin3"))
151+
require.NoError(t, err)
152+
153+
cmd := exec.CommandContext(t.Context(), "go", "mod", "edit", "-json")
154+
cmd.Dir = b.repo
155+
output, err := cmd.CombinedOutput()
156+
require.NoError(t, err)
157+
158+
var goMod struct {
159+
Replace []struct{ New struct{ Path string } }
160+
}
161+
err = json.Unmarshal(output, &goMod)
162+
require.NoError(t, err)
163+
164+
assert.Len(t, goMod.Replace, 2)
165+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module example.com/plugin2
2+
3+
go 1.24.0
4+
5+
require example.com/target v0.0.0
6+
7+
replace example.com/target => ./target
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package plugin
2+
3+
import _ "example.com/target"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module example.com/target
2+
3+
go 1.24.0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package target
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module example.com/plugin2
2+
3+
go 1.24.0
4+
5+
require example.com/target v1.0.0
6+
7+
replace example.com/[email protected] => ./target
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package plugin
2+
3+
import _ "example.com/target"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module example.com/target
2+
3+
go 1.24.0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package target

0 commit comments

Comments
 (0)