github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/dotnet/package_reference.go (about) 1 package dotnet 2 3 import ( 4 "path/filepath" 5 "regexp" 6 7 "github.com/fossas/fossa-cli/files" 8 "github.com/fossas/fossa-cli/graph" 9 "github.com/fossas/fossa-cli/pkg" 10 ) 11 12 type Manifest struct { 13 PropertyGroup []PropertyGroup 14 ItemGroup []ItemGroup 15 } 16 17 type PropertyGroup struct { 18 RootNamespace string 19 Version string 20 } 21 22 type ItemGroup struct { 23 Reference []Reference 24 PackageReference []Reference 25 ProjectReference []Reference 26 } 27 28 type Reference struct { 29 Include string `xml:",attr"` 30 Version string `xml:"Version"` 31 } 32 33 func (m *Manifest) Name() string { 34 for _, propertyGroup := range m.PropertyGroup { 35 if propertyGroup.RootNamespace != "" { 36 return propertyGroup.RootNamespace 37 } 38 } 39 return "" 40 } 41 42 func (m *Manifest) Version() string { 43 for _, propertyGroup := range m.PropertyGroup { 44 if propertyGroup.Version != "" { 45 return propertyGroup.Version 46 } 47 } 48 return "" 49 } 50 51 func (m *Manifest) packages() []Reference { 52 var references []Reference 53 for _, itemGroup := range m.ItemGroup { 54 references = append(references, itemGroup.PackageReference...) 55 } 56 return references 57 } 58 59 func (m *Manifest) projects() []Reference { 60 var projects []Reference 61 for _, itemGroup := range m.ItemGroup { 62 projects = append(projects, itemGroup.ProjectReference...) 63 } 64 return projects 65 } 66 67 // IsPackageReferenceFile checks for a valid package reference file name. 68 func IsPackageReferenceFile(filename string) bool { 69 var xmlProj = regexp.MustCompile(`\.(cs|x|vb|db|fs)proj$`) 70 return xmlProj.MatchString(filename) 71 } 72 73 // PackageReferenceGraph reads a package reference file and returns a dependency graph. 74 func PackageReferenceGraph(file string) (graph.Deps, error) { 75 imports := []pkg.Import{} 76 dependencyMap := make(map[pkg.ID]pkg.Package) 77 78 projects := make(map[string]Manifest) 79 err := Projects(projects, file) 80 if err != nil { 81 return graph.Deps{}, nil 82 } 83 84 for _, project := range projects { 85 for _, reference := range project.packages() { 86 id := pkg.ID{ 87 Type: pkg.NuGet, 88 Name: reference.Include, 89 Revision: reference.Version, 90 } 91 imports = append(imports, pkg.Import{ 92 Target: reference.Include, 93 Resolved: id, 94 }) 95 dependencyMap[id] = pkg.Package{ 96 ID: id, 97 } 98 } 99 } 100 101 return graph.Deps{ 102 Direct: imports, 103 Transitive: dependencyMap, 104 }, nil 105 } 106 107 // Projects recursively discovers references to other manifest files from the base manifest file. 108 func Projects(projects map[string]Manifest, projectFile string) error { 109 // Break out of cycles. 110 if _, ok := projects[projectFile]; ok { 111 return nil 112 } 113 114 var manifest Manifest 115 err := files.ReadXML(&manifest, projectFile) 116 if err != nil { 117 return err 118 } 119 projects[projectFile] = manifest 120 121 // Get all project reference files and recurse. 122 for _, reference := range manifest.projects() { 123 err = Projects(projects, filepath.Join(filepath.Dir(projectFile), Path(reference.Include))) 124 if err != nil { 125 return err 126 } 127 } 128 129 return nil 130 }