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

Add importer for github.com/LK4D4/vndr #978

Merged
merged 7 commits into from
Aug 11, 2017
Merged
Show file tree
Hide file tree
Changes from 4 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
34 changes: 16 additions & 18 deletions cmd/dep/glide_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"github.com/pkg/errors"
)

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

var (
discardLogger = log.New(ioutil.Discard, "", 0)
)
Expand All @@ -43,10 +41,10 @@ func TestGlideConfig_Import(t *testing.T) {
h.Must(err)
defer sm.Release()

h.TempDir(filepath.Join("src", testGlideProjectRoot))
h.TempCopy(filepath.Join(testGlideProjectRoot, glideYamlName), "glide/glide.yaml")
h.TempCopy(filepath.Join(testGlideProjectRoot, glideLockName), "glide/glide.lock")
projectRoot := h.Path(testGlideProjectRoot)
h.TempDir(filepath.Join("src", testProjectRoot))
h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
h.TempCopy(filepath.Join(testProjectRoot, glideLockName), "glide/glide.lock")
projectRoot := h.Path(testProjectRoot)

// Capture stderr so we can verify output
verboseOutput := &bytes.Buffer{}
Expand All @@ -57,7 +55,7 @@ func TestGlideConfig_Import(t *testing.T) {
t.Fatal("Expected the importer to detect the glide configuration files")
}

m, l, err := g.Import(projectRoot, testGlideProjectRoot)
m, l, err := g.Import(projectRoot, testProjectRoot)
h.Must(err)

if m == nil {
Expand Down Expand Up @@ -91,16 +89,16 @@ func TestGlideConfig_Import_MissingLockFile(t *testing.T) {
h.Must(err)
defer sm.Release()

h.TempDir(filepath.Join("src", testGlideProjectRoot))
h.TempCopy(filepath.Join(testGlideProjectRoot, glideYamlName), "glide/glide.yaml")
projectRoot := h.Path(testGlideProjectRoot)
h.TempDir(filepath.Join("src", testProjectRoot))
h.TempCopy(filepath.Join(testProjectRoot, glideYamlName), "glide/glide.yaml")
projectRoot := h.Path(testProjectRoot)

g := newGlideImporter(ctx.Err, true, sm)
if !g.HasDepMetadata(projectRoot) {
t.Fatal("The glide importer should gracefully handle when only glide.yaml is present")
}

m, l, err := g.Import(projectRoot, testGlideProjectRoot)
m, l, err := g.Import(projectRoot, testProjectRoot)
h.Must(err)

if m == nil {
Expand Down Expand Up @@ -144,7 +142,7 @@ func TestGlideConfig_Convert_Project(t *testing.T) {
},
}

manifest, lock, err := g.convert(testGlideProjectRoot)
manifest, lock, err := g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -230,7 +228,7 @@ func TestGlideConfig_Convert_TestProject(t *testing.T) {
},
}

manifest, lock, err := g.convert(testGlideProjectRoot)
manifest, lock, err := g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -265,7 +263,7 @@ func TestGlideConfig_Convert_Ignore(t *testing.T) {
Ignores: []string{pkg},
}

manifest, _, err := g.convert(testGlideProjectRoot)
manifest, _, err := g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -293,7 +291,7 @@ func TestGlideConfig_Convert_ExcludeDir(t *testing.T) {
ExcludeDirs: []string{"samples"},
}

manifest, _, err := g.convert(testGlideProjectRoot)
manifest, _, err := g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -322,7 +320,7 @@ func TestGlideConfig_Convert_ExcludeDir_IgnoresMismatchedPackageName(t *testing.
ExcludeDirs: []string{"samples"},
}

manifest, _, err := g.convert(testGlideProjectRoot)
manifest, _, err := g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -364,7 +362,7 @@ func TestGlideConfig_Convert_WarnsForUnusedFields(t *testing.T) {
Imports: []glidePackage{pkg},
}

_, _, err = g.convert(testGlideProjectRoot)
_, _, err = g.convert(testProjectRoot)
if err != nil {
t.Fatal(err)
}
Expand All @@ -391,7 +389,7 @@ func TestGlideConfig_Convert_BadInput_EmptyPackageName(t *testing.T) {
Imports: []glidePackage{{Name: ""}},
}

_, _, err = g.convert(testGlideProjectRoot)
_, _, err = g.convert(testProjectRoot)
if err == nil {
t.Fatal("Expected conversion to fail because the package name is empty")
}
Expand Down
14 changes: 7 additions & 7 deletions cmd/dep/godep_importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/pkg/errors"
)

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

func TestGodepConfig_Import(t *testing.T) {
h := test.NewHelper(t)
Expand All @@ -25,10 +25,10 @@ func TestGodepConfig_Import(t *testing.T) {
cacheDir := "gps-repocache"
h.TempDir(cacheDir)
h.TempDir("src")
h.TempDir(filepath.Join("src", testGodepProjectRoot))
h.TempCopy(filepath.Join(testGodepProjectRoot, godepPath), "godep/Godeps.json")
h.TempDir(filepath.Join("src", testProjectRoot))
h.TempCopy(filepath.Join(testProjectRoot, godepPath), "godep/Godeps.json")

projectRoot := h.Path(testGodepProjectRoot)
projectRoot := h.Path(testProjectRoot)
sm, err := gps.NewSourceManager(h.Path(cacheDir))
h.Must(err)
defer sm.Release()
Expand All @@ -42,7 +42,7 @@ func TestGodepConfig_Import(t *testing.T) {
t.Fatal("Expected the importer to detect godep configuration file")
}

m, l, err := g.Import(projectRoot, testGodepProjectRoot)
m, l, err := g.Import(projectRoot, testProjectRoot)
h.Must(err)

if m == nil {
Expand Down Expand Up @@ -88,9 +88,9 @@ func TestGodepConfig_JsonLoad(t *testing.T) {

ctx := newTestContext(h)

h.TempCopy(filepath.Join(testGodepProjectRoot, godepPath), "godep/Godeps.json")
h.TempCopy(filepath.Join(testProjectRoot, godepPath), "godep/Godeps.json")

projectRoot := h.Path(testGodepProjectRoot)
projectRoot := h.Path(testProjectRoot)

g := newGodepImporter(ctx.Err, true, nil)
err := g.load(projectRoot)
Expand Down
1 change: 1 addition & 0 deletions cmd/dep/root_analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func (a *rootAnalyzer) importManifestAndLock(dir string, pr gps.ProjectRoot, sup
importers := []importer{
newGlideImporter(logger, a.ctx.Verbose, a.sm),
newGodepImporter(logger, a.ctx.Verbose, a.sm),
newVndrImporter(logger, a.ctx.Verbose, a.sm),
}

for _, i := range importers {
Expand Down
6 changes: 6 additions & 0 deletions cmd/dep/testdata/vndr/golden.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Detected vndr configuration file...
Converting from vendor.conf...
Using 3f4c3bea144e112a69bbe5d8d01c1b09a544253f as initial hint for imported dep github.com/sdboyer/deptest
Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest
Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos
Trying * (v2.0.0) as initial lock for imported dep github.com/sdboyer/deptestdos
4 changes: 4 additions & 0 deletions cmd/dep/testdata/vndr/vendor.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f https://github.com/sdboyer/deptest.git # trailing comment
# line comment

github.com/sdboyer/deptestdos v2.0.0 # trailing comment
153 changes: 153 additions & 0 deletions cmd/dep/vndr_importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"bufio"
"log"
"os"
"path/filepath"
"strings"

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

func vndrFile(dir string) string {
return filepath.Join(dir, "vendor.conf")
}

type vndrImporter struct {
logger *log.Logger
verbose bool
sm gps.SourceManager
}

func newVndrImporter(log *log.Logger, verbose bool, sm gps.SourceManager) *vndrImporter {
return &vndrImporter{
logger: log,
verbose: verbose,
sm: sm,
}
}

func (v *vndrImporter) Name() string { return "vndr" }

func (v *vndrImporter) HasDepMetadata(dir string) bool {
_, err := os.Stat(vndrFile(dir))
return err == nil
}

func (v *vndrImporter) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
v.logger.Println("Detected vndr configuration file...")

packages, err := v.loadVndrFile(dir)
if err != nil {
return nil, nil, errors.Wrapf(err, "unable to load vndr file")
}

manifest := &dep.Manifest{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: If #952 is merged first, we should use the constructor dep.NewManifest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The race is on! 🏁

Constraints: make(gps.ProjectConstraints),
}
lock := &dep.Lock{}

for _, pkg := range packages {
pc := gps.ProjectConstraint{
Ident: gps.ProjectIdentifier{
ProjectRoot: gps.ProjectRoot(pkg.importPath),
Source: pkg.repository,
},
}
pc.Constraint, err = v.sm.InferConstraint(pkg.revision, pc.Ident)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that moby uses short git hashes, which is a bit of a problem. I think it would be easiest to have that be a separate issue, so I created #987 to address that part.

if err != nil {
return nil, nil, errors.Wrapf(err, "Unable to interpret revision specifier '%s' for package %s", pkg.importPath, pkg.revision)
}

manifest.Constraints[pc.Ident.ProjectRoot] = gps.ProjectProperties{
Source: pc.Ident.Source,
Constraint: pc.Constraint,
}
fb.NewConstraintFeedback(pc, fb.DepTypeImported).LogFeedback(v.logger)

revision := gps.Revision(pkg.revision)
version, err := lookupVersionForLockedProject(pc.Ident, pc.Constraint, revision, v.sm)
if err != nil {
v.logger.Println(err.Error())
}

lp := gps.NewLockedProject(pc.Ident, version, nil)

lock.P = append(lock.P, lp)
fb.NewLockedProjectFeedback(lp, fb.DepTypeImported).LogFeedback(v.logger)
}

return manifest, lock, nil
}

func (v *vndrImporter) loadVndrFile(dir string) ([]vndrPackage, error) {
v.logger.Printf("Converting from vendor.conf...")

f, err := os.Open(vndrFile(dir))
if err != nil {
return nil, errors.Wrapf(err, "Unable to open %s", vndrFile(dir))
}
defer f.Close()

var packages []vndrPackage
scanner := bufio.NewScanner(f)
for scanner.Scan() {
pkg, err := parseVndrLine(scanner.Text())
if err != nil {
return nil, errors.Wrapf(err, "unable to parse line")
}
if pkg == nil {
// Could be an empty line or one which is just a comment
continue
}
packages = append(packages, *pkg)
}

if scanner.Err() != nil {
return nil, errors.Wrapf(err, "unable to read %s", vndrFile(dir))
}

return packages, nil
}

func parseVndrLine(line string) (*vndrPackage, error) {
commentIdx := strings.Index(line, "#")
if commentIdx >= 0 {
line = line[:commentIdx]
}
line = strings.TrimSpace(line)

if line == "" {
return nil, nil
}

parts := strings.Fields(line)

if !(len(parts) == 2 || len(parts) == 3) {
return nil, errors.Errorf("invalid config format: %q", line)
}

pkg := &vndrPackage{
importPath: parts[0],
revision: parts[1],
}
if len(parts) == 3 {
pkg.repository = parts[2]
}

return pkg, nil
}

type vndrPackage struct {
importPath string
revision string
repository string
}
Loading