Skip to content

Commit

Permalink
prune: Decode directly from TOML types
Browse files Browse the repository at this point in the history
Our TOML lib doesn't support decoding directly into interface{} types,
so our only short-term choice is to decode...for a third time, and
operate directly on that.
  • Loading branch information
sdboyer committed Jan 24, 2018
1 parent 877b793 commit ece3342
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 148 deletions.
101 changes: 51 additions & 50 deletions manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ type rawPruneOptions struct {
NonGoFiles bool `toml:"non-go,omitempty"`
GoTests bool `toml:"go-tests,omitempty"`

Projects []map[string]interface{} `toml:"project,omitempty"`
//Projects []map[string]interface{} `toml:"project,omitempty"`
Projects []map[string]interface{}
}

const (
Expand Down Expand Up @@ -351,12 +352,16 @@ func readManifest(r io.Reader) (*Manifest, []error, error) {
return nil, warns, errors.Wrap(err, "unable to parse the manifest as TOML")
}

m, err := fromRawManifest(raw)
//warns = append(warns, checkRedundantPruneOptions(m)...)
return m, warns, err
m, err := fromRawManifest(raw, buf)
if err != nil {
return nil, warns, err
}

warns = append(warns, checkRedundantPruneOptions(m.PruneOptions)...)
return m, warns, nil
}

