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

Commit

Permalink
Merge pull request #742 from darkowlzz/godep-importer
Browse files Browse the repository at this point in the history
Godep importer
  • Loading branch information
carolynvs committed Jun 12, 2017
2 parents 32ace93 + d2109d3 commit d2ead1d
Show file tree
Hide file tree
Showing 10 changed files with 642 additions and 0 deletions.
192 changes: 192 additions & 0 deletions cmd/dep/godep_importer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// 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 (
"encoding/json"
"io/ioutil"
"log"
"os"
"path/filepath"

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

const godepJSONName = "Godeps.json"

type godepImporter struct {
json godepJSON

logger *log.Logger
verbose bool
sm gps.SourceManager
}

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

type godepJSON struct {
Imports []godepPackage `json:"Deps"`
}

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

func (g *godepImporter) Name() string {
return "godep"
}

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

return true
}

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

return g.convert(pr)
}

func (g *godepImporter) load(projectDir string) error {
g.logger.Println("Detected godep configuration files...")
j := filepath.Join(projectDir, "Godeps", godepJSONName)
if g.verbose {
g.logger.Printf(" Loading %s", j)
}
jb, err := ioutil.ReadFile(j)
if err != nil {
return errors.Wrapf(err, "Unable to read %s", j)
}
err = json.Unmarshal(jb, &g.json)
if err != nil {
return errors.Wrapf(err, "Unable to parse %s", j)
}

return nil
}

func (g *godepImporter) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
g.logger.Println("Converting from Godeps.json ...")

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

for _, pkg := range g.json.Imports {
// ImportPath must not be empty
if pkg.ImportPath == "" {
err := errors.New("Invalid godep configuration, ImportPath is required")
return nil, nil, err
}

// Obtain ProjectRoot. Required for avoiding sub-package imports.
ip, err := g.sm.DeduceProjectRoot(pkg.ImportPath)
if err != nil {
return nil, nil, err
}
pkg.ImportPath = string(ip)

// Check if it already existing in locked projects
if projectExistsInLock(lock, pkg.ImportPath) {
continue
}

// Rev must not be empty
if pkg.Rev == "" {
err := errors.New("Invalid godep configuration, Rev is required")
return nil, nil, err
}

if pkg.Comment == "" {
// When there's no comment, try to get corresponding version for the Rev
// and fill Comment.
pi := gps.ProjectIdentifier{
ProjectRoot: gps.ProjectRoot(pkg.ImportPath),
}
revision := gps.Revision(pkg.Rev)
version, err := lookupVersionForRevision(revision, pi, g.sm)
if err != nil {
warn := errors.Wrapf(err, "Unable to lookup the version represented by %s in %s. Falling back to locking the revision only.", pkg.Rev, pi.ProjectRoot)
g.logger.Printf(warn.Error())
version = revision
}

pp := getProjectPropertiesFromVersion(version)
if pp.Constraint != nil {
pkg.Comment = pp.Constraint.String()
}
}

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

lp := g.buildLockedProject(pkg)
lock.P = append(lock.P, lp)
}

return manifest, lock, nil
}

// buildProjectConstraint uses the provided package ImportPath and Comment to
// create a project constraint
func (g *godepImporter) buildProjectConstraint(pkg godepPackage) (pc gps.ProjectConstraint, err error) {
pc.Ident = gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath)}
pc.Constraint, err = deduceConstraint(pkg.Comment, pc.Ident, g.sm)
return
}

// buildLockedProject uses the package Rev and Comment to create lock project
func (g *godepImporter) buildLockedProject(pkg godepPackage) gps.LockedProject {
pi := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath)}

var version gps.Version

if pkg.Comment != "" {
ver := gps.NewVersion(pkg.Comment)
version = ver.Is(gps.Revision(pkg.Rev))
} else {
version = gps.Revision(pkg.Rev)
}

feedback(version, pi.ProjectRoot, fb.DepTypeImported, g.logger)
return gps.NewLockedProject(pi, version, nil)
}

// projectExistsInLock checks if the given import path already existing in
// locked projects.
func projectExistsInLock(l *dep.Lock, ip string) bool {
for _, lp := range l.P {
if ip == string(lp.Ident().ProjectRoot) {
return true
}
}

return false
}
Loading

0 comments on commit d2ead1d

Please sign in to comment.