shad-go/tools/testtool/commands/list.go
2023-04-28 00:43:03 +04:00

165 lines
3.7 KiB
Go

package commands
import (
"bytes"
"io/fs"
"log"
"os"
"path/filepath"
"sort"
"strings"
"golang.org/x/tools/go/packages"
)
// getPackageFiles returns absolute paths for all files in rootPackage and it's subpackages
// including tests and non-go files.
func getPackageFiles(rootPackage string, buildFlags []string) map[string]struct{} {
cfg := &packages.Config{
Dir: rootPackage,
Mode: packages.NeedFiles,
BuildFlags: buildFlags,
Tests: true,
}
pkgs, err := packages.Load(cfg, "./...")
if err != nil {
log.Fatalf("unable to load packages %s: %s", rootPackage, err)
}
if packages.PrintErrors(pkgs) > 0 {
os.Exit(1)
}
files := make(map[string]struct{})
for _, p := range pkgs {
for _, f := range p.GoFiles {
if strings.HasSuffix(f, ".go") {
files[f] = struct{}{}
}
}
}
return files
}
// listTestFiles returns absolute paths for all _test.go files of the package
// including the ones with "private" build tag.
func listTestFiles(rootPackage string) []string {
files := getPackageFiles(rootPackage, []string{"-tags", "private"})
var tests []string
for f := range files {
if strings.HasSuffix(f, "_test.go") {
tests = append(tests, f)
}
}
sort.Strings(tests)
return tests
}
// listProtectedFiles returns absolute paths for all files of the package
// protected by "!change" build tag.
func listProtectedFiles(rootPackage string) []string {
allFiles := getPackageFiles(rootPackage, nil)
allFilesWithoutProtected := getPackageFiles(rootPackage, []string{"-tags", "change"})
var protectedFiles []string
for f := range allFiles {
if _, ok := allFilesWithoutProtected[f]; !ok {
protectedFiles = append(protectedFiles, f)
}
}
sort.Strings(protectedFiles)
return protectedFiles
}
// listPrivateFiles returns absolute paths for all files of the package
// protected by "private,solution" build tag.
func listPrivateFiles(rootPackage string) []string {
allFiles := getPackageFiles(rootPackage, []string{})
allWithPrivate := getPackageFiles(rootPackage, []string{"-tags", "private,solution"})
var files []string
for f := range allWithPrivate {
if _, isPublic := allFiles[f]; !isPublic {
files = append(files, f)
}
}
if err := filepath.WalkDir(rootPackage, func(path string, d fs.DirEntry, err error) error {
if strings.HasSuffix(path, ".proto") {
content, err := os.ReadFile(path)
if err != nil {
return err
}
if bytes.Contains(content, []byte("//go:build solution")) {
absPath, err := filepath.Abs(path)
if err != nil {
return err
}
files = append(files, absPath)
}
}
return nil
}); err != nil {
log.Fatalf("filewalk failed: %v", err)
}
config, err := os.ReadFile(".private")
if err != nil && !os.IsNotExist(err) {
log.Fatalf("failed: %v", err)
}
for _, line := range strings.Split(string(config), "\n") {
line = strings.Trim(line, " ")
if line != "" {
fname, _ := filepath.Abs(line)
_, err := os.Stat(fname)
if err == nil {
files = append(files, fname)
}
}
}
sort.Strings(files)
return files
}
func listTestsAndBinaries(rootDir string, buildFlags []string) (binaries, tests map[string]struct{}) {
cfg := &packages.Config{
Dir: rootDir,
Mode: packages.NeedName | packages.NeedFiles,
BuildFlags: buildFlags,
Tests: true,
}
pkgs, err := packages.Load(cfg, "./...")
if err != nil {
log.Fatalf("unable to load packages %s: %s", rootDir, err)
}
if packages.PrintErrors(pkgs) > 0 {
os.Exit(1)
}
tests = map[string]struct{}{}
binaries = map[string]struct{}{}
for _, p := range pkgs {
if p.Name != "main" {
continue
}
if strings.HasSuffix(p.PkgPath, ".test") {
tests[strings.TrimSuffix(p.PkgPath, ".test")] = struct{}{}
} else {
binaries[p.PkgPath] = struct{}{}
}
}
return
}