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

Use new gps capabilities during init's dep search #305

Merged
merged 3 commits into from
Mar 10, 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
129 changes: 61 additions & 68 deletions cmd/dep/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,6 @@ type projectData struct {
}

func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.SourceMgr) (projectData, error) {
vlogf("Building dependency graph...")

constraints := make(gps.ProjectConstraints)
dependencies := make(map[gps.ProjectRoot][]string)
packages := make(map[string]bool)
Expand All @@ -254,59 +252,48 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour
fmt.Fprintf(os.Stderr, "%s %s\n", message, pr)
}

for _, v := range pkgT.Packages {
// TODO: Some errors maybe should not be skipped ;-)
if v.Err != nil {
vlogf("%v", v.Err)
continue
}
vlogf("Package %q, analyzing...", v.P.ImportPath)

for _, ip := range v.P.Imports {
if isStdLib(ip) {
continue
}
if hasImportPathPrefix(ip, cpr) {
// Don't analyze imports from the current project.
continue
}
pr, err := sm.DeduceProjectRoot(ip)
if err != nil {
return projectData{}, errors.Wrap(err, "sm.DeduceProjectRoot") // TODO: Skip and report ?
}
rm, _ := pkgT.ToReachMap(true, true, false, nil)
if len(rm) == 0 {
return projectData{}, nil
}

packages[ip] = true
if _, ok := dependencies[pr]; ok {
if !contains(dependencies[pr], ip) {
dependencies[pr] = append(dependencies[pr], ip)
}
vlogf("Building dependency graph...")
// Exclude stdlib imports from the list returned from Flatten().
const omitStdlib = false
for _, ip := range rm.Flatten(omitStdlib) {
pr, err := sm.DeduceProjectRoot(ip)
if err != nil {
return projectData{}, errors.Wrap(err, "sm.DeduceProjectRoot") // TODO: Skip and report ?
}

continue
}
go syncDep(pr, sm)
packages[ip] = true
if _, has := dependencies[pr]; has {
dependencies[pr] = append(dependencies[pr], ip)
continue
}
go syncDep(pr, sm)

vlogf("Package %q has import %q, analyzing...", v.P.ImportPath, ip)
vlogf("Found import of %q, analyzing...", ip)

dependencies[pr] = []string{ip}
v, err := ctx.VersionInWorkspace(pr)
if err != nil {
notondisk[pr] = true
vlogf("Could not determine version for %q, omitting from generated manifest", pr)
continue
}

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
}
dependencies[pr] = []string{ip}
v, err := ctx.VersionInWorkspace(pr)
if err != nil {
notondisk[pr] = true
vlogf("Could not determine version for %q, omitting from generated manifest", pr)
continue
}

constraints[pr] = pp
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
}

vlogf("Analyzing transitive imports...")
Expand Down Expand Up @@ -350,13 +337,31 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour
// project is not present in the workspace, and so we need to
// solve to deal with this dep.
r := filepath.Join(ctx.GOPATH, "src", string(pr))
_, err := os.Lstat(r)
if os.IsNotExist(err) {
fi, err := os.Stat(r)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the change from Lstat to Stat?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because, unless I misunderstand how this all works, we could Lstat a symlink that exists, but its referent does not. In that case, the subsequent check of os.IsNotExist() would not have the desired effect - it would tell us the symlink exists, but what we really care about is the referent existing.

...At least, I think that's what I think we care about here. My latest explorations into symlinks, and what we should do/the toolchain currently does left me dizzy.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good.

if os.IsNotExist(err) || !fi.IsDir() {
colors[pkg] = black
notondisk[pr] = true
return nil
}

// We know the project is on disk; the question is whether we're
// first seeing it here, in the transitive exploration, or if it
// was found in the initial pass on direct imports. We know it's
// the former if there's no entry for it in the ondisk map.
if _, in := ondisk[pr]; !in {
v, err := ctx.VersionInWorkspace(pr)
if err != nil {
// Even if we know it's on disk, errors are still
// possible when trying to deduce version. If we
// encounter such an error, just treat the project as
// not being on disk; the solver will work it out.
colors[pkg] = black
notondisk[pr] = true
return nil
}
ondisk[pr] = v
}

ptree, err = gps.ListPackages(r, string(pr))
if err != nil {
// Any error here other than an a nonexistent dir (which
Expand Down Expand Up @@ -386,28 +391,15 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour
return nil
}

if _, ok := dependencies[pr]; ok {
if !contains(dependencies[pr], pkg) {
dependencies[pr] = append(dependencies[pr], pkg)
if deps, has := dependencies[pr]; has {
if !contains(deps, pkg) {
dependencies[pr] = append(deps, pkg)
}
} else {
dependencies[pr] = []string{pkg}
go syncDep(pr, sm)
}

// project must be on disk at this point; question is
// whether we're first seeing it here, in the transitive
// exploration, or if it arose in the direct dep parts
if _, in := ondisk[pr]; !in {
v, err := ctx.VersionInWorkspace(pr)
if err != nil {
colors[pkg] = black
notondisk[pr] = true
return nil
}
ondisk[pr] = v
}

// recurse
for _, rpkg := range reached.External {
if isStdLib(rpkg) {
Expand All @@ -416,13 +408,14 @@ func getProjectData(ctx *dep.Ctx, pkgT gps.PackageTree, cpr string, sm *gps.Sour

err := dft(rpkg)
if err != nil {
// Bubble up any errors we encounter
return err
}
}

colors[pkg] = black
case grey:
return fmt.Errorf("Import cycle detected on %s", pkg)
return errors.Errorf("Import cycle detected on %s", pkg)
}
return nil
}
Expand Down
13 changes: 13 additions & 0 deletions cmd/dep/testdata/harness_tests/init/skip-hidden/final/lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"memo": "63510efb9632ec69c1164ce396d7ebea4ad3884b4fa508373da17226d5a39739",
"projects": [
{
"name": "github.com/sdboyer/deptest",
"version": "v1.0.0",
"revision": "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
"packages": [
"."
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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 (
"fmt"

"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)

func main() {
var x deptestdos.Bar
y := foo.FooFunc()

fmt.Println(x, y)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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 (
"fmt"

"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)

func main() {
var x deptestdos.Bar
y := foo.FooFunc()

fmt.Println(x, y)
}
13 changes: 13 additions & 0 deletions cmd/dep/testdata/harness_tests/init/skip-hidden/initial/lib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 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 foo

import "github.com/sdboyer/deptest"

func Foo() deptest.Foo {
var y deptest.Foo

return y
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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 (
"fmt"

"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)

func main() {
var x deptestdos.Bar
y := foo.FooFunc()

fmt.Println(x, y)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"commands": [
["init"]
],
"finalVendors": [
"github.com/sdboyer/deptest"
]
}