func fromRawManifest(raw rawManifest) (*Manifest, error) {
func fromRawManifest(raw rawManifest, buf *bytes.Buffer) (*Manifest, error) {
m := NewManifest()

m.Constraints = make(gps.ProjectConstraints, len(raw.Constraints))
Expand Down Expand Up @@ -386,74 +391,70 @@ func fromRawManifest(raw rawManifest) (*Manifest, error) {
m.Ovr[name] = prj
}

var err error
m.PruneOptions, err = fromRawPruneOptions(raw.PruneOptions)
// TODO(sdboyer) it is awful that we have to do this manual extraction
tree, err := toml.Load(buf.String())
if err != nil {
return nil, err
return nil, errors.Wrap(err, "unable to load TomlTree from string")
}

iprunemap := tree.Get("prune")
if iprunemap == nil {
return m, nil
}
// Previous validation already guaranteed that, if it exists, it's this map
// type.
m.PruneOptions = fromRawPruneOptions(iprunemap.(*toml.Tree).ToMap())

return m, nil
}

func fromRawPruneOptions(raw rawPruneOptions) (gps.CascadingPruneOptions, error) {
func fromRawPruneOptions(prunemap map[string]interface{}) gps.CascadingPruneOptions {
opts := gps.CascadingPruneOptions{
DefaultOptions: gps.PruneNestedVendorDirs,
PerProjectOptions: make(map[gps.ProjectRoot]gps.PruneOptionSet),
}

if raw.UnusedPackages {
if val, has := prunemap[pruneOptionUnusedPackages]; has && val.(bool) {
opts.DefaultOptions |= gps.PruneUnusedPackages
}
if raw.GoTests {
opts.DefaultOptions |= gps.PruneGoTestFiles
}
if raw.NonGoFiles {
if val, has := prunemap[pruneOptionNonGo]; has && val.(bool) {
opts.DefaultOptions |= gps.PruneNonGoFiles
}
if val, has := prunemap[pruneOptionGoTests]; has && val.(bool) {
opts.DefaultOptions |= gps.PruneGoTestFiles
}

for _, p := range raw.Projects {
name, has := p["name"]
if !has {
return gps.CascadingPruneOptions{}, errors.Errorf("no name field declared for per-project prune options")
}
if name.(string) == "" {
return gps.CascadingPruneOptions{}, errors.Errorf("empty name field in per-project prune options")
trinary := func(v interface{}) uint8 {
b := v.(bool)
if b {
return pvtrue
}
return pvfalse
}

pr := gps.ProjectRoot(name.(string))
pos := gps.PruneOptionSet{
if projprunes, has := prunemap["project"]; has {
for _, proj := range projprunes.([]interface{}) {
var pr gps.ProjectRoot
// This should be redundant, but being explicit doesn't hurt.
NestedVendor: pvtrue,
}

if val, has := p[pruneOptionUnusedPackages]; has {
if val.(bool) {
pos.UnusedPackages = pvtrue
} else {
pos.UnusedPackages = pvfalse
}
}

if val, has := p[pruneOptionGoTests]; has {
if val.(bool) {
pos.GoTests = pvtrue
} else {
pos.GoTests = pvfalse
}
}

if val, has := p[pruneOptionNonGo]; has {
if val.(bool) {
pos.NonGoFiles = pvtrue
} else {
pos.NonGoFiles = pvfalse
pos := gps.PruneOptionSet{NestedVendor: pvtrue}

for key, val := range proj.(map[string]interface{}) {
switch key {
case "name":
pr = gps.ProjectRoot(val.(string))
case pruneOptionNonGo:
pos.NonGoFiles = trinary(val)
case pruneOptionGoTests:
pos.GoTests = trinary(val)
case pruneOptionUnusedPackages:
pos.UnusedPackages = trinary(val)
}
}
opts.PerProjectOptions[pr] = pos
}

opts.PerProjectOptions[pr] = pos
}

return opts, nil
return opts
}

// toRawPruneOptions converts a gps.RootPruneOption's PruneOptions to rawPruneOptions
Expand Down
196 changes: 98 additions & 98 deletions manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -658,104 +658,104 @@ func TestValidateProjectRoots(t *testing.T) {
}
}

func TestFromRawPruneOptions(t *testing.T) {
cases := []struct {
name string
rawPruneOptions rawPruneOptions
wantOptions gps.CascadingPruneOptions
}{
{
name: "global all options project no options",
rawPruneOptions: rawPruneOptions{
UnusedPackages: true,
NonGoFiles: true,
GoTests: true,
Projects: []map[string]interface{}{
{
"name": "github.com/golang/dep",
pruneOptionUnusedPackages: false,
pruneOptionNonGo: false,
pruneOptionGoTests: false,
},
},
},
wantOptions: gps.CascadingPruneOptions{
DefaultOptions: 15,
PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
"github.com/golang/dep": gps.PruneOptionSet{
NestedVendor: pvtrue,
UnusedPackages: pvfalse,
NonGoFiles: pvfalse,
GoTests: pvfalse,
},
},
},
},
{
name: "global all options project mixed options",
rawPruneOptions: rawPruneOptions{
UnusedPackages: true,
NonGoFiles: true,
GoTests: true,
Projects: []map[string]interface{}{
{
"name": "github.com/golang/dep",
pruneOptionUnusedPackages: false,
},
},
},
wantOptions: gps.CascadingPruneOptions{
DefaultOptions: 15,
PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
"github.com/golang/dep": gps.PruneOptionSet{
NestedVendor: pvtrue,
UnusedPackages: pvfalse,
},
},
},
},
{
name: "global no options project all options",
rawPruneOptions: rawPruneOptions{
UnusedPackages: false,
NonGoFiles: false,
GoTests: false,
Projects: []map[string]interface{}{
{
"name": "github.com/golang/dep",
pruneOptionUnusedPackages: true,
pruneOptionNonGo: true,
pruneOptionGoTests: true,
},
},
},
wantOptions: gps.CascadingPruneOptions{
DefaultOptions: 1,
PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
"github.com/golang/dep": gps.PruneOptionSet{
NestedVendor: pvtrue,
UnusedPackages: pvtrue,
NonGoFiles: pvtrue,
GoTests: pvtrue,
},
},
},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
opts, err := fromRawPruneOptions(c.rawPruneOptions)
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(opts, c.wantOptions) {
t.Fatalf("rawPruneOptions are not as expected:\n\t(GOT) %v\n\t(WNT) %v", opts, c.wantOptions)
}
})
}
}
//func TestFromRawPruneOptions(t *testing.T) {
//cases := []struct {
//name string
//rawPruneOptions rawPruneOptions
//wantOptions gps.CascadingPruneOptions
//}{
//{
//name: "global all options project no options",
//rawPruneOptions: rawPruneOptions{
//UnusedPackages: true,
//NonGoFiles: true,
//GoTests: true,
//Projects: []map[string]interface{}{
//{
//"name": "github.com/golang/dep",
//pruneOptionUnusedPackages: false,
//pruneOptionNonGo: false,
//pruneOptionGoTests: false,
//},
//},
//},
//wantOptions: gps.CascadingPruneOptions{
//DefaultOptions: 15,
//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
//"github.com/golang/dep": gps.PruneOptionSet{
//NestedVendor: pvtrue,
//UnusedPackages: pvfalse,
//NonGoFiles: pvfalse,
//GoTests: pvfalse,
//},
//},
//},
//},
//{
//name: "global all options project mixed options",
//rawPruneOptions: rawPruneOptions{
//UnusedPackages: true,
//NonGoFiles: true,
//GoTests: true,
//Projects: []map[string]interface{}{
//{
//"name": "github.com/golang/dep",
//pruneOptionUnusedPackages: false,
//},
//},
//},
//wantOptions: gps.CascadingPruneOptions{
//DefaultOptions: 15,
//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
//"github.com/golang/dep": gps.PruneOptionSet{
//NestedVendor: pvtrue,
//UnusedPackages: pvfalse,
//},
//},
//},
//},
//{
//name: "global no options project all options",
//rawPruneOptions: rawPruneOptions{
//UnusedPackages: false,
//NonGoFiles: false,
//GoTests: false,
//Projects: []map[string]interface{}{
//{
//"name": "github.com/golang/dep",
//pruneOptionUnusedPackages: true,
//pruneOptionNonGo: true,
//pruneOptionGoTests: true,
//},
//},
//},
//wantOptions: gps.CascadingPruneOptions{
//DefaultOptions: 1,
//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{
//"github.com/golang/dep": gps.PruneOptionSet{
//NestedVendor: pvtrue,
//UnusedPackages: pvtrue,
//NonGoFiles: pvtrue,
//GoTests: pvtrue,
//},
//},
//},
//},
//}

//for _, c := range cases {
//t.Run(c.name, func(t *testing.T) {
//opts, err := fromRawPruneOptions(c.rawPruneOptions)
//if err != nil {
//t.Fatal(err)
//}

//if !reflect.DeepEqual(opts, c.wantOptions) {
//t.Fatalf("rawPruneOptions are not as expected:\n\t(GOT) %v\n\t(WNT) %v", opts, c.wantOptions)
//}
//})
//}
//}

func TestToRawPruneOptions(t *testing.T) {
cases := []struct {
Expand Down

0 comments on commit ece3342

Please sign in to comment.