Skip to content

Commit

Permalink
feat(sbt): SBT path data parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
elldritch committed Apr 27, 2018
1 parent 75f22ce commit 0a58a70
Showing 1 changed file with 51 additions and 17 deletions.
68 changes: 51 additions & 17 deletions builders/sbt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/bmatcuk/doublestar"
Expand Down Expand Up @@ -68,16 +69,17 @@ func (builder *SBTBuilder) Build(m module.Module, force bool) error {
return nil
}

// Analyze parses the output of `sbt -no-colors dependencyList`
// Analyze parses the output of `sbt -no-colors dependencyTree`
func (builder *SBTBuilder) Analyze(m module.Module, allowUnresolved bool) ([]module.Dependency, error) {
sbtLogger.Debugf("Running SBT analysis: %#v %#v", m, allowUnresolved)

output, _, err := runLogged(sbtLogger, m.Dir, builder.SBTCmd, "-no-colors", "dependencyList")
output, _, err := runLogged(sbtLogger, m.Dir, builder.SBTCmd, "-no-colors", "dependencyTree")
if err != nil {
return nil, fmt.Errorf("could not get dependency list from SBT: %s", err.Error())
return nil, fmt.Errorf("could not get dependency tree from SBT: %s", err.Error())
}

deps := []module.Dependency{}
// Filter lines to only include dependency tree
var depLines []string
for _, line := range strings.Split(output, "\n") {
if strings.Index(line, "[info] Loading ") != -1 ||
strings.Index(line, "[info] Resolving ") != -1 ||
Expand All @@ -89,22 +91,54 @@ func (builder *SBTBuilder) Analyze(m module.Module, allowUnresolved bool) ([]mod
continue
}
sbtLogger.Debugf("Matched line: %#v", line)
depLines = append(depLines, line)
}

if len(line) > 0 {
depLocator := strings.TrimSpace(strings.TrimPrefix(line, "[info] "))
depSections := strings.Split(depLocator, ":")
dep := module.Dependency{
Locator: module.Locator{
Fetcher: "mvn",
Project: depSections[0] + ":" + depSections[1],
Revision: depSections[2],
},
Via: nil,
}
sbtLogger.Debugf("Adding dep: %#v", dep)
deps = append(deps, dep)
// Parse dependency tree
var imports []Imported
root := module.Locator{
Fetcher: "root",
Project: "root",
Revision: "root",
}
from := module.ImportPath{root}
depRegex := regexp.MustCompile("^\\[info\\] ([ `+\\\\|-]*)([^ `+\\\\|-].+)$")
spacerRegex := regexp.MustCompile("^\\[info\\] ([ `+\\\\|-]*)(\\s*?)$")
locatorRegex := regexp.MustCompile("([^:\\s]+):([^:\\s]+):([^:\\s]+).*")
for _, line := range depLines {
sbtLogger.Debugf("Parsing line: %#v\n", line)
if spacerRegex.MatchString(line) {
continue
}
// Match for context
depMatches := depRegex.FindStringSubmatch(line)
sbtLogger.Debugf("Dep matches: %#v\n", depMatches)
depth := len(depMatches[1])
// SBT quirk: the indentation from level 1 to level 2 is 4 spaces, but all others are 2 spaces
if depth >= 4 {
depth -= 2
}
if depth%2 != 0 {
// Sanity check
sbtLogger.Panicf("Bad depth: %#v %s %#v", depth, line, depMatches)
}
// Parse locator
locatorMatches := locatorRegex.FindStringSubmatch(depMatches[2])
sbtLogger.Debugf("Locator matches: %#v\n", locatorMatches)
locator := module.Locator{
Fetcher: "sbt",
Project: locatorMatches[1] + ":" + locatorMatches[2],
Revision: locatorMatches[3],
}
// Add to imports
from = from[:depth/2]
imports = append(imports, Imported{
Locator: locator,
From: append(module.ImportPath{}, from...),
})
from = append(from, locator)
}
deps := computeImportPaths(imports)

sbtLogger.Debugf("Done running SBT analysis: %#v", deps)
return deps, nil
Expand Down

0 comments on commit 0a58a70

Please sign in to comment.