github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/dep/dep.go (about) 1 // Package dep provides functions for working with the dep tool. 2 package dep 3 4 import ( 5 "path" 6 "strings" 7 8 "github.com/pkg/errors" 9 10 "github.com/fossas/fossa-cli/buildtools" 11 "github.com/fossas/fossa-cli/files" 12 "github.com/fossas/fossa-cli/pkg" 13 ) 14 15 // Resolver contains both the lockfile and manifest information. Resolver implements golang.Resolver. 16 type Resolver struct { 17 manifest manifest 18 lockfile lockfile 19 } 20 21 // manifest contains the ignored packages in a dep toml file. manifest implements golang.Resolver. 22 type manifest struct { 23 Ignored []string 24 } 25 26 // lockfile contains the Projects in a dep lockfile and a corresponding map for retrieving project data. 27 type lockfile struct { 28 Projects []Project 29 normalized map[string]pkg.Import 30 } 31 32 // Project is a single imported repository within a dep project. 33 type Project struct { 34 Name string 35 Packages []string 36 Revision string 37 Version string 38 } 39 40 // Resolve returns the revision of an imported Go package contained within the 41 // lockfile and checks to see if it should be ignored. If the package cannot be 42 // ignored and is not found, buildtools.ErrNoRevisionForPackage is returned. 43 func (r Resolver) Resolve(importpath string) (pkg.Import, error) { 44 if r.manifest.isIgnored(importpath) { 45 return pkg.Import{}, buildtools.ErrPackageIsIgnored 46 } 47 48 revision, ok := r.lockfile.normalized[importpath] 49 if !ok { 50 return pkg.Import{}, buildtools.ErrNoRevisionForPackage 51 } 52 53 return revision, nil 54 } 55 56 // isIgnored checks if a Go package can be ignored according to a dep manifest. 57 func (m manifest) isIgnored(importpath string) bool { 58 for _, ignoredPackage := range m.Ignored { 59 if strings.HasSuffix(ignoredPackage, "*") { 60 ignoredPrefix := ignoredPackage[:len(ignoredPackage)-1] 61 if strings.HasPrefix(importpath, ignoredPrefix) { 62 return true 63 } 64 } 65 66 if ignoredPackage == importpath { 67 return true 68 } 69 } 70 71 return false 72 } 73 74 // New constructs a golang.Resolver given the path to the manifest and lockfile. 75 func New(lockfilePath string, manifestPath string) (Resolver, error) { 76 var err error 77 78 resolver := Resolver{} 79 resolver.lockfile, err = readLockfile(lockfilePath) 80 if err != nil { 81 return Resolver{}, err 82 } 83 84 resolver.manifest, err = readManifest(manifestPath) 85 if err != nil { 86 return Resolver{}, err 87 } 88 89 return resolver, nil 90 } 91 92 // readLockfile returns a lockfile object using the provided filepath. 93 func readLockfile(filepath string) (lockfile, error) { 94 var lock lockfile 95 96 err := files.ReadTOML(&lock, filepath) 97 if err != nil { 98 return lockfile{}, errors.Wrap(err, "No lockfile Gopkg.lock found") 99 } 100 101 normalized := make(map[string]pkg.Import) 102 for _, project := range lock.Projects { 103 for _, pk := range project.Packages { 104 revision := project.Version 105 if revision == "" { 106 revision = project.Revision 107 } 108 importpath := path.Join(project.Name, pk) 109 normalized[importpath] = pkg.Import{ 110 Target: project.Version, 111 Resolved: pkg.ID{ 112 Type: pkg.Go, 113 Name: importpath, 114 Revision: revision, 115 Location: "", 116 }, 117 } 118 } 119 } 120 121 lock.normalized = normalized 122 return lock, nil 123 } 124 125 // readManifest returns a manifest using the provided filepath. 126 func readManifest(filepath string) (manifest, error) { 127 var man manifest 128 err := files.ReadTOML(&man, filepath) 129 if err != nil { 130 return manifest{}, errors.Wrap(err, "No manifest Gopkg.toml found") 131 } 132 133 return man, nil 134 }