github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/sbt/sbt.go (about) 1 package sbt 2 3 import ( 4 "regexp" 5 "strings" 6 7 "github.com/apex/log" 8 "github.com/pkg/errors" 9 10 "github.com/fossas/fossa-cli/exec" 11 "github.com/fossas/fossa-cli/files" 12 "github.com/fossas/fossa-cli/pkg" 13 ) 14 15 type SBT struct { 16 Bin string 17 } 18 19 func (s *SBT) Clean(dir, project, configuration string) error { 20 _, _, err := exec.Run(exec.Cmd{ 21 Dir: dir, 22 Name: s.Bin, 23 Argv: []string{Task(project, configuration, "clean")}, 24 }) 25 return err 26 } 27 28 func (s *SBT) Compile(dir, project, configuration string) error { 29 _, _, err := exec.Run(exec.Cmd{ 30 Dir: dir, 31 Name: s.Bin, 32 Argv: []string{Task(project, configuration, "compile")}, 33 }) 34 return err 35 } 36 37 func (s *SBT) Projects(dir string) ([]string, error) { 38 output, _, err := exec.Run(exec.Cmd{ 39 Dir: dir, 40 Name: s.Bin, 41 Argv: []string{"-no-colors", "projects"}, 42 }) 43 if err != nil { 44 return nil, errors.Wrap(err, "could not get projects from SBT") 45 } 46 47 // Filter lines to only include projects. 48 var projects []string 49 for _, project := range FilterLines(strings.Split(output, "\n")) { 50 log.WithField("project", project).Debug("project line") 51 noPrefix := strings.TrimPrefix(project, "[info] ") 52 noSelectedPrefix := strings.TrimPrefix(noPrefix, "[info] * ") 53 log.WithField("project", project).Debug("trimmed project line") 54 projects = append(projects, noSelectedPrefix) 55 } 56 return projects, nil 57 } 58 59 type Dependency struct { 60 Name string 61 Version string 62 } 63 64 func (s *SBT) DependencyTree(dir, project, configuration string) (pkg.Imports, pkg.Deps, error) { 65 output, _, err := exec.Run(exec.Cmd{ 66 Dir: dir, 67 Name: s.Bin, 68 Argv: []string{"-no-colors", Task(project, configuration, "dependencyGraphMl")}, 69 }) 70 if err != nil { 71 return nil, nil, errors.Wrap(err, "could not get dependency graph from SBT") 72 } 73 74 file := "" 75 r := regexp.MustCompile("^\\[info\\] Wrote dependency graph to '(.*?)'$") 76 for _, line := range strings.Split(output, "\n") { 77 matches := r.FindStringSubmatch(line) 78 if matches != nil { 79 file = matches[1] 80 } 81 } 82 log.WithField("file", file).Debug("graph XML file") 83 84 var root GraphML 85 err = files.ReadXML(&root, file) 86 if err != nil { 87 return nil, nil, errors.Wrap(err, "could not parse SBT dependency graph") 88 } 89 log.WithField("root", root).Debug("parsed XML graph") 90 91 evicted, _, err := exec.Run(exec.Cmd{ 92 Dir: dir, 93 Name: s.Bin, 94 Argv: []string{"-no-colors", Task(project, configuration, "evicted")}, 95 }) 96 if err != nil { 97 return nil, nil, errors.Wrap(err, "could not get version conflict resolutions from SBT") 98 } 99 100 return ParseDependencyGraph(root.Graph, evicted) 101 } 102 103 func (s *SBT) DependencyList(dir, project, configuration string) (string, error) { 104 output, _, err := exec.Run(exec.Cmd{ 105 Dir: dir, 106 Name: s.Bin, 107 Argv: []string{"-no-colors", Task(project, configuration, "dependencyList")}, 108 }) 109 if err != nil { 110 return "", errors.Wrap(err, "could not get dependency list from SBT") 111 } 112 113 // Filter lines to only include dependency list. 114 return strings.Join(FilterLines(strings.Split(output, "\n")), "\n"), err 115 } 116 117 func FilterLine(line string) bool { 118 trimmed := strings.TrimSpace(line) 119 if !strings.HasPrefix(trimmed, "[info] ") { 120 return false 121 } 122 infoMsg := strings.TrimPrefix(trimmed, "[info] ") 123 return !(strings.HasPrefix(infoMsg, "Loading ") || 124 strings.HasPrefix(infoMsg, "Compiling ") || 125 strings.HasPrefix(infoMsg, "Non-compiled module ") || 126 strings.HasPrefix(strings.TrimSpace(infoMsg), "Compilation ") || 127 strings.HasPrefix(infoMsg, "Resolving ") || 128 strings.HasPrefix(infoMsg, "Resolved ") || 129 strings.HasPrefix(infoMsg, "Fetching ") || 130 strings.HasPrefix(infoMsg, "Fetched ") || 131 strings.HasPrefix(infoMsg, "Set ") || 132 strings.HasPrefix(infoMsg, "In file:") || 133 strings.HasPrefix(infoMsg, "Updating ") || 134 strings.HasPrefix(infoMsg, "Done ") || 135 strings.HasPrefix(infoMsg, "downloading ") || 136 strings.HasPrefix(strings.TrimSpace(infoMsg), "[SUCCESSFUL ]")) 137 } 138 139 func FilterLines(lines []string) []string { 140 var filtered []string 141 for _, line := range lines { 142 if FilterLine(line) { 143 log.WithField("line", line).Debug("matched line") 144 filtered = append(filtered, line) 145 } else { 146 log.WithField("line", line).Debug("ignoring line") 147 } 148 } 149 return filtered 150 } 151 152 func Task(project, configuration, task string) string { 153 cmd := task 154 if configuration != "" { 155 cmd = configuration + ":" + cmd 156 } 157 if project != "" { 158 cmd = project + "/" + cmd 159 } 160 return cmd 161 }