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

Commit

Permalink
Add godepFile load, convert and godep importer
Browse files Browse the repository at this point in the history
  • Loading branch information
darkowlzz committed May 16, 2017
1 parent aa4a4c9 commit 393e718
Show file tree
Hide file tree
Showing 5 changed files with 354 additions and 0 deletions.
102 changes: 102 additions & 0 deletions cmd/dep/godep_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"encoding/json"
"io/ioutil"
"path/filepath"

"github.com/golang/dep"
"github.com/golang/dep/internal/gps"
"github.com/pkg/errors"
)

type godepFile struct {
json godepJson
loggers *dep.Loggers
}

func newGodepFile(loggers *dep.Loggers) *godepFile {
return &godepFile{loggers: loggers}
}

type godepJson struct {
Name string `json:"ImportPath"`
Imports []godepPackage `json:"Deps"`
}

type godepPackage struct {
ImportPath string `json:"ImportPath"`
Rev string `json:"Rev"`
Comment string `json:"Comment"`
}

// load parses Godeps.json in projectDir and unmarshals the json to godepFile.json
func (g *godepFile) load(projectDir string) error {
j := filepath.Join(projectDir, "Godeps", godepJsonName)
if g.loggers.Verbose {
g.loggers.Err.Printf("godep: Loading %s", j)
}

raw, err := ioutil.ReadFile(j)
if err != nil {
return errors.Wrapf(err, "Unable to read %s", j)
}
err = json.Unmarshal(raw, &g.json)

return nil
}

func (g *godepFile) convert(projectName string, sm gps.SourceManager) (*dep.Manifest, *dep.Lock, error) {
// Create empty manifest and lock
manifest := &dep.Manifest{
Dependencies: make(gps.ProjectConstraints),
}
lock := &dep.Lock{}

// Parse through each import and add them to manifest and lock
for _, pkg := range g.json.Imports {
// ImportPath must not be empty
if pkg.ImportPath == "" {
err := errors.New("godep: Invalid godep configuration, ImportPath is required")
return nil, nil, err
}

if pkg.Comment != "" {
// If there's a comment, use it to create project constraint
pc, err := g.buildProjectConstraint(pkg, sm)
if err != nil {
return nil, nil, err
}
manifest.Dependencies[pc.Ident.ProjectRoot] = gps.ProjectProperties{Source: pc.Ident.Source, Constraint: pc.Constraint}
}

if pkg.Rev != "" {
// Use the revision to create lock project
lp := g.buildLockedProject(pkg, manifest)
lock.P = append(lock.P, lp)
}
}

return manifest, lock, nil
}

func (g *godepFile) buildProjectConstraint(pkg godepPackage, sm gps.SourceManager) (pc gps.ProjectConstraint, err error) {
pc.Ident = gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath), Source: pkg.ImportPath}
pc.Constraint, err = deduceConstraint(pkg.Comment, pc.Ident, sm)
return
}

func (g *godepFile) buildLockedProject(pkg godepPackage, manifest *dep.Manifest) gps.LockedProject {
var ver gps.Version
id := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath), Source: pkg.ImportPath}
c, has := manifest.Dependencies[id.ProjectRoot]
if has {
// Create PairedVersion if constraint details are available
version := gps.NewVersion(c.Constraint.String())
ver = version.Is(gps.Revision(pkg.Rev))
} else {
ver = gps.Revision(pkg.Rev)
}

return gps.NewLockedProject(id, ver, nil)
}
149 changes: 149 additions & 0 deletions cmd/dep/godep_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package main

import (
"log"
"os"
"path/filepath"
"testing"

"github.com/golang/dep"
"github.com/golang/dep/internal/test"
)

const testGodepProjectRoot = "github.com/golang/notexist"

func TestGodepJsonLoad(t *testing.T) {
// This is same as cmd/dep/testdata/Godeps.json
wantJSON := godepJson{
Name: "github.com/golang/notexist",
Imports: []godepPackage{
{
ImportPath: "github.com/sdboyer/deptest",
Rev: "3f4c3bea144e112a69bbe5d8d01c1b09a544253f",
},
{
ImportPath: "github.com/sdboyer/deptestdos",
Rev: "5c607206be5decd28e6263ffffdcee067266015e",
Comment: "v2.0.0",
},
},
}

h := test.NewHelper(t)
defer h.Cleanup()

h.TempCopy(filepath.Join(testGodepProjectRoot, "Godeps", godepJsonName), "Godeps.json")

projectRoot := h.Path(testGodepProjectRoot)

g := &godepFile{
loggers: &dep.Loggers{
Out: log.New(os.Stderr, "", 0),
Err: log.New(os.Stderr, "", 0),
Verbose: true,
},
}
err := g.load(projectRoot)
if err != nil {
t.Fatalf("Error while loading... %v", err)
}

if g.json.Name != wantJSON.Name {
t.Fatalf("Expected project name to be %v, but got %v", wantJSON.Name, g.json.Name)
}

if !equalImports(g.json.Imports, wantJSON.Imports) {
t.Fatalf("Expected imports to be equal. \n\t(GOT): %v\n\t(WNT): %v", g.json.Imports, wantJSON.Imports)
}
}

func TestGodepConvertProject(t *testing.T) {
loggers := &dep.Loggers{
Out: log.New(os.Stdout, "", 0),
Err: log.New(os.Stderr, "", 0),
Verbose: true,
}

f := godepFile{
loggers: loggers,
json: godepJson{
Name: "github.com/foo/bar",
Imports: []godepPackage{
{
ImportPath: "github.com/sdboyer/deptest",
Rev: "6a741be0cc55ecbe4f45690ebfd606a956d5f14a",
Comment: "v1.0.0",
},
},
},
}

manifest, lock, err := f.convert("", nil)
if err != nil {
t.Fatal(err)
}

d, ok := manifest.Dependencies["github.com/sdboyer/deptest"]
if !ok {
t.Fatal("Expected the manifest to have a dependency for 'github.com/sdboyer/deptest' but got none")
}

v := d.Constraint.String()
if v != "v1.0.0" {
t.Fatalf("Expected manifest constraint to be master, got %s", v)
}

p := lock.P[0]
if p.Ident().ProjectRoot != "github.com/sdboyer/deptest" {
t.Fatalf("Expected the lock to have a project for 'github.com/sdboyer/deptest' but got '%s'", p.Ident().ProjectRoot)
}

lv := p.Version().String()
if lv != "v1.0.0" {
t.Fatalf("Expected locked revision to be 'v1.0.0', got %s", lv)
}
}

func TestGodepConvertBadInput_EmptyPackageName(t *testing.T) {
loggers := &dep.Loggers{
Out: log.New(os.Stdout, "", 0),
Err: log.New(os.Stderr, "", 0),
Verbose: true,
}

f := godepFile{
loggers: loggers,
json: godepJson{
Imports: []godepPackage{{ImportPath: ""}},
},
}

_, _, err := f.convert("", nil)
if err == nil {
t.Fatal("Expected conversion to fail because the ImportPath is empty")
}
}

// Compares two slices of godepPackage and checks if they are equal.
func equalImports(a, b []godepPackage) bool {

if a == nil && b == nil {
return true
}

if a == nil || b == nil {
return false
}

if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}
39 changes: 39 additions & 0 deletions cmd/dep/godep_importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"os"
"path/filepath"

"github.com/golang/dep"
"github.com/golang/dep/internal/gps"
)

const godepJsonName = "Godeps.json"

type godepImporter struct {
loggers *dep.Loggers
sm gps.SourceManager
}

func newGodepImporter(loggers *dep.Loggers, sm gps.SourceManager) *godepImporter {
return &godepImporter{loggers: loggers, sm: sm}
}

func (i godepImporter) HasConfig(dir string) bool {
y := filepath.Join(dir, "Godeps", godepJsonName)
if _, err := os.Stat(y); err != nil {
return false
}

return true
}

func (i godepImporter) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
file := newGodepFile(i.loggers)
err := file.load(dir)
if err != nil {
return nil, nil, err
}

return file.convert(string(pr), i.sm)
}
48 changes: 48 additions & 0 deletions cmd/dep/godep_importer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"log"
"os"
"path/filepath"
"testing"

"github.com/golang/dep"
"github.com/golang/dep/internal/gps"
"github.com/golang/dep/internal/test"
)

func TestGodepImport(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()

cacheDir := "gps-repocache"
h.TempDir(cacheDir)
h.TempDir("src")
h.TempDir(filepath.Join("src", testGlideProjectRoot))
h.TempCopy(filepath.Join(testGodepProjectRoot, "Godeps", godepJsonName), "Godeps.json")

loggers := &dep.Loggers{
Out: log.New(os.Stdout, "", 0),
Err: log.New(os.Stderr, "", 0),
Verbose: true,
}
projectRoot := h.Path(testGodepProjectRoot)
sm, err := gps.NewSourceManager(h.Path(cacheDir))
h.Must(err)

i := newGodepImporter(loggers, sm)
if !i.HasConfig(projectRoot) {
t.Fatal("Expected the importer to detect the godep configuration file")
}

m, l, err := i.Import(projectRoot, gps.ProjectRoot(testGodepProjectRoot))
h.Must(err)

if m == nil {
t.Fatal("Expected the manifest to be generated")
}

if l == nil {
t.Fatal("Expected the lock to be generated")
}
}
16 changes: 16 additions & 0 deletions cmd/dep/testdata/Godeps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"ImportPath": "github.com/golang/notexist",
"GoVersion": "go1.8",
"GodepVersion": "vXYZ",
"Deps": [
{
"ImportPath": "github.com/sdboyer/deptest",
"Rev": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f"
},
{
"ImportPath": "github.com/sdboyer/deptestdos",
"Comment": "v2.0.0",
"Rev": "5c607206be5decd28e6263ffffdcee067266015e"
}
]
}

0 comments on commit 393e718

Please sign in to comment.