Compare commits

..

7 Commits

7 changed files with 271 additions and 15 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
go.*

30
goModClean.go Normal file
View File

@ -0,0 +1,30 @@
package fhelp
import (
"fmt"
"go.wit.com/log"
)
func CheckGoModClean() bool {
if checkCmdSimple("go-mod-clean") {
return true
}
goModCleanInstructions()
return false
}
func CheckGoModCleanExit() {
if CheckGoModClean() {
return
}
badExit(fmt.Errorf("missing go-mod-clean"))
}
func goModCleanInstructions() {
log.Info("you are missing 'go-mod-clean' which is required")
log.Info("")
log.Info("you can:")
log.Info(" go install go.wit.com/apps/utils/go-mod-clean # if you have go")
log.Info("")
}

85
goSrcFind.go Normal file
View File

@ -0,0 +1,85 @@
package fhelp
// returns whatever your golang source dir is
// If there is a go.work file in your parent, that directory will be returned
// otherwise, return ~/go/src
import (
"fmt"
"os"
"path/filepath"
"go.wit.com/log"
)
// look for a go.work file
// otherwise use ~/go/src
func findGoSrc() (string, error) {
pwd, err := os.Getwd()
// startpwd, _ := os.Getwd()
if err == nil {
// Check for go.work in the current directory and then move up until root
if pwd, err := digup(pwd); err == nil {
// found an existing go.work file
// os.Chdir(pwd)
return pwd, nil
} else {
// if there is an error looking for the go.work file
// default to using ~/go/src
// log.Info("forge.digup() err", pwd, err)
}
} else {
// this shouldn't really happen. maybe your working directory got deleted
log.Info("forge.findGoSrc() os.Getwd() was probably deleted", pwd, err)
}
// there are no go.work files, resume the ~/go/src behavior from prior to golang 1.22
pwd, err = useGoSrc()
return pwd, err
}
// this is the 'old way" and works fine for me. I use it because I like the ~/go/src directory
// because I know exactly what is in it: GO stuff & nothing else
func useGoSrc() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
pwd := filepath.Join(homeDir, "go/src")
err = os.MkdirAll(pwd, os.ModePerm)
return pwd, err
}
func goWorkExists(dir string) bool {
var err error
workFilePath := filepath.Join(dir, "go.work")
if _, err = os.Stat(workFilePath); err == nil {
// log.Info("f.goWorkExists() found", workFilePath)
return true
} else if !os.IsNotExist(err) {
// log.Info("f.goWorkExists() missing", workFilePath)
return false
}
// probably false, but some other error
// log.Info("f.goWorkExists() os.Stat() error", err, workFilePath)
return false
}
func digup(path string) (string, error) {
for {
workFilePath := filepath.Join(path, "go.work")
if _, err := os.Stat(workFilePath); err == nil {
return path, nil // Found the go.work file
} else if !os.IsNotExist(err) {
return "", err // An error other than not existing
}
parentPath := filepath.Dir(path)
if parentPath == path {
break // Reached the filesystem root
}
path = parentPath
}
return "", fmt.Errorf("no go.work file found")
}

34
goWork.go Normal file
View File

@ -0,0 +1,34 @@
package fhelp
import (
"os"
"go.wit.com/log"
)
/*
try to determine the GO working dir
this will look for a go.work file, otherwise
it will default to ~/go/src
returns:
string # ~/go/src or the path to the go.work file
bool # true if the user is using a go.work file
err # if everything goes wrong, the error
*/
func DetermineGoPath() (string, bool, error) {
gosrc := os.Getenv("FORGE_GOSRC")
if gosrc != "" {
hasWork := goWorkExists(gosrc)
log.Info("Using ENV{FORGE_GOSRC} =", gosrc)
return gosrc, hasWork, nil
}
gosrc, err := findGoSrc()
if err != nil {
log.Info("fhelp.DetermineGoPath()", err)
}
hasWork := goWorkExists(gosrc)
return gosrc, hasWork, err
}

View File

@ -4,19 +4,44 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"runtime"
"go.wit.com/log" "go.wit.com/log"
) )
func CheckProtoc() bool { func CheckProtoc() bool {
if checkCmdSimple("protoc") { if !checkCmdSimple("protoc") {
userInstructions() userInstructions()
log.Sleep(2) switch runtime.GOOS {
case "linux":
linuxInstall("protoc")
case "macos":
log.Info("todo: print instructions here for installing protoc on macos. brew install?")
case "windows":
log.Info("todo: print instructions here for installing protoc on windows")
default:
log.Info("todo: print instructions here for installing protoc on", runtime.GOOS)
}
return false return false
} }
if checkCmdSimple("protoc-gen-go") { if !checkCmdSimple("protoc") {
return false
}
if !checkCmdSimple("protoc-gen-go") {
userInstructions() userInstructions()
log.Sleep(2) switch runtime.GOOS {
case "linux":
linuxInstall("protoc-gen-go")
case "macos":
log.Info("todo: print instructions here for installing protoc on macos. brew install?")
case "windows":
log.Info("todo: print instructions here for installing protoc on windows")
default:
log.Info("todo: print instructions here for installing protoc on", runtime.GOOS)
}
}
if !checkCmdSimple("protoc-gen-go") {
return false return false
} }
return true return true
@ -33,7 +58,7 @@ func checkCmdSimple(cmd string) bool {
return true return true
} }
func checkCmd(cmd string) (string, error) { func CheckCmd(cmd string) (string, error) {
path, err := exec.LookPath(cmd) path, err := exec.LookPath(cmd)
if err != nil { if err != nil {
fmt.Printf("\n%s is not in the PATH\n", cmd) fmt.Printf("\n%s is not in the PATH\n", cmd)
@ -43,6 +68,8 @@ func checkCmd(cmd string) (string, error) {
return path, err return path, err
} }
/*
func oldcheckCmd(cmd string) { func oldcheckCmd(cmd string) {
// path, err := exec.LookPath(cmd) // path, err := exec.LookPath(cmd)
_, err := exec.LookPath(cmd) _, err := exec.LookPath(cmd)
@ -54,6 +81,7 @@ func oldcheckCmd(cmd string) {
// fmt.Printf("%s is available at %s\n", cmd, path) // fmt.Printf("%s is available at %s\n", cmd, path)
} }
} }
*/
// todo: figure out how to determine, in a package, what the program name is // todo: figure out how to determine, in a package, what the program name is
func okExit(s string) { func okExit(s string) {

34
linux.go Normal file
View File

@ -0,0 +1,34 @@
package fhelp
// auto run protoc with the correct args
import (
"bufio"
"fmt"
"os"
"strings"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func linuxInstall(pkg string) {
cmd := []string{"apt", "install", "-y", pkg}
if pkg == "protoc" {
cmd = []string{"apt", "install", "-y", "protobuf-compiler"}
}
log.Info("Would you like to run", "sudo", cmd, "now?")
fmt.Fprintf(os.Stdout, "(y)es or (n)o ? ")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
line = strings.TrimSpace(line)
line = strings.ToLower(line)
switch line {
case "y":
shell.Sudo(cmd)
default:
}
}
}

View File

@ -54,34 +54,71 @@ func ValidProtobuf(filename string) (string, string, error) {
scanner.Scan() scanner.Scan()
line = scanner.Text() line = scanner.Text()
fields := strings.Fields(line) fields := strings.Fields(line)
if len(fields) < 2 {
noUuidExit(filename)
return "", "", fmt.Errorf("proto file does not have a UUID")
}
// log.Info("GOT LINE", line) // log.Info("GOT LINE", line)
if fields[0] == "string" && fields[1] != "uuid" { if fields[0] == "string" && fields[1] != "uuid" {
noUuid(filename) noUuidExit(filename)
return "", "", fmt.Errorf("proto file does not have a UUID") return "", "", fmt.Errorf("proto file does not have a UUID")
} }
// ok, uuid is here // ok, uuid is here
UUID := line UUID := parseUuid(line)
log.Info("found UUID:", line) if UUID == "" {
noUuidExit(filename)
return "", "", fmt.Errorf("proto file does not have a UUID")
}
log.Info("found UUID:", UUID)
scanner.Scan() scanner.Scan()
line = scanner.Text() line = scanner.Text()
fields = strings.Fields(line) fields = strings.Fields(line)
// log.Info("GOT LINE", line) // log.Info("GOT LINE", line)
if fields[0] == "string" && fields[1] != "version" { if fields[0] == "string" && fields[1] != "version" {
noUuid(filename) noUuidExit(filename)
return "", "", fmt.Errorf("proto file does not have a version") return "", "", fmt.Errorf("proto file does not have a version")
} }
// found "version", the .proto file conforms // found "version", the .proto file conforms
version := line version := parseVersion(line)
log.Info("found Version:", line) if version == "" {
noUuidExit(filename)
return "", "", fmt.Errorf("proto file does not have a version")
}
log.Info("found Version:", version)
return UUID, version, nil return UUID, version, nil
} }
// right now, noPluralMessage does os.Exit(-1) // right now, noPluralMessage does os.Exit(-1)
// return "", "", noPluralMessage(filename) noPluralMessageExit(filename)
return "", "", fmt.Errorf("proto file does not have message %s", pluralBase) return "", "", fmt.Errorf("proto file does not have message %s", pluralBase)
} }
func noPluralMessage(filename string) { func parseUuid(line string) string {
fields := strings.Split(line, "autogenpb:uuid:")
if len(fields) < 2 {
return ""
}
end := fields[1]
fields = strings.Fields(end)
uuid := fields[0]
uuid = strings.Trim(uuid, "`")
// log.Info("fhelp.parseUuid() uuid =", uuid)
return uuid
}
func parseVersion(line string) string {
fields := strings.Split(line, "autogenpb:version:")
if len(fields) < 2 {
return ""
}
end := fields[1]
fields = strings.Fields(end)
ver := fields[0]
ver = strings.Trim(ver, "`")
// log.Info("fhelp.parseVersion() ver =", ver)
return ver
}
func noPluralMessageExit(filename string) {
filebase := strings.TrimSuffix(filename, ".proto") filebase := strings.TrimSuffix(filename, ".proto")
base := cases.Title(language.English, cases.NoLower).String(filebase) base := cases.Title(language.English, cases.NoLower).String(filebase)
@ -106,7 +143,7 @@ func noPluralMessage(filename string) {
// repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s" // repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s"
// } // }
func noUuid(filename string) { func noUuidExit(filename string) {
filebase := strings.TrimSuffix(filename, ".proto") filebase := strings.TrimSuffix(filename, ".proto")
base := cases.Title(language.English, cases.NoLower).String(filebase) base := cases.Title(language.English, cases.NoLower).String(filebase)
id := uuid.New() id := uuid.New()
@ -125,7 +162,14 @@ func noUuid(filename string) {
log.Info("") log.Info("")
log.Info("If you don't have a UUID, you can use the randomly generated one here") log.Info("If you don't have a UUID, you can use the randomly generated one here")
log.Info("") log.Info("")
log.Info("If you wish to ignore this, set PROTOBUF_REGRET=true")
log.Info("You will probably regret not trying to follow the standard here. This format is used as a 'handshake'.")
log.Info("###########################################################################") log.Info("###########################################################################")
if os.Getenv("PROTOBUF_REGRET") == "true" {
log.Info("PROTOBUF_REGRET=true was set")
log.Info("###########################################################################")
return
}
badExit(fmt.Errorf("proto file error %s", filename)) badExit(fmt.Errorf("proto file error %s", filename))
} }