github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/cargo/cargo.go (about) 1 package cargo 2 3 import ( 4 "path/filepath" 5 "strings" 6 7 "github.com/apex/log" 8 9 "github.com/fossas/fossa-cli/errors" 10 "github.com/fossas/fossa-cli/files" 11 "github.com/fossas/fossa-cli/graph" 12 "github.com/fossas/fossa-cli/pkg" 13 ) 14 15 type manifest struct { 16 Workspace workspace 17 Dependencies map[string]interface{} `toml:"dependencies"` 18 BuildDependencies map[string]interface{} `toml:"build-dependencies"` 19 Package Package 20 } 21 22 type workspace struct { 23 Members []string 24 } 25 26 type lockfile struct { 27 Packages []Package `toml:"package"` 28 } 29 30 // Package is a single imported repository within a dep project. 31 type Package struct { 32 Name string 33 Dependencies []string 34 Version string 35 Source string 36 } 37 38 // LockfileDependencies uses a lockfile and the associated manifest file to create a dependency 39 // graph. This method approximates the direct dependencies by selecting all dependencies 40 // in the manifest file as direct dependencies and determines the version from the lockfile. 41 func LockfileDependencies(lockfilePath string, dir string) (graph.Deps, error) { 42 var lock lockfile 43 err := files.ReadTOML(&lock, filepath.Join(dir, lockfilePath)) 44 if err != nil { 45 return graph.Deps{}, errors.Wrap(err, "No lockfile Cargo.lock found") 46 } 47 48 IDMap := make(map[string]pkg.ID) 49 for _, dep := range lock.Packages { 50 IDMap[dep.Name] = pkg.ID{ 51 Type: pkg.Rust, 52 Name: dep.Name, 53 Revision: dep.Version, 54 Location: dep.Source, 55 } 56 } 57 58 transitiveDependenices := make(map[pkg.ID]pkg.Package) 59 for _, dep := range lock.Packages { 60 imports := []pkg.Import{} 61 for _, trans := range dep.Dependencies { 62 transDep := strings.Split(trans, " ") 63 imports = append(imports, pkg.Import{ 64 Target: transDep[0], 65 Resolved: IDMap[transDep[0]], 66 }) 67 } 68 69 transitiveDependenices[IDMap[dep.Name]] = pkg.Package{ 70 ID: IDMap[dep.Name], 71 Imports: imports, 72 } 73 } 74 75 manifests := []manifest{} 76 var man manifest 77 err = files.ReadTOML(&man, filepath.Join(dir, "Cargo.toml")) 78 if err != nil { 79 log.Warnf("manifest file `Cargo.toml` was not found in directory: %s. direct dependencies may be incorrect. error: %+v", dir, err) 80 } 81 manifests = append(manifests, man) 82 83 for _, member := range man.Workspace.Members { 84 memberManifest := manifest{} 85 memberFile := filepath.Join(dir, member, "Cargo.toml") 86 err = files.ReadTOML(&memberManifest, memberFile) 87 if err != nil { 88 log.Warnf("member manifest file `%s` was not able to be read. direct dependencies may be incorrect. error: %+v", memberFile, err) 89 continue 90 } 91 manifests = append(manifests, memberManifest) 92 } 93 94 imports := []pkg.Import{} 95 for _, manifest := range manifests { 96 for dep := range manifest.Dependencies { 97 imports = append(imports, pkg.Import{ 98 Target: dep, 99 Resolved: IDMap[dep], 100 }) 101 } 102 for dep := range manifest.BuildDependencies { 103 imports = append(imports, pkg.Import{ 104 Target: dep, 105 Resolved: IDMap[dep], 106 }) 107 } 108 } 109 110 return graph.Deps{ 111 Direct: imports, 112 Transitive: transitiveDependenices, 113 }, nil 114 }