Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"path"
"text/template"

"github.com/dmgk/modules2tuple/spack"
"github.com/dmgk/modules2tuple/tuple"
)

Expand All @@ -28,7 +29,21 @@ func main() {
parser := tuple.NewParser(flagPackagePrefix, flagOffline)
tuples, errors := parser.Load(args[0])
if len(tuples) != 0 {
fmt.Println(tuples)
if !flagSpack {
fmt.Println(tuples)
} else {
resources, err := spack.ResourcesFromTuples(flagAppVersion, tuples)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)
}
json, err := resources.ToJson()
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)
}
fmt.Println(string(json))
}
}
if errors != nil {
fmt.Println(errors)
Expand All @@ -53,7 +68,9 @@ this commit ID translation can be disabled with -offline flag.

var (
flagOffline = false
flagSpack = false
flagPackagePrefix = "vendor"
flagAppVersion = ""
flagVersion = false
)

Expand All @@ -63,7 +80,9 @@ func init() {
basename := path.Base(os.Args[0])

flag.BoolVar(&flagOffline, "offline", flagOffline, "disable network access")
flag.BoolVar(&flagSpack, "spack", flagSpack, "print Spack resource stanzas")
flag.StringVar(&flagPackagePrefix, "prefix", "vendor", "package prefix")
flag.StringVar(&flagAppVersion, "app_version", "", "application version (for spack)")
flag.BoolVar(&flagVersion, "v", flagVersion, "show version")

flag.Usage = func() {
Expand Down
88 changes: 88 additions & 0 deletions spack/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package spack

import (
"encoding/json"
"fmt"
"reflect"
"regexp"

"github.com/dmgk/modules2tuple/tuple"
)

type Resource struct {
Name string `json:"name,omitempty"`
Git string `json:"git,omitempty"`
Tag string `json:"tag,omitempty"`
Commit string `json:"commit,omitempty"`
Placement string `json:"placement,omitempty"`
When string `json:"when,omitempty"`
Destination string `json:"destination,omitempty"`
}

type Resources []*Resource

func (r Resources) ToJson() ([]byte, error) {
b, err := json.Marshal(r)
if err != nil {
return nil, err
}
return b, nil
}

func (r Resource) ToJson() ([]byte, error) {
b, err := json.Marshal(r)
if err != nil {
return nil, err
}
return b, nil
}

func ResourcesFromTuples(appVersion string, tt tuple.Tuples) (Resources, error) {
resources := make(Resources, 0, len(tt))

for _, t := range tt {
r, err := resourceFromTuple(appVersion, t)
if err != nil {
return nil, err
}
resources = append(resources, r)
}

return resources, nil
}

func resourceFromTuple(appVersion string, t *tuple.Tuple) (*Resource, error) {
r := Resource{
Name: t.Package,
Destination: ".",
Placement: fmt.Sprintf("%s/%s", t.Prefix, t.Package),
}

st := reflect.TypeOf(t.Source)
switch st.String() {
case "tuple.GH":
repoSite := "https://github.com" // tuple.GH.Site() returns ""...
r.Git = fmt.Sprintf("%s/%s/%s", repoSite, t.Account, t.Project)
case "tuple.GL":
repoSite := t.Source.Site()
r.Git = fmt.Sprintf("%s/%s/%s", repoSite, t.Account, t.Project)
default:
return nil, fmt.Errorf("Unknown site type: %s", st.String())
}

matched, err := regexp.MatchString("[0-9a-f]{12}", t.Tag)
if err != nil {
return nil, err
}
if matched {
r.Commit = t.Tag
} else {
r.Tag = t.Tag
}

if appVersion != "" {
r.When = "@" + appVersion
}

return &r, nil
}
119 changes: 119 additions & 0 deletions spack/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package spack

import (
"encoding/json"
"reflect"
"testing"

"github.com/dmgk/modules2tuple/tuple"
)

type testCase struct {
AppVersion string
Tuple *tuple.Tuple
Expected string
}

// TestResource tests that an input tuple generates the expected
// resource string.
func TestResource(t *testing.T) {
testCases := []testCase{
// This should use "commit"
{AppVersion: "1.2.3",
Tuple: tParse("github.com/rivo/uniseg v0.0.0-20190313204849-f699dde9c340"),
Expected: `
{
"name": "github.com/rivo/uniseg",
"git": "https://github.com/rivo/uniseg",
"commit": "f699dde9c340",
"placement": "vendor/github.com/rivo/uniseg",
"when": "@1.2.3",
"destination": "."
}`,
},
// This should use "tag" and resolve to github
{AppVersion: "1.2.3",
Tuple: tParse("golang.org/x/text v0.3.2"),
Expected: `
{
"name": "golang.org/x/text",
"git": "https://github.com/golang/text",
"tag": "v0.3.2",
"placement": "vendor/golang.org/x/text",
"when": "@1.2.3",
"destination": "."
}`,
},
// empty AppVersion => no when
{AppVersion: "",
Tuple: tParse("golang.org/x/text v0.3.2"),
Expected: `
{
"name": "golang.org/x/text",
"git": "https://github.com/golang/text",
"tag": "v0.3.2",
"placement": "vendor/golang.org/x/text",
"destination": "."
}`,
},
// A nonstandard, GitLab repo
{AppVersion: "",
Tuple: tParse("howett.net/plist v0.0.0-20181124034731-591f970eefbb"),
Expected: `
{
"name": "howett.net/plist",
"git": "https://gitlab.howett.net/go/plist",
"commit": "591f970eefbb",
"placement": "vendor/howett.net/plist",
"destination": "."
}`,
},
}

for _, c := range testCases {
expected := []byte(c.Expected)
r, err := resourceFromTuple(c.AppVersion, c.Tuple)
if err != nil {
t.Error(err)
}
got, err := r.ToJson()
if err != nil {
t.Error(err)
}
equal, err := jsonCompare(expected, got)
if err != nil {
t.Error(err)
}
if !equal {
t.Errorf("Got: %s, expected %s", r, c.Expected)
}
}
}

// tParse is a helper function that parses a tuple string and returns
// the resulting *tuple.Tuple. It panics if there's a problem parsing
// the string, since that's not what we're testing here.
func tParse(t string) *tuple.Tuple {
tuple, err := tuple.Parse(t, "vendor")
if err != nil {
panic(err)
}
return tuple
}

// After https://gist.github.com/turtlemonvh/e4f7404e28387fadb8ad275a99596f67
func jsonCompare(j1, j2 []byte) (bool, error) {
var o1 interface{}
var o2 interface{}

err := json.Unmarshal([]byte(j1), &o1)
if err != nil {
return false, err
}
err = json.Unmarshal([]byte(j2), &o2)
if err != nil {
return false, err
}

return reflect.DeepEqual(o1, o2), nil
}