github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/analyzers/nuget/nuget.go (about) 1 // Package nuget implements NuGet analysis. 2 // 3 // A `BuildTarget` for NuGet is the path to the project file (e.g. the *.csproj 4 // file). 5 package nuget 6 7 import ( 8 "os" 9 "path/filepath" 10 "strings" 11 12 "github.com/apex/log" 13 "github.com/mitchellh/mapstructure" 14 15 "github.com/fossas/fossa-cli/buildtools/dotnet" 16 "github.com/fossas/fossa-cli/exec" 17 "github.com/fossas/fossa-cli/files" 18 "github.com/fossas/fossa-cli/module" 19 "github.com/fossas/fossa-cli/pkg" 20 ) 21 22 type Analyzer struct { 23 dotNET dotnet.DotNET 24 Module module.Module 25 Options Options 26 } 27 28 type Options struct { 29 Strategy string `mapstructure:"strategy"` 30 } 31 32 func New(m module.Module) (*Analyzer, error) { 33 log.WithField("options", m.Options).Debug("constructing analyzer") 34 // Set Bower context variables 35 dotnetCmd, dotnetVersion, err := exec.Which("--version", os.Getenv("DOTNET_BINARY"), "dotnet") 36 if err != nil { 37 log.Warn("Cannot find .NET binary") 38 } 39 40 // Decode options 41 var options Options 42 err = mapstructure.Decode(m.Options, &options) 43 if err != nil { 44 return nil, err 45 } 46 47 analyzer := Analyzer{ 48 dotNET: dotnet.DotNET{ 49 Version: dotnetVersion, 50 Cmd: dotnetCmd, 51 }, 52 Module: m, 53 Options: options, 54 } 55 56 log.Debugf("analyzer: %#v", analyzer) 57 return &analyzer, nil 58 } 59 60 func Discover(dir string, options map[string]interface{}) ([]module.Module, error) { 61 moduleMap := make(map[string]module.Module) 62 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 63 if err != nil { 64 log.WithError(err).WithField("path", path).Debug("error while walking for discovery") 65 return err 66 } 67 68 if !info.IsDir() { 69 name := info.Name() 70 dir := filepath.Dir(path) 71 moduleName := dir 72 target := dir 73 existingModule, directoryDiscovered := moduleMap[dir] 74 75 // Module preference 76 // 1. Package Reference 77 // 2. Nuspec 78 // 3. packages.config, project.json, paket.lock 79 if dotnet.IsPackageReferenceFile(name) { 80 // For *.{cs,x,vb,db,fs}proj files, use the first <RootNamespace> seen. 81 var manifest dotnet.Manifest 82 err := files.ReadXML(&manifest, path) 83 if err != nil { 84 return err 85 } 86 if n := manifest.Name(); n != "" { 87 moduleName = n 88 } 89 target = path 90 } else if strings.HasSuffix(name, ".nuspec") && (!directoryDiscovered || !dotnet.IsPackageReferenceFile(existingModule.BuildTarget)) { 91 // For *.nuspec files, use the <id>. 92 var nuspec dotnet.NuSpec 93 err := files.ReadXML(&nuspec, path) 94 if err != nil { 95 return err 96 } 97 if id := nuspec.Metadata.ID; id != "" { 98 moduleName = id 99 } 100 target = path 101 } else if (name == "packages.config" || name == "project.json" || name == "paket.lock") && !directoryDiscovered { 102 // For other module indicators, use the directory name. 103 target = dir 104 } else { 105 return nil 106 } 107 108 moduleMap[dir] = module.Module{ 109 Name: moduleName, 110 Type: pkg.NuGet, 111 BuildTarget: target, 112 Dir: dir, 113 } 114 return nil 115 } 116 117 return nil 118 }) 119 if err != nil { 120 return nil, err 121 } 122 123 var modules []module.Module 124 for _, module := range moduleMap { 125 modules = append(modules, module) 126 } 127 return modules, nil 128 } 129 130 func (a *Analyzer) Clean() error { 131 log.Warn("Clean is not implemented for NuGet") 132 return nil 133 } 134 135 func (a *Analyzer) Build() error { 136 return a.dotNET.Build(Dir(a.Module)) 137 } 138 139 func (a *Analyzer) IsBuilt() (bool, error) { 140 return files.Exists(Dir(a.Module), "obj", "project.assets.json") 141 }