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

Implement new spec for init #470

Merged
Merged
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
115 changes: 75 additions & 40 deletions cmd/dep/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ import (

const initShortHelp = `Initialize a new project with manifest and lock files`
const initLongHelp = `
Initialize the project at filepath root by parsing its dependencies and writing
manifest and lock files. If root isn't specified, use the current directory.
Initialize the project at filepath root by parsing its dependencies, writing
manifest and lock files, and vendoring the dependencies. If root isn't
specified, use the current directory.

The version of each dependency will reflect the current state of the GOPATH. If
a dependency doesn't exist in the GOPATH, it won't be written to the manifest,
but it will be solved-for, and will appear in the lock.

Note: init may use the network to solve the dependency graph.

Note: init does NOT vendor dependencies at the moment. See dep ensure.
a dependency doesn't exist in the GOPATH, the network would be used to
solve-for, and the solution will appear in manifest and lock. Solved
dependencies will be vendored in vendor/ dir relative to project root.
`

func (cmd *initCommand) Name() string { return "init" }
Expand Down Expand Up @@ -139,33 +137,51 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
)
}

if len(pd.notondisk) > 0 {
internal.Vlogf("Solving...")
params := gps.SolveParameters{
RootDir: root,
RootPackageTree: pkgT,
Manifest: m,
Lock: l,
ProjectAnalyzer: dep.Analyzer{},
}
// Run solver with project versions found on disk
internal.Vlogf("Solving...")
params := gps.SolveParameters{
RootDir: root,
RootPackageTree: pkgT,
Manifest: m,
Lock: l,
ProjectAnalyzer: dep.Analyzer{},
}

if *verbose {
params.Trace = true
params.TraceLogger = log.New(os.Stderr, "", 0)
}
s, err := gps.Prepare(params, sm)
if err != nil {
return errors.Wrap(err, "prepare solver")
}
if *verbose {
params.Trace = true
params.TraceLogger = log.New(os.Stderr, "", 0)
}
s, err := gps.Prepare(params, sm)
if err != nil {
return errors.Wrap(err, "prepare solver")
}

soln, err := s.Solve()
if err != nil {
handleAllTheFailuresOfTheWorld(err)
return err
soln, err := s.Solve()
if err != nil {
handleAllTheFailuresOfTheWorld(err)
return err
}
l = dep.LockFromInterface(soln)

// Pick notondisk project constraints from solution and add to manifest
for k, _ := range pd.notondisk {
for _, x := range l.Projects() {
if k == x.Ident().ProjectRoot {
m.Dependencies[k] = getProjectPropertiesFromVersion(x.Version())
break
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is there a better way to pick the constraints and add to manifests?

Copy link
Member

Choose a reason for hiding this comment

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

Not one that's wrapped up in a nice function, but there is something sorta analogous - I'll make more detailed comments down on the impl. But really, the algorithm you'll want to follow for this is bulleted in the spec doc. 😄

}
l = dep.LockFromInterface(soln)
}

// Run gps.Prepare with appropriate constraint solutions from solve run
// to generate the final lock memo.
s, err = gps.Prepare(params, sm)
if err != nil {
return errors.Wrap(err, "prepare solver")
}

l.Memo = s.HashInputs()

internal.Vlogf("Writing manifest and lock files.")

var sw dep.SafeWriter
Expand Down Expand Up @@ -213,6 +229,34 @@ func hasImportPathPrefix(s, prefix string) bool {
return strings.HasPrefix(s, prefix+"/")
}

// getProjectPropertiesFromVersion takes a gps.Version and returns a proper
// gps.ProjectProperties with Constraint value based on the provided version.
func getProjectPropertiesFromVersion(v gps.Version) gps.ProjectProperties {
pp := gps.ProjectProperties{}

// extract version and ignore if it's revision only
switch tv := v.(type) {
case gps.PairedVersion:
v = tv.Unpair()
case gps.Revision:
return pp
}

switch v.Type() {
case gps.IsBranch, gps.IsVersion:
pp.Constraint = v
case gps.IsSemver:
// TODO: remove "^" when https://github.com/golang/dep/issues/225 is ready.
c, err := gps.NewSemverConstraint("^" + v.String())
if err != nil {
panic(err)
}
pp.Constraint = c
}

return pp
}

type projectData struct {
constraints gps.ProjectConstraints // constraints that could be found
dependencies map[gps.ProjectRoot][]string // all dependencies (imports) found by project root
Expand Down Expand Up @@ -267,16 +311,7 @@ func getProjectData(ctx *dep.Ctx, pkgT pkgtree.PackageTree, cpr string, sm *gps.
}

ondisk[pr] = v
pp := gps.ProjectProperties{}
switch v.Type() {
case gps.IsBranch, gps.IsVersion, gps.IsRevision:
pp.Constraint = v
case gps.IsSemver:
c, _ := gps.NewSemverConstraint("^" + v.String())
pp.Constraint = c
}

constraints[pr] = pp
constraints[pr] = getProjectPropertiesFromVersion(v)
}

internal.Vlogf("Analyzing transitive imports...")
Expand Down
49 changes: 48 additions & 1 deletion cmd/dep/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

package main

import "testing"
import (
"testing"

"github.com/sdboyer/gps"
)

func TestContains(t *testing.T) {
a := []string{"a", "b", "abcd"}
Expand Down Expand Up @@ -33,3 +37,46 @@ func TestIsStdLib(t *testing.T) {
}
}
}

func TestGetProjectPropertiesFromVersion(t *testing.T) {
cases := []struct {
version gps.Version
want gps.Version
}{
{
version: gps.NewBranch("foo-branch"),
want: gps.NewBranch("foo-branch"),
},
{
version: gps.NewVersion("foo-version"),
want: gps.NewVersion("foo-version"),
},
{
version: gps.NewBranch("foo-branch").Is("some-revision"),
want: gps.NewBranch("foo-branch"),
},
{
version: gps.NewVersion("foo-version").Is("some-revision"),
want: gps.NewVersion("foo-version"),
},
{
version: gps.Revision("some-revision"),
want: nil,
},
}

for _, c := range cases {
actualProp := getProjectPropertiesFromVersion(c.version)
if c.want != actualProp.Constraint {
t.Fatalf("Expected project property to be %v, got %v", actualProp.Constraint, c.want)
}
}

// Test to have caret in semver version
outsemver := getProjectPropertiesFromVersion(gps.NewVersion("v1.0.0"))
wantSemver, _ := gps.NewSemverConstraint("^1.0.0")
Copy link
Member

Choose a reason for hiding this comment

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

The actual problem here is an annoying implementation detail - it should work without needing to fall back on string comparison if you use ^v1.0.0 instead of ^1.0.0. I believe this kind of issue is improved in newer versions of the semver lib, but we're stuck with what we've got for now.


if outsemver.Constraint.String() != wantSemver.String() {
t.Fatalf("Expected semver to be %v, got %v", outsemver.Constraint, wantSemver)
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@
# source = "https://github.com/myfork/package.git"



[[dependencies]]
name = "github.com/sdboyer/deptest"
version = "^1.0.0"
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@
# source = "https://github.com/myfork/package.git"



[[dependencies]]
name = "github.com/sdboyer/deptest"
version = "^1.0.0"

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@

[[dependencies]]
name = "github.com/sdboyer/deptestdos"
revision = "a0196baa11ea047dd65037287451d36b861b00ea"

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
[[dependencies]]
name = "github.com/sdboyer/deptest"
version = ">=0.8.0, <1.0.0"

[[dependencies]]
name = "github.com/sdboyer/deptestdos"
version = "^2.0.0"

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@

[[dependencies]]
name = "github.com/sdboyer/deptestdos"
revision = "a0196baa11ea047dd65037287451d36b861b00ea"

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

[[dependencies]]
name = "github.com/sdboyer/deptest"
version = "^1.0.0"