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

Commit d2ead1d

Browse files
authored
Merge pull request #742 from darkowlzz/godep-importer
Godep importer
2 parents 32ace93 + d2109d3 commit d2ead1d

File tree

10 files changed

+642
-0
lines changed

10 files changed

+642
-0
lines changed

cmd/dep/godep_importer.go

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// Copyright 2017 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"encoding/json"
9+
"io/ioutil"
10+
"log"
11+
"os"
12+
"path/filepath"
13+
14+
"github.com/golang/dep"
15+
fb "github.com/golang/dep/internal/feedback"
16+
"github.com/golang/dep/internal/gps"
17+
"github.com/pkg/errors"
18+
)
19+
20+
const godepJSONName = "Godeps.json"
21+
22+
type godepImporter struct {
23+
json godepJSON
24+
25+
logger *log.Logger
26+
verbose bool
27+
sm gps.SourceManager
28+
}
29+
30+
func newGodepImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *godepImporter {
31+
return &godepImporter{
32+
logger: logger,
33+
verbose: verbose,
34+
sm: sm,
35+
}
36+
}
37+
38+
type godepJSON struct {
39+
Imports []godepPackage `json:"Deps"`
40+
}
41+
42+
type godepPackage struct {
43+
ImportPath string `json:"ImportPath"`
44+
Rev string `json:"Rev"`
45+
Comment string `json:"Comment"`
46+
}
47+
48+
func (g *godepImporter) Name() string {
49+
return "godep"
50+
}
51+
52+
func (g *godepImporter) HasDepMetadata(dir string) bool {
53+
y := filepath.Join(dir, "Godeps", godepJSONName)
54+
if _, err := os.Stat(y); err != nil {
55+
return false
56+
}
57+
58+
return true
59+
}
60+
61+
func (g *godepImporter) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
62+
err := g.load(dir)
63+
if err != nil {
64+
return nil, nil, err
65+
}
66+
67+
return g.convert(pr)
68+
}
69+
70+
func (g *godepImporter) load(projectDir string) error {
71+
g.logger.Println("Detected godep configuration files...")
72+
j := filepath.Join(projectDir, "Godeps", godepJSONName)
73+
if g.verbose {
74+
g.logger.Printf(" Loading %s", j)
75+
}
76+
jb, err := ioutil.ReadFile(j)
77+
if err != nil {
78+
return errors.Wrapf(err, "Unable to read %s", j)
79+
}
80+
err = json.Unmarshal(jb, &g.json)
81+
if err != nil {
82+
return errors.Wrapf(err, "Unable to parse %s", j)
83+
}
84+
85+
return nil
86+
}
87+
88+
func (g *godepImporter) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
89+
g.logger.Println("Converting from Godeps.json ...")
90+
91+
manifest := &dep.Manifest{
92+
Constraints: make(gps.ProjectConstraints),
93+
}
94+
lock := &dep.Lock{}
95+
96+
for _, pkg := range g.json.Imports {
97+
// ImportPath must not be empty
98+
if pkg.ImportPath == "" {
99+
err := errors.New("Invalid godep configuration, ImportPath is required")
100+
return nil, nil, err
101+
}
102+
103+
// Obtain ProjectRoot. Required for avoiding sub-package imports.
104+
ip, err := g.sm.DeduceProjectRoot(pkg.ImportPath)
105+
if err != nil {
106+
return nil, nil, err
107+
}
108+
pkg.ImportPath = string(ip)
109+
110+
// Check if it already existing in locked projects
111+
if projectExistsInLock(lock, pkg.ImportPath) {
112+
continue
113+
}
114+
115+
// Rev must not be empty
116+
if pkg.Rev == "" {
117+
err := errors.New("Invalid godep configuration, Rev is required")
118+
return nil, nil, err
119+
}
120+
121+
if pkg.Comment == "" {
122+
// When there's no comment, try to get corresponding version for the Rev
123+
// and fill Comment.
124+
pi := gps.ProjectIdentifier{
125+
ProjectRoot: gps.ProjectRoot(pkg.ImportPath),
126+
}
127+
revision := gps.Revision(pkg.Rev)
128+
version, err := lookupVersionForRevision(revision, pi, g.sm)
129+
if err != nil {
130+
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)
131+
g.logger.Printf(warn.Error())
132+
version = revision
133+
}
134+
135+
pp := getProjectPropertiesFromVersion(version)
136+
if pp.Constraint != nil {
137+
pkg.Comment = pp.Constraint.String()
138+
}
139+
}
140+
141+
if pkg.Comment != "" {
142+
// If there's a comment, use it to create project constraint
143+
pc, err := g.buildProjectConstraint(pkg)
144+
if err != nil {
145+
return nil, nil, err
146+
}
147+
manifest.Constraints[pc.Ident.ProjectRoot] = gps.ProjectProperties{Constraint: pc.Constraint}
148+
}
149+
150+
lp := g.buildLockedProject(pkg)
151+
lock.P = append(lock.P, lp)
152+
}
153+
154+
return manifest, lock, nil
155+
}
156+
157+
// buildProjectConstraint uses the provided package ImportPath and Comment to
158+
// create a project constraint
159+
func (g *godepImporter) buildProjectConstraint(pkg godepPackage) (pc gps.ProjectConstraint, err error) {
160+
pc.Ident = gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath)}
161+
pc.Constraint, err = deduceConstraint(pkg.Comment, pc.Ident, g.sm)
162+
return
163+
}
164+
165+
// buildLockedProject uses the package Rev and Comment to create lock project
166+
func (g *godepImporter) buildLockedProject(pkg godepPackage) gps.LockedProject {
167+
pi := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(pkg.ImportPath)}
168+
169+
var version gps.Version
170+
171+
if pkg.Comment != "" {
172+
ver := gps.NewVersion(pkg.Comment)
173+
version = ver.Is(gps.Revision(pkg.Rev))
174+
} else {
175+
version = gps.Revision(pkg.Rev)
176+
}
177+
178+
feedback(version, pi.ProjectRoot, fb.DepTypeImported, g.logger)
179+
return gps.NewLockedProject(pi, version, nil)
180+
}
181+
182+
// projectExistsInLock checks if the given import path already existing in
183+
// locked projects.
184+
func projectExistsInLock(l *dep.Lock, ip string) bool {
185+
for _, lp := range l.P {
186+
if ip == string(lp.Ident().ProjectRoot) {
187+
return true
188+
}
189+
}
190+
191+
return false
192+
}

0 commit comments

Comments
 (0)