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

Add itemized feedback for dep resolution in init #512

Merged
merged 1 commit into from
May 13, 2017
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
84 changes: 75 additions & 9 deletions cmd/dep/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package main

import (
"encoding/hex"
"flag"
"os"
"path/filepath"
Expand All @@ -14,6 +15,7 @@ import (

"github.com/golang/dep"
"github.com/golang/dep/internal"
fb "github.com/golang/dep/internal/feedback"
"github.com/golang/dep/internal/gps"
"github.com/golang/dep/internal/gps/pkgtree"
"github.com/pkg/errors"
Expand Down Expand Up @@ -113,6 +115,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
sm.UseDefaultSignalHandling()
defer sm.Release()

ctx.Loggers.Err.Println("Searching GOPATH for projects...")
pd, err := getProjectData(ctx, pkgT, cpr, sm)
if err != nil {
return err
Expand Down Expand Up @@ -145,6 +148,10 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
)
}

ctx.Loggers.Err.Println("Using network for remaining projects...")
// Copy lock before solving. Use this to separate new lock projects from soln
copyLock := *l

// Run solver with project versions found on disk
if ctx.Loggers.Verbose {
ctx.Loggers.Err.Println("dep: Solving...")
Expand Down Expand Up @@ -173,12 +180,26 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
}
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
// Iterate through the new projects in solved lock and add them to manifest
// if direct deps and log feedback for all the new projects.
for _, x := range l.Projects() {
pr := x.Ident().ProjectRoot
newProject := true
// Check if it's a new project, not in the old lock
for _, y := range copyLock.Projects() {
if pr == y.Ident().ProjectRoot {
newProject = false
}
}
if newProject {
// Check if it's in notondisk project map. These are direct deps, should
// be added to manifest.
if _, ok := pd.notondisk[pr]; ok {
m.Dependencies[pr] = getProjectPropertiesFromVersion(x.Version())
feedback(x.Version(), pr, fb.DepTypeDirect, ctx)
} else {
// Log feedback of transitive project
feedback(x.Version(), pr, fb.DepTypeTransitive, ctx)
}
}
}
Expand Down Expand Up @@ -253,6 +274,50 @@ func hasImportPathPrefix(s, prefix string) bool {
return strings.HasPrefix(s, prefix+"/")
}

// feedback logs project constraint as feedback to the user.
func feedback(v gps.Version, pr gps.ProjectRoot, depType string, ctx *dep.Ctx) {
rev, version, branch := gps.VersionComponentStrings(v)

// Check if it's a valid SHA1 digest and trim to 7 characters.
if len(rev) == 40 {
if _, err := hex.DecodeString(rev); err == nil {
// Valid SHA1 digest
rev = rev[0:7]
}
}

// Get LockedVersion
var ver string
if version != "" {
ver = version
} else if branch != "" {
ver = branch
}

cf := &fb.ConstraintFeedback{
LockedVersion: ver,
Revision: rev,
ProjectPath: string(pr),
DependencyType: depType,
}

// Get non-revision constraint if available
if c := getProjectPropertiesFromVersion(v).Constraint; c != nil {
cf.Version = c.String()
}

// Attach ConstraintType for direct dep based on locked version
if cf.DependencyType == fb.DepTypeDirect {
if cf.LockedVersion != "" {
cf.ConstraintType = fb.ConsTypeConstraint
} else {
cf.ConstraintType = fb.ConsTypeHint
}
}

cf.LogFeedback(ctx)
}

// 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 {
Expand Down Expand Up @@ -297,11 +362,9 @@ func getProjectData(ctx *dep.Ctx, pkgT pkgtree.PackageTree, cpr string, sm gps.S

var syncDepGroup sync.WaitGroup
syncDep := func(pr gps.ProjectRoot, sm gps.SourceManager) {
message := "Cached"
if err := sm.SyncSourceFor(gps.ProjectIdentifier{ProjectRoot: pr}); err != nil {
message = "Unable to cache"
ctx.Loggers.Err.Printf("Unable to cache %s", pr)
}
ctx.Loggers.Err.Printf("%s %s\n", message, pr)
syncDepGroup.Done()
}

Expand Down Expand Up @@ -345,6 +408,8 @@ func getProjectData(ctx *dep.Ctx, pkgT pkgtree.PackageTree, cpr string, sm gps.S

ondisk[pr] = v
constraints[pr] = getProjectPropertiesFromVersion(v)

feedback(v, pr, fb.DepTypeDirect, ctx)
}

if ctx.Loggers.Verbose {
Expand Down Expand Up @@ -415,6 +480,7 @@ func getProjectData(ctx *dep.Ctx, pkgT pkgtree.PackageTree, cpr string, sm gps.S
return nil
}
ondisk[pr] = v
feedback(v, pr, fb.DepTypeTransitive, ctx)
}

ptree, err = pkgtree.ListPackages(r, string(pr))
Expand Down
58 changes: 58 additions & 0 deletions internal/feedback/feedback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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 feedback

import (
"fmt"

"github.com/golang/dep"
)

// Constraint types
const ConsTypeConstraint = "constraint"
const ConsTypeHint = "hint"

// Dependency types
const DepTypeDirect = "direct dep"
const DepTypeTransitive = "transitive dep"

// ConstraintFeedback holds project constraint feedback data
type ConstraintFeedback struct {
Version, LockedVersion, Revision, ConstraintType, DependencyType, ProjectPath string
}

// LogFeedback logs the feedback
func (cf ConstraintFeedback) LogFeedback(ctx *dep.Ctx) {
// "Using" feedback for direct dep
if cf.DependencyType == DepTypeDirect {
ver := cf.Version
// revision as version for hint
if cf.ConstraintType == ConsTypeHint {
ver = cf.Revision
}
ctx.Loggers.Err.Printf(" %v", GetUsingFeedback(ver, cf.ConstraintType, cf.DependencyType, cf.ProjectPath))
}
// No "Locking" feedback for hints. "Locking" feedback only for constraint
// and transitive dep
if cf.ConstraintType != ConsTypeHint {
ctx.Loggers.Err.Printf(" %v", GetLockingFeedback(cf.LockedVersion, cf.Revision, cf.DependencyType, cf.ProjectPath))
}
}

// GetUsingFeedback returns dependency using feedback string.
// Example:
// Using ^1.0.0 as constraint for direct dep github.com/foo/bar
// Using 1b8edb3 as hint for direct dep github.com/bar/baz
func GetUsingFeedback(version, consType, depType, projectPath string) string {
return fmt.Sprintf("Using %s as %s for %s %s", version, consType, depType, projectPath)
}

// GetLockingFeedback returns dependency locking feedback string.
// Example:
// Locking in v1.1.4 (bc29b4f) for direct dep github.com/foo/bar
// Locking in master (436f39d) for transitive dep github.com/baz/qux
func GetLockingFeedback(version, revision, depType, projectPath string) string {
return fmt.Sprintf("Locking in %s (%s) for %s %s", version, revision, depType, projectPath)
}
39 changes: 39 additions & 0 deletions internal/feedback/feedback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 feedback

import (
"testing"
)

func TestGetConstraintString(t *testing.T) {
cases := []struct {
feedback string
want string
}{
{
feedback: GetUsingFeedback("^1.0.0", ConsTypeConstraint, DepTypeDirect, "github.com/foo/bar"),
want: "Using ^1.0.0 as constraint for direct dep github.com/foo/bar",
},
{
feedback: GetUsingFeedback("1b8edb3", ConsTypeHint, DepTypeDirect, "github.com/bar/baz"),
want: "Using 1b8edb3 as hint for direct dep github.com/bar/baz",
},
{
feedback: GetLockingFeedback("v1.1.4", "bc29b4f", DepTypeDirect, "github.com/foo/bar"),
want: "Locking in v1.1.4 (bc29b4f) for direct dep github.com/foo/bar",
},
{
feedback: GetLockingFeedback("master", "436f39d", DepTypeTransitive, "github.com/baz/qux"),
want: "Locking in master (436f39d) for transitive dep github.com/baz/qux",
},
}

for _, c := range cases {
if c.want != c.feedback {
t.Fatalf("Feedbacks are not expected: \n\t(GOT) %v\n\t(WNT) %v", c.feedback, c.want)
}
}
}