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  }