Skip to content

Commit

Permalink
Merge pull request golang#512 from darkowlzz/503-itemize-init-feedback
Browse files Browse the repository at this point in the history
Add itemized feedback for dep resolution in init
  • Loading branch information
sdboyer committed May 13, 2017
2 parents 1355884 + 4c785b9 commit b86ad16
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 9 deletions.
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)
}
}
}

0 comments on commit b86ad16

Please sign in to comment.