Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 28fb6b0

Browse files
authored
Merge pull request #1116 from darkowlzz/manifest-pr-validate
fix(manifest): validate project roots in manifest
2 parents 5a05adf + fa811f2 commit 28fb6b0

File tree

4 files changed

+166
-4
lines changed

4 files changed

+166
-4
lines changed

cmd/dep/ensure.go

+4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
160160
sm.UseDefaultSignalHandling()
161161
defer sm.Release()
162162

163+
if err := dep.ValidateProjectRoots(ctx, p.Manifest, sm); err != nil {
164+
return err
165+
}
166+
163167
params := p.MakeParams()
164168
if ctx.Verbose {
165169
params.TraceLogger = ctx.Err

cmd/dep/status.go

+4
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ func (cmd *statusCommand) Run(ctx *dep.Ctx, args []string) error {
190190
sm.UseDefaultSignalHandling()
191191
defer sm.Release()
192192

193+
if err := dep.ValidateProjectRoots(ctx, p.Manifest, sm); err != nil {
194+
return err
195+
}
196+
193197
var buf bytes.Buffer
194198
var out outputter
195199
switch {

manifest.go

+48-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"reflect"
1212
"regexp"
1313
"sort"
14+
"sync"
1415

1516
"github.com/golang/dep/internal/gps"
1617
"github.com/pelletier/go-toml"
@@ -22,10 +23,11 @@ const ManifestName = "Gopkg.toml"
2223

2324
// Errors
2425
var (
25-
errInvalidConstraint = errors.New("\"constraint\" must be a TOML array of tables")
26-
errInvalidOverride = errors.New("\"override\" must be a TOML array of tables")
27-
errInvalidRequired = errors.New("\"required\" must be a TOML list of strings")
28-
errInvalidIgnored = errors.New("\"ignored\" must be a TOML list of strings")
26+
errInvalidConstraint = errors.New("\"constraint\" must be a TOML array of tables")
27+
errInvalidOverride = errors.New("\"override\" must be a TOML array of tables")
28+
errInvalidRequired = errors.New("\"required\" must be a TOML list of strings")
29+
errInvalidIgnored = errors.New("\"ignored\" must be a TOML list of strings")
30+
errInvalidProjectRoot = errors.New("ProjectRoot name validation failed")
2931
)
3032

3133
// Manifest holds manifest file data and implements gps.RootManifest.
@@ -156,6 +158,48 @@ func validateManifest(s string) ([]error, error) {
156158
return warns, nil
157159
}
158160

161+
// ValidateProjectRoots validates the project roots present in manifest.
162+
func ValidateProjectRoots(c *Ctx, m *Manifest, sm gps.SourceManager) error {
163+
// Channel to receive all the errors
164+
errorCh := make(chan error, len(m.Constraints)+len(m.Ovr))
165+
166+
var wg sync.WaitGroup
167+
168+
validate := func(pr gps.ProjectRoot) {
169+
defer wg.Done()
170+
origPR, err := sm.DeduceProjectRoot(string(pr))
171+
if err != nil {
172+
errorCh <- err
173+
} else if origPR != pr {
174+
errorCh <- fmt.Errorf("the name for %q should be changed to %q", pr, origPR)
175+
}
176+
}
177+
178+
for pr := range m.Constraints {
179+
wg.Add(1)
180+
go validate(pr)
181+
}
182+
for pr := range m.Ovr {
183+
wg.Add(1)
184+
go validate(pr)
185+
}
186+
187+
wg.Wait()
188+
close(errorCh)
189+
190+
var valErr error
191+
if len(errorCh) > 0 {
192+
valErr = errInvalidProjectRoot
193+
c.Err.Printf("The following issues were found in Gopkg.toml:\n\n")
194+
for err := range errorCh {
195+
c.Err.Println(" ✗", err.Error())
196+
}
197+
c.Err.Println()
198+
}
199+
200+
return valErr
201+
}
202+
159203
// readManifest returns a Manifest read from r and a slice of validation warnings.
160204
func readManifest(r io.Reader) (*Manifest, []error, error) {
161205
buf := &bytes.Buffer{}

manifest_test.go

+110
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package dep
66

77
import (
8+
"bytes"
89
"errors"
10+
"io/ioutil"
11+
"log"
912
"reflect"
1013
"strings"
1114
"testing"
@@ -372,3 +375,110 @@ func TestValidateManifest(t *testing.T) {
372375
}
373376
}
374377
}
378+
379+
func TestValidateProjectRoots(t *testing.T) {
380+
cases := []struct {
381+
name string
382+
manifest Manifest
383+
wantError error
384+
wantWarn []string
385+
}{
386+
{
387+
name: "empty Manifest",
388+
manifest: Manifest{},
389+
wantError: nil,
390+
wantWarn: []string{},
391+
},
392+
{
393+
name: "valid project root",
394+
manifest: Manifest{
395+
Constraints: map[gps.ProjectRoot]gps.ProjectProperties{
396+
gps.ProjectRoot("github.com/golang/dep"): {
397+
Constraint: gps.Any(),
398+
},
399+
},
400+
},
401+
wantError: nil,
402+
wantWarn: []string{},
403+
},
404+
{
405+
name: "invalid project roots in Constraints and Overrides",
406+
manifest: Manifest{
407+
Constraints: map[gps.ProjectRoot]gps.ProjectProperties{
408+
gps.ProjectRoot("github.com/golang/dep/foo"): {
409+
Constraint: gps.Any(),
410+
},
411+
gps.ProjectRoot("github.com/golang/go/xyz"): {
412+
Constraint: gps.Any(),
413+
},
414+
gps.ProjectRoot("github.com/golang/fmt"): {
415+
Constraint: gps.Any(),
416+
},
417+
},
418+
Ovr: map[gps.ProjectRoot]gps.ProjectProperties{
419+
gps.ProjectRoot("github.com/golang/mock/bar"): {
420+
Constraint: gps.Any(),
421+
},
422+
gps.ProjectRoot("github.com/golang/mock"): {
423+
Constraint: gps.Any(),
424+
},
425+
},
426+
},
427+
wantError: errInvalidProjectRoot,
428+
wantWarn: []string{
429+
"the name for \"github.com/golang/dep/foo\" should be changed to \"github.com/golang/dep\"",
430+
"the name for \"github.com/golang/mock/bar\" should be changed to \"github.com/golang/mock\"",
431+
"the name for \"github.com/golang/go/xyz\" should be changed to \"github.com/golang/go\"",
432+
},
433+
},
434+
{
435+
name: "invalid source path",
436+
manifest: Manifest{
437+
Constraints: map[gps.ProjectRoot]gps.ProjectProperties{
438+
gps.ProjectRoot("github.com/golang"): {
439+
Constraint: gps.Any(),
440+
},
441+
},
442+
},
443+
wantError: errInvalidProjectRoot,
444+
wantWarn: []string{},
445+
},
446+
}
447+
448+
h := test.NewHelper(t)
449+
defer h.Cleanup()
450+
451+
h.TempDir("src")
452+
pwd := h.Path(".")
453+
454+
// Capture the stderr to verify the warnings
455+
stderrOutput := &bytes.Buffer{}
456+
errLogger := log.New(stderrOutput, "", 0)
457+
ctx := &Ctx{
458+
GOPATH: pwd,
459+
Out: log.New(ioutil.Discard, "", 0),
460+
Err: errLogger,
461+
}
462+
463+
sm, err := ctx.SourceManager()
464+
h.Must(err)
465+
defer sm.Release()
466+
467+
for _, c := range cases {
468+
t.Run(c.name, func(t *testing.T) {
469+
// Empty the buffer for every case
470+
stderrOutput.Reset()
471+
err := ValidateProjectRoots(ctx, &c.manifest, sm)
472+
if err != c.wantError {
473+
t.Fatalf("Unexpected error while validating project roots:\n\t(GOT): %v\n\t(WNT): %v", err, c.wantError)
474+
}
475+
476+
warnings := stderrOutput.String()
477+
for _, warn := range c.wantWarn {
478+
if !strings.Contains(warnings, warn) {
479+
t.Fatalf("Expected ValidateProjectRoot errors to contain: %q", warn)
480+
}
481+
}
482+
})
483+
}
484+
}

0 commit comments

Comments
 (0)