github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/analyzers/rust/rust.go (about) 1 // Package rust provides analysers for Rust projects. 2 // 3 // A `BuildTarget` in Rust is the directory of the Rust project containing `Cargo.lock`. 4 5 package rust 6 7 import ( 8 "os" 9 "path/filepath" 10 11 "github.com/apex/log" 12 "github.com/mitchellh/mapstructure" 13 14 "github.com/fossas/fossa-cli/buildtools/cargo" 15 "github.com/fossas/fossa-cli/errors" 16 "github.com/fossas/fossa-cli/files" 17 "github.com/fossas/fossa-cli/graph" 18 "github.com/fossas/fossa-cli/module" 19 "github.com/fossas/fossa-cli/pkg" 20 ) 21 22 type Analyzer struct { 23 Module module.Module 24 Options Options 25 } 26 27 type Options struct { 28 Strategy string `mapstructure:"strategy"` 29 } 30 31 func New(m module.Module) (*Analyzer, error) { 32 log.WithField("options", m.Options).Debug("constructing analyzer") 33 34 var options Options 35 err := mapstructure.Decode(m.Options, &options) 36 if err != nil { 37 return nil, err 38 } 39 log.WithField("options", options).Debug("parsed analyzer options") 40 41 return &Analyzer{ 42 Module: m, 43 Options: options, 44 }, nil 45 } 46 47 // Discover constructs modules in all directories with a `Cargo.lock`. 48 func Discover(dir string, options map[string]interface{}) ([]module.Module, error) { 49 var modules []module.Module 50 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 51 if err != nil { 52 log.WithError(err).WithField("path", path).Debug("error while walking for discovery") 53 } 54 55 if !info.IsDir() && info.Name() == "Cargo.lock" { 56 log.WithFields(log.Fields{ 57 "path": path, 58 "name": path, 59 }).Debug("found Rust module") 60 relPath, err := filepath.Rel(dir, path) 61 if err != nil { 62 return errors.Wrap(err, "error discovering rust modules") 63 } 64 modules = append(modules, module.Module{ 65 Name: path, 66 Type: pkg.Rust, 67 BuildTarget: filepath.Dir(relPath), 68 Dir: filepath.Dir(relPath), 69 }) 70 } 71 return nil 72 }) 73 if err != nil { 74 return nil, errors.Wrap(err, "Could not find Rust package manifests:") 75 } 76 77 return modules, nil 78 } 79 80 // Clean logs a warning and does nothing for Rust. 81 func (a *Analyzer) Clean() error { 82 log.Warnf("Clean is not implemented for Rust") 83 return nil 84 } 85 86 func (a *Analyzer) Build() error { 87 return errors.New("Build is not implemented for Rust") 88 } 89 90 func (a *Analyzer) IsBuilt() (bool, error) { 91 return files.Exists(a.Module.Dir, "Cargo.lock") 92 } 93 94 func (a *Analyzer) Analyze() (graph.Deps, error) { 95 switch a.Options.Strategy { 96 case "manifest": 97 // TODO: Add for filetree scanning. 98 fallthrough 99 case "cargo-tree": 100 // TODO: Check for `cargo-tree` command and parse output. 101 // This will give the most accurate results. 102 fallthrough 103 case "lockfile": 104 fallthrough 105 default: 106 return cargo.LockfileDependencies("Cargo.lock", a.Module.Dir) 107 } 108 }