mirror of
https://github.com/neilotoole/sq.git
synced 2024-12-18 21:52:28 +03:00
425702e7ba
* linting * yet more linting * yet more linting * yet more linting * yet more linting * yet more linting
208 lines
4.2 KiB
Go
208 lines
4.2 KiB
Go
// Package proj contains test utilities for dealing with project
|
|
// paths and the like. The sq project dir is accessed via the
|
|
// Dir function. When proj's init function returns, certain envars
|
|
// such as SQ_ROOT are guaranteed to be set. Thus the following
|
|
// will work as expected:
|
|
//
|
|
// p := proj.Expand("${SQ_ROOT}/go.mod")
|
|
package proj
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/stringz"
|
|
)
|
|
|
|
const (
|
|
// EnvRoot is the name of the envar holding the path of
|
|
// the sq project root.
|
|
EnvRoot = "SQ_ROOT"
|
|
|
|
// EnvPassw is the name of the envar holding the standard
|
|
// password used for testing.
|
|
EnvPassw = "SQ_PASSW"
|
|
|
|
// DefaultPassw is the default password used for testing.
|
|
DefaultPassw = "p_ssW0rd"
|
|
|
|
EnvLogFile = "SQ_LOGFILE"
|
|
)
|
|
|
|
var projDir string
|
|
|
|
func init() { //nolint:gochecknoinits
|
|
envar, ok := os.LookupEnv(EnvPassw)
|
|
if !ok || envar == "" {
|
|
err := os.Setenv(EnvPassw, DefaultPassw)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
var path string
|
|
envar, ok = os.LookupEnv(EnvRoot)
|
|
if !ok || envar == "" {
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
for {
|
|
if isProjDir(dir) {
|
|
path = dir
|
|
break
|
|
}
|
|
|
|
if os.IsPathSeparator(dir[len(dir)-1]) {
|
|
// per filepath.Dir contract, we're at the root
|
|
break
|
|
}
|
|
|
|
dir = filepath.Dir(dir)
|
|
}
|
|
|
|
if path == "" {
|
|
panic("unable to determine sq project dir")
|
|
}
|
|
|
|
// If we get here, we've found the proj dir.
|
|
|
|
// Set the env so that os.ExpandEnv etc can use the envar
|
|
err = os.Setenv(EnvRoot, path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
var err error
|
|
path, err = filepath.Abs(envar)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if !isProjDir(path) {
|
|
panic("envar " + EnvRoot + " does not appear to be sq project dir: " + envar)
|
|
}
|
|
}
|
|
|
|
projDir = path
|
|
}
|
|
|
|
// isProjDir returns true if dir contains a go.mod file
|
|
// containing sq's module declaration. Any io error panics.
|
|
func isProjDir(dir string) bool {
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var gotMatch bool
|
|
for _, fi := range files {
|
|
if fi.Name() == "go.mod" {
|
|
gotMatch = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !gotMatch {
|
|
return false
|
|
}
|
|
|
|
f, err := os.Open(filepath.Join(dir, "go.mod"))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
gotMatch = false // reuse var
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
if scanner.Text() == `module github.com/neilotoole/sq` {
|
|
gotMatch = true
|
|
break
|
|
}
|
|
}
|
|
|
|
err = f.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return gotMatch
|
|
}
|
|
|
|
// Dir returns the absolute path to the root of the sq project,
|
|
// as set in envar EnvRoot or determined programmatically.
|
|
func Dir() string {
|
|
return projDir
|
|
}
|
|
|
|
// Rel returns the relative path from the current
|
|
// working dir to path, where path is relative to the project dir.
|
|
// This is useful for accessing common test fixtures across
|
|
// packages.
|
|
func Rel(path string) string {
|
|
abs := filepath.Join(Dir(), path)
|
|
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
relPath, err := filepath.Rel(cwd, abs)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return relPath
|
|
}
|
|
|
|
// Abs returns the absolute path of projRelPath,
|
|
// where projRelPath is relative to the project dir.
|
|
func Abs(projRelPath string) string {
|
|
return filepath.Join(Dir(), projRelPath)
|
|
}
|
|
|
|
// ReadFile is a convenience function for reading
|
|
// a file under the proj dir. It's equivalent to
|
|
// os.ReadFile(proj.Abs(path)) but panics on any error.
|
|
func ReadFile(projRelPath string) []byte {
|
|
p := Abs(projRelPath)
|
|
d, err := os.ReadFile(p)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return d
|
|
}
|
|
|
|
// Expand wraps os.ExpandEnv. This function is preferred
|
|
// as it ensures that envar SQ_ROOT is set (via
|
|
// proj's init function).
|
|
func Expand(s string) string {
|
|
return os.ExpandEnv(s)
|
|
}
|
|
|
|
// Passw returns the password used for testing.
|
|
func Passw() string {
|
|
return os.Getenv(EnvPassw)
|
|
}
|
|
|
|
// LogFile returns the path to sq's log file, as
|
|
// specified by EnvLogFile. If none set, the empty
|
|
// string is returned.
|
|
func LogFile() string {
|
|
return os.Getenv(EnvLogFile)
|
|
}
|
|
|
|
// BoolEnvar returns true if the environment variable e is set
|
|
// and its value is boolean true.
|
|
func BoolEnvar(envar string) bool {
|
|
s, ok := os.LookupEnv(envar)
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
b, _ := stringz.ParseBool(strings.TrimSpace(s))
|
|
return b
|
|
}
|