github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/utils/nuget/solution/solution.go (about) 1 package solution 2 3 import ( 4 "encoding/json" 5 "errors" 6 "github.com/jfrog/jfrog-cli-go/artifactory/utils/nuget/solution/project" 7 "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" 8 "github.com/jfrog/jfrog-client-go/utils" 9 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 10 "github.com/jfrog/jfrog-client-go/utils/log" 11 "io/ioutil" 12 "path/filepath" 13 "regexp" 14 "strings" 15 ) 16 17 type Solution interface { 18 BuildInfo(module string) (*buildinfo.BuildInfo, error) 19 Marshal() ([]byte, error) 20 GetProjects() []project.Project 21 } 22 23 var projectRegExp *regexp.Regexp 24 25 func Load(solutionPath, slnFile string) (Solution, error) { 26 solution := &solution{path: solutionPath, slnFile: slnFile} 27 err := solution.loadProjects() 28 return solution, err 29 } 30 31 type solution struct { 32 path string 33 // If there are more then one sln files in the directory, 34 // the user must specify as arguments the sln file that should be used. 35 slnFile string 36 projects []project.Project 37 } 38 39 func (solution *solution) BuildInfo(module string) (*buildinfo.BuildInfo, error) { 40 buildInfo := &buildinfo.BuildInfo{} 41 var modules []buildinfo.Module 42 for _, project := range solution.projects { 43 // Get All project dependencies 44 dependencies, err := project.Extractor().AllDependencies() 45 if err != nil { 46 return nil, err 47 } 48 var projectDependencies []buildinfo.Dependency 49 50 for _, dep := range dependencies { 51 projectDependencies = append(projectDependencies, *dep) 52 } 53 module := buildinfo.Module{Id: getModuleId(module, project.Name()), Dependencies: projectDependencies} 54 modules = append(modules, module) 55 } 56 buildInfo.Modules = modules 57 return buildInfo, nil 58 } 59 60 func getModuleId(customModuleID, projectName string) string { 61 if customModuleID != "" { 62 return customModuleID 63 } 64 return projectName 65 } 66 67 func (solution *solution) Marshal() ([]byte, error) { 68 return json.Marshal(&struct { 69 Projects []project.Project `json:"projects,omitempty"` 70 }{ 71 Projects: solution.projects, 72 }) 73 } 74 75 func (solution *solution) GetProjects() []project.Project { 76 return solution.projects 77 } 78 79 func (solution *solution) loadProjects() error { 80 allProjects, err := solution.getProjectsFromSlns() 81 if err != nil { 82 return err 83 } 84 85 for _, projectLine := range allProjects { 86 projectName, csprojPath, err := parseProject(projectLine, solution.path) 87 if err != nil { 88 log.Error(err) 89 continue 90 } 91 proj, err := project.Load(projectName, filepath.Dir(csprojPath), csprojPath) 92 if err != nil { 93 log.Error(err) 94 continue 95 } 96 if proj.Extractor() != nil { 97 solution.projects = append(solution.projects, proj) 98 } 99 } 100 return nil 101 } 102 103 // Finds all the projects by reading the content of the the sln files. If sln file is not provided, 104 // finds all sln files in the directory. 105 // Returns a slice with all the projects in the solution. 106 func (solution *solution) getProjectsFromSlns() ([]string, error) { 107 var allProjects []string 108 if solution.slnFile == "" { 109 slnFiles, err := fileutils.ListFilesWithExtension(solution.path, ".sln") 110 if err != nil { 111 return nil, err 112 } 113 for _, slnFile := range slnFiles { 114 projects, err := parseSlnFile(slnFile) 115 if err != nil { 116 return nil, err 117 } 118 allProjects = append(allProjects, projects...) 119 } 120 } else { 121 projects, err := parseSlnFile(filepath.Join(solution.path, solution.slnFile)) 122 if err != nil { 123 return nil, err 124 } 125 allProjects = append(allProjects, projects...) 126 } 127 return allProjects, nil 128 } 129 130 // Parses the project line for the project name and path information. 131 // Returns the name and path to csproj 132 func parseProject(projectLine, path string) (projectName, csprojPath string, err error) { 133 parsedLine := strings.Split(projectLine, "=") 134 if len(parsedLine) <= 1 { 135 return "", "", errors.New("Unexpected project line format: " + projectLine) 136 } 137 138 projectInfo := strings.Split(parsedLine[1], ",") 139 if len(projectInfo) <= 2 { 140 return "", "", errors.New("Unexpected project information format: " + parsedLine[1]) 141 } 142 projectName = removeQuotes(projectInfo[0]) 143 csprojPath = filepath.Join(path, removeQuotes(projectInfo[1])) 144 return 145 } 146 147 // Parse the sln file according to project regular expression and returns all the founded lines by the regex 148 func parseSlnFile(slnFile string) ([]string, error) { 149 var err error 150 if projectRegExp == nil { 151 projectRegExp, err = utils.GetRegExp(`Project\("(.*)\nEndProject`) 152 if err != nil { 153 return nil, err 154 } 155 } 156 157 content, err := ioutil.ReadFile(slnFile) 158 if err != nil { 159 return nil, err 160 } 161 projects := projectRegExp.FindAllString(string(content), -1) 162 return projects, nil 163 } 164 165 func removeQuotes(value string) string { 166 return strings.Trim(strings.TrimSpace(value), "\"") 167 }