Skip to content

Commit

Permalink
fixes rancher#67 Add support for ignoring imports from files with spe…
Browse files Browse the repository at this point in the history
…cific build constraints
  • Loading branch information
Ben Krieger committed Dec 10, 2016
1 parent 456f0aa commit 2fa2338
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 12 deletions.
15 changes: 15 additions & 0 deletions test/ignore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// +build ignore

// package description
package trashtestfixture

import (
"fmt"

"github.com/Sirupsen/logrus"
)

func Foo() string {
logrus.Fatal("This is a test")
return fmt.Sprint("bar")
}
67 changes: 56 additions & 11 deletions trash.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ func main() {
Hidden: true,
EnvVar: "GOPATH",
},
cli.StringSliceFlag{
Name: "skip-tag",
Usage: "Skip looking for imports in files with any of these build tags (flag can be used multiple times)",
// Consider the breaking change of defaulting to ["ignore"]
},
}
app.Action = run

Expand All @@ -91,6 +96,7 @@ func run(c *cli.Context) error {
insecure := c.Bool("insecure")
trashDir := c.String("cache")
gopath = c.String("gopath")
buildtagfilters := c.StringSlice("skip-tag")

trashDir, err := filepath.Abs(trashDir)
if err != nil {
Expand Down Expand Up @@ -129,18 +135,18 @@ func run(c *cli.Context) error {
return err
}
if update {
return updateTrash(trashDir, dir, targetDir, confFile, trashConf, insecure)
return updateTrash(trashDir, dir, targetDir, confFile, trashConf, insecure, buildtagfilters)
}
if err := vendor(keep, trashDir, dir, targetDir, trashConf, insecure); err != nil {
return err
}
if keep {
return nil
}
return cleanup(dir, targetDir, trashConf)
return cleanup(dir, targetDir, trashConf, buildtagfilters)
}

func updateTrash(trashDir, dir, targetDir, trashFile string, trashConf *conf.Conf, insecure bool) error {
func updateTrash(trashDir, dir, targetDir, trashFile string, trashConf *conf.Conf, insecure bool, buildtagfilters []string) error {
// TODO collect imports, create `trashConf *conf.Trash`
rootPackage := trashConf.Package
if rootPackage == "" {
Expand All @@ -154,7 +160,7 @@ func updateTrash(trashDir, dir, targetDir, trashFile string, trashConf *conf.Con
importsLen := 0

os.Chdir(dir)
imports := collectImports(rootPackage, libRoot, targetDir)
imports := collectImports(rootPackage, libRoot, targetDir, buildtagfilters)
for len(imports) > importsLen {
importsLen = len(imports)
for pkg := range imports {
Expand All @@ -170,7 +176,7 @@ func updateTrash(trashDir, dir, targetDir, trashFile string, trashConf *conf.Con
checkout(trashDir, i)
}
os.Chdir(dir)
imports = collectImports(rootPackage, libRoot, targetDir)
imports = collectImports(rootPackage, libRoot, targetDir, buildtagfilters)
}

trashConf.Package = rootPackage // Overwrite possibly non existent root package name
Expand Down Expand Up @@ -458,7 +464,7 @@ func parentPackages(root, p string) util.Packages {
return r
}

func listImports(rootPackage, libRoot, pkg string) <-chan util.Packages {
func listImports(rootPackage, libRoot, pkg string, buildtagfilters []string) <-chan util.Packages {
pkgPath := "."
if pkg != rootPackage {
if strings.HasPrefix(pkg, rootPackage+"/") {
Expand All @@ -479,7 +485,7 @@ func listImports(rootPackage, libRoot, pkg string) <-chan util.Packages {
defer close(sch)

// Gather all the Go imports
ps, err := parser.ParseDir(token.NewFileSet(), pkgPath, noVendoredTests, parser.ImportsOnly)
ps, err := parser.ParseDir(token.NewFileSet(), pkgPath, noVendoredTests, parser.ParseComments|parser.ImportsOnly)
if err != nil {
if os.IsNotExist(err) {
logrus.Debugf("listImports, pkgPath does not exist: %s", err)
Expand All @@ -491,6 +497,10 @@ func listImports(rootPackage, libRoot, pkg string) <-chan util.Packages {
logrus.Infof("Collecting imports for package '%s'", pkg)
for _, p := range ps {
for _, f := range p.Files {
if hasFilteredBuildTag(f, buildtagfilters) {
logrus.Warn("Skipping file ", f.Name.Name)
continue
}
for _, v := range f.Imports {
imp := v.Path.Value[1 : len(v.Path.Value)-1]
if pkgComponents := strings.Split(imp, "/"); !strings.Contains(pkgComponents[0], ".") {
Expand Down Expand Up @@ -555,6 +565,41 @@ func listImports(rootPackage, libRoot, pkg string) <-chan util.Packages {
return chanPackagesFromLines(lnc)
}

func hasFilteredBuildTag(f *ast.File, filtered []string) bool {
if len(f.Comments) == 0 {
// No build tags if no comments!
return false
}
block := f.Comments[0]
if block.Pos() > f.Package {
// Ignore import comments
return false
}
if block == f.Doc {
// Build tags cannot be in the package documentation
return false
}

// Loop through comment lines, searching for build tags
for _, line := range block.List {
comment := strings.TrimSpace(line.Text[2:])
if strings.HasPrefix(comment, "+build") {
tagline := strings.TrimSpace(strings.TrimPrefix(comment, "+build"))
groups := strings.Split(tagline, " ")
for _, grp := range groups {
for _, tag := range strings.Split(grp, ",") {
for _, filter := range filtered {
if tag == filter {
return true
}
}
}
}
}
}
return false
}

func chanPackagesFromLines(lnc <-chan string) <-chan util.Packages {
return util.ChanPackages(func() util.Packages {
r := util.Packages{}
Expand Down Expand Up @@ -599,7 +644,7 @@ func listPackages(rootPackage, targetDir string) util.Packages {
return r
}

func collectImports(rootPackage, libRoot, targetDir string) util.Packages {
func collectImports(rootPackage, libRoot, targetDir string, buildtagfilters []string) util.Packages {
logrus.Infof("Collecting packages in '%s'", rootPackage)

imports := util.Packages{}
Expand All @@ -609,7 +654,7 @@ func collectImports(rootPackage, libRoot, targetDir string) util.Packages {
for len(packages) > 0 {
cs := []<-chan util.Packages{}
for p := range packages {
cs = append(cs, listImports(rootPackage, libRoot, p))
cs = append(cs, listImports(rootPackage, libRoot, p, buildtagfilters))
}
for ps := range util.MergePackagesChans(cs...) {
imports.Merge(ps)
Expand Down Expand Up @@ -761,7 +806,7 @@ func guessRootPackage(dir string) string {
return dir[len(srcPath+"/"):]
}

func cleanup(dir, targetDir string, trashConf *conf.Conf) error {
func cleanup(dir, targetDir string, trashConf *conf.Conf, buildtagfilters []string) error {
rootPackage := trashConf.Package
if rootPackage == "" {
rootPackage = guessRootPackage(dir)
Expand All @@ -771,7 +816,7 @@ func cleanup(dir, targetDir string, trashConf *conf.Conf) error {

os.Chdir(dir)

imports := collectImports(rootPackage, targetDir, targetDir)
imports := collectImports(rootPackage, targetDir, targetDir, buildtagfilters)
if err := removeExcludes(trashConf.Excludes, targetDir); err != nil {
logrus.Errorf("Error removing excluded dirs: %v", err)
}
Expand Down
27 changes: 26 additions & 1 deletion trash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,36 @@ import (
"fmt"
"go/parser"
"go/token"
"os"
"path"
"testing"

"github.com/Sirupsen/logrus"
"github.com/stretchr/testify/require"
)

func TestCollectImports(t *testing.T) {
defer logrus.SetLevel(logrus.GetLevel())
logrus.SetLevel(logrus.FatalLevel)

assert := require.New(t)
os.Chdir("./test")
defer os.Chdir("..")

libRoot := path.Join(os.Getenv("GOPATH"), "src")
trashCache := path.Join(os.Getenv("HOME"), ".trash-cache")

// Test that build tags are ignored
allPackages := collectImports(".", libRoot, trashCache, []string{})
assert.Equal(2, len(allPackages))
assert.Contains(allPackages, "github.com/Sirupsen/logrus")

// Test that a build tag can be used to filter
filteredPackages := collectImports(".", libRoot, trashCache, []string{"ignore"})
assert.Equal(1, len(filteredPackages))
assert.NotContains(filteredPackages, "github.com/Sirupsen/logrus")
}

func TestParentPackages(t *testing.T) {
assert := require.New(t)

Expand Down Expand Up @@ -48,8 +72,9 @@ func TestListPackages(t *testing.T) {
assert := require.New(t)
p := listPackages("github.com/rancher/trash", "vendor")
logrus.Debug(p)
assert.Equal(3, len(p))
assert.Equal(4, len(p))
assert.Contains(p, "github.com/rancher/trash")
assert.Contains(p, "github.com/rancher/trash/util")
assert.Contains(p, "github.com/rancher/trash/conf")
assert.Contains(p, "github.com/rancher/trash/test")
}

0 comments on commit 2fa2338

Please sign in to comment.