/
scan.go
78 lines (72 loc) · 1.81 KB
/
scan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package pkg
import (
"bytes"
"fmt"
"os/exec"
"path/filepath"
"sort"
"strings"
)
// Scan will scan a project using go list. As go list is running
// in the background, scan will display a waiting indicator.
func Scan(projectName string, parallel int) (*Packages, error) {
pkgs := NewPackages(parallel)
// Format: [packageName] = {outSide import count}
c := "go"
args := []string{
"list",
"-f",
"{{.ImportPath}} {{join .Imports \",\"}} {{join .GoFiles \",\"}} {{.Dir}}",
"./...",
}
/* #nosec */
cmd := exec.Command(c, args...)
fmt.Print("Waiting for go list to finish scanning the project...")
b, err := cmd.Output()
if err != nil {
return nil, err
}
fmt.Print("done.\n")
lines := bytes.Split(b, []byte("\n"))
for _, line := range lines {
split := bytes.Split(line, []byte(" "))
if len(split) < 2 {
continue
}
pkg := split[0]
imports := split[1]
goFiles := string(split[2])
dir := split[3]
gf := strings.Split(goFiles, ",")
is := bytes.Split(imports, []byte(","))
p := Package{
Name: filepath.Base(string(pkg)),
Imports: make([]string, 0),
ImportCount: 0,
DependedOnByCount: 0,
FullName: string(pkg),
Stability: 0.0,
GoFiles: gf,
Dir: string(dir),
}
for _, i := range is {
if bytes.Contains(i, []byte(".")) {
if len(projectName) > 0 && !bytes.Contains(i, []byte(projectName)) {
continue
}
p.Imports = append(p.Imports, string(i))
p.ImportCount++
}
}
pkgs.packageMap[p.FullName] = p
pkgs.packageNames = append(pkgs.packageNames, p.FullName)
}
sort.Strings(pkgs.packageNames)
pkgs.GatherDependedOnByCount()
pkgs.CalculateInstability()
if err := pkgs.CalculateAbstractnessOfPackages(); err != nil {
return pkgs, err
}
pkgs.CalculateDistance()
return pkgs, nil
}