129 lines
3.1 KiB
Go
129 lines
3.1 KiB
Go
package convert
|
|
|
|
import (
|
|
"fmt"
|
|
"go/build"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"regexp"
|
|
)
|
|
|
|
/*
|
|
* RewritePackage takes a name (eg: my-package/tools), finds its test files using
|
|
* Go's build package, and then rewrites them. A ginkgo test suite file will
|
|
* also be added for this package, and all of its child packages.
|
|
*/
|
|
func RewritePackage(packageName string) {
|
|
pkg, err := packageWithName(packageName)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("unexpected error reading package: '%s'\n%s\n", packageName, err.Error()))
|
|
}
|
|
|
|
for _, filename := range findTestsInPackage(pkg) {
|
|
rewriteTestsInFile(filename)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Given a package, findTestsInPackage reads the test files in the directory,
|
|
* and then recurses on each child package, returning a slice of all test files
|
|
* found in this process.
|
|
*/
|
|
func findTestsInPackage(pkg *build.Package) (testfiles []string) {
|
|
for _, file := range append(pkg.TestGoFiles, pkg.XTestGoFiles...) {
|
|
testfile, _ := filepath.Abs(filepath.Join(pkg.Dir, file))
|
|
testfiles = append(testfiles, testfile)
|
|
}
|
|
|
|
dirFiles, err := ioutil.ReadDir(pkg.Dir)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("unexpected error reading dir: '%s'\n%s\n", pkg.Dir, err.Error()))
|
|
}
|
|
|
|
re := regexp.MustCompile(`^[._]`)
|
|
|
|
for _, file := range dirFiles {
|
|
if !file.IsDir() {
|
|
continue
|
|
}
|
|
|
|
if re.Match([]byte(file.Name())) {
|
|
continue
|
|
}
|
|
|
|
packageName := filepath.Join(pkg.ImportPath, file.Name())
|
|
subPackage, err := packageWithName(packageName)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("unexpected error reading package: '%s'\n%s\n", packageName, err.Error()))
|
|
}
|
|
|
|
testfiles = append(testfiles, findTestsInPackage(subPackage)...)
|
|
}
|
|
|
|
addGinkgoSuiteForPackage(pkg)
|
|
goFmtPackage(pkg)
|
|
return
|
|
}
|
|
|
|
/*
|
|
* Shells out to `ginkgo bootstrap` to create a test suite file
|
|
*/
|
|
func addGinkgoSuiteForPackage(pkg *build.Package) {
|
|
originalDir, err := os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
suite_test_file := filepath.Join(pkg.Dir, pkg.Name+"_suite_test.go")
|
|
|
|
_, err = os.Stat(suite_test_file)
|
|
if err == nil {
|
|
return // test file already exists, this should be a no-op
|
|
}
|
|
|
|
err = os.Chdir(pkg.Dir)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
output, err := exec.Command("ginkgo", "bootstrap").Output()
|
|
|
|
if err != nil {
|
|
panic(fmt.Sprintf("error running 'ginkgo bootstrap'.\nstdout: %s\n%s\n", output, err.Error()))
|
|
}
|
|
|
|
err = os.Chdir(originalDir)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Shells out to `go fmt` to format the package
|
|
*/
|
|
func goFmtPackage(pkg *build.Package) {
|
|
path, _ := filepath.Abs(pkg.ImportPath)
|
|
output, err := exec.Command("go", "fmt", path).CombinedOutput()
|
|
|
|
if err != nil {
|
|
fmt.Printf("Warning: Error running 'go fmt %s'.\nstdout: %s\n%s\n", path, output, err.Error())
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Attempts to return a package with its test files already read.
|
|
* The ImportMode arg to build.Import lets you specify if you want go to read the
|
|
* buildable go files inside the package, but it fails if the package has no go files
|
|
*/
|
|
func packageWithName(name string) (pkg *build.Package, err error) {
|
|
pkg, err = build.Default.Import(name, ".", build.ImportMode(0))
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
pkg, err = build.Default.Import(name, ".", build.ImportMode(1))
|
|
return
|
|
}
|