small pixel drawing of a pufferfish zoa

dramatically simplify everything
Jes Olson j3s@c3f.net
Wed, 28 Sep 2022 02:08:52 -0500
commit

ec8f4922f3ad36b746812997267e0e1b0392aade

parent

f6c23fdd44aafb8e0e3183194922d8274a147a5d

M main.gomain.go

@@ -6,15 +6,9 @@ "log"

"os" "path/filepath" - "j3s.sh/zoa/env" "j3s.sh/zoa/git" "j3s.sh/zoa/shell" - - "mvdan.cc/sh/v3/interp" -) - -const ( - zoaRoot = "/var/lib/zoa" + "j3s.sh/zoa/utils" ) func main() {

@@ -35,33 +29,25 @@ path := os.Args[1]

gitMode := git.GitMode(path) if gitMode { - err := os.MkdirAll(zoaRoot, 0755) + utils.SetZoaRoot("/var/lib/zoa") + err := os.MkdirAll(utils.ZoaRoot, 0755) if err != nil { log.Fatal(err) } // check the path & branch, make sure it's correct // then clone git.Clone(path, branch) - entryPointDir = filepath.Join(zoaRoot, "repo") + entryPointDir = filepath.Join(utils.ZoaRoot, "repo") } else { - entryPointDir = path + utils.SetZoaRoot(path) + entryPointDir = utils.ZoaRoot } // TODO: this writer is responsible for the random stdout // maybe save the stdout for debug mode somehow - r, err := interp.New(interp.StdIO(nil, os.Stdout, os.Stderr)) - if err != nil { - log.Fatal(err) - } - // set standard env vars for runtime - r.Env, err = env.GenerateEnv() - if err != nil { - log.Fatal(err) - } - // for debuggin' fmt.Printf("%+v", r.Env) - - shell.RunCommands(entryPointDir, "main", r) + main := filepath.Join(entryPointDir, "main") + shell.RunScript(main) } func printUsage() {
M shell/shell.goshell/shell.go

@@ -1,7 +1,6 @@

package shell import ( - "bytes" "context" "fmt" "log"

@@ -9,6 +8,7 @@ "os"

"path/filepath" "strings" + "j3s.sh/zoa/env" "j3s.sh/zoa/utils" "mvdan.cc/sh/v3/interp"

@@ -18,82 +18,167 @@

// this is used to detect when the script // name changes from run to run, which allows // us to prettily-print -var lastScriptPath string -var ctx = context.Background() +// var lastScriptPath string + +var r *interp.Runner + +func init() { + var err error + envs, err := env.GenerateEnv() + if err != nil { + log.Fatal(err) + } -func RunCommands(zoaRoot string, scriptName string, r *interp.Runner) { - scriptPath := filepath.Join(zoaRoot, scriptName) - script, err := parseFile(scriptPath) + r, err = interp.New( + interp.StdIO(nil, os.Stdout, os.Stdout), + interp.CallHandler(CallHandler), + interp.Env(envs), + ) if err != nil { - fmt.Println("error in " + scriptPath) - fmt.Println(err) - os.Exit(1) + log.Fatal(err) } +} + +var last string - // execute every statement individually, decorating - // each with ->, and doing some speshul logicks against - // certain strings - for _, stmt := range script.Stmts { - fullCmd := commandName(stmt) - command, after, _ := strings.Cut(fullCmd, " ") +func CallHandler(ctx context.Context, args []string) ([]string, error) { + // hc := interp.HandlerCtx(ctx) - if command == "zoa-script" { - // recursion detected!!!!!! :3 :3 :3 - subScriptPath := filepath.Join("scripts/" + after) - RunCommands(zoaRoot, subScriptPath, r) - continue - } + if args[0] == "zoa-script" { + subScript := filepath.Join(utils.ZoaRoot, "scripts", args[1]) + // TODO: figure out how to get scripts to echo their names + // when we resume their execution + utils.BluePrintln("-> " + subScript) + runScriptInSubshell(ctx, subScript) - if command == "zoa-file" { - // after = "nginx /etc/nginx/conf.d/jesse.conf systemctl nginx reload" - zoaFileParts := strings.Split(after, " ") - if len(zoaFileParts) < 2 { - log.Fatal("zoa-file requires 2+ arguments") - } - src := zoaFileParts[0] - dst := zoaFileParts[1] - optionalCmd := "" - if len(zoaFileParts) > 2 { - optionalCmd = strings.Join(zoaFileParts[2:], " ") - } - fmt.Printf("$ zoa-file %s %s\n", src, dst) - filePath := filepath.Join(zoaRoot, "files", src) - dstChanged, err := zoaCopy(filePath, dst) - if err != nil { - log.Fatal(err) - } - // if there's an optional argument - if optionalCmd != "" && dstChanged { - re := strings.NewReader(optionalCmd) - f, err := syntax.NewParser().Parse(re, "") - if err != nil { - log.Fatal(err) - } + // args has to have something in it - true is a pretty safe bet + args = []string{"true", "true"} + } - for _, stmt := range f.Stmts { - runCommand(ctx, stmt, r) - } - } - continue + if args[0] == "zoa-file" { + // fmt.Fprintln(hc.Stdout, "") + // return nil + // args = "zoa-file nginx /etc/nginx/conf.d/jesse.conf systemctl nginx reload" + if len(args) <= 2 { + log.Fatal("zoa-file requires 2+ arguments") } - - // if the script name changed between runs, - // print it - if scriptPath != lastScriptPath { - utils.BluePrintln("-> " + scriptPath) - lastScriptPath = scriptPath + src := args[1] + dst := args[2] + optionalCmd := []string{} + if len(args) >= 4 { + optionalCmd = args[3:] } - - fmt.Printf("$ %s\n", fullCmd) - // todo: better colorz idk utils.BluePrintln("$ " + cmdName) - err = r.Run(ctx, stmt) + fmt.Printf("$ zoa-file %s %s\n", src, dst) + filePath := filepath.Join(utils.ZoaRoot, "files", src) + dstChanged, err := zoaCopy(filePath, dst) if err != nil { - // ignore err here bc it's just the status code - os.Exit(1) + log.Fatal(err) } + if len(optionalCmd) >= 1 && dstChanged { + args = optionalCmd + } else { + args = []string{"true", "true"} + } + } + + // this should really just say "if zoa-file or zoa-script ran" + if len(args) == 2 && args[0] == "true" { + // no printy + } else { + fmt.Printf("$ %s\n", strings.Join(args, " ")) + } + + return args, nil + + // return interp.DefaultCallHandler(2*time.Second)(ctx, args) +} + +func runScriptInSubshell(ctx context.Context, script string) error { + r := r.Subshell() + f, err := parseFile(script) + if err != nil { + return err + } + r.Run(ctx, f) + return nil +} + +func RunScript(s string) { + script, err := parseFile(s) + if err != nil { + fmt.Printf("error in %s: %s\n", s, err) + os.Exit(1) + } + err = r.Run(context.TODO(), script) + if err != nil { + fmt.Println(err) + os.Exit(1) } } +// execute every statement individually, decorating +// each with ->, and doing some speshul logicks against +// certain strings +// for _, stmt := range script.Stmts { +// fullCmd := commandName(stmt) +// command, after, _ := strings.Cut(fullCmd, " ") + +// if command == "zoa-script" { +// // recursion detected!!!!!! :3 :3 :3 +// subScriptPath := filepath.Join("scripts/" + after) +// RunCommands(zoaRoot, subScriptPath, r) +// continue +// } + +// if command == "zoa-file" { +// // after = "nginx /etc/nginx/conf.d/jesse.conf systemctl nginx reload" +// zoaFileParts := strings.Split(after, " ") +// if len(zoaFileParts) < 2 { +// log.Fatal("zoa-file requires 2+ arguments") +// } +// src := zoaFileParts[0] +// dst := zoaFileParts[1] +// optionalCmd := "" +// if len(zoaFileParts) > 2 { +// optionalCmd = strings.Join(zoaFileParts[2:], " ") +// } +// fmt.Printf("$ zoa-file %s %s\n", src, dst) +// filePath := filepath.Join(zoaRoot, "files", src) +// dstChanged, err := zoaCopy(filePath, dst) +// if err != nil { +// log.Fatal(err) +// } +// // if there's an optional argument +// if optionalCmd != "" && dstChanged { +// re := strings.NewReader(optionalCmd) +// f, err := syntax.NewParser().Parse(re, "") +// if err != nil { +// log.Fatal(err) +// } + +// for _, stmt := range f.Stmts { +// runCommand(ctx, stmt, r) +// } +// } +// continue +// } + +// if the script name changed between runs, +// print it +// if scriptPath != lastScriptPath { +// utils.BluePrintln("-> " + scriptPath) +// lastScriptPath = scriptPath +// } + +// fmt.Printf("$ %s\n", fullCmd) +// // todo: better colorz idk utils.BluePrintln("$ " + cmdName) +// err = r.Run(ctx, stmt) +// if err != nil { +// // ignore err here bc it's just the status code +// os.Exit(1) +// } +// } + func parseFile(filename string) (*syntax.File, error) { var result = &syntax.File{} f, err := os.Open(filename)

@@ -103,21 +188,6 @@ }

defer f.Close() result, err = syntax.NewParser().Parse(f, "") return result, err -} - -func runCommand(c context.Context, s *syntax.Stmt, r *interp.Runner) { - name := commandName(s) - fmt.Printf("$ %s\n", name) - err := r.Run(c, s) - if err != nil { - os.Exit(1) - } -} - -func commandName(statement *syntax.Stmt) string { - b := new(bytes.Buffer) - syntax.NewPrinter().Print(b, statement) - return b.String() } // zoaCopy copies a file from zoaRoot/scripts/src to dst.
M test/maintest/main

@@ -1,6 +1,6 @@

# test function inheretence println() { - printf "%s.\n" "$1" + printf "%s\n" "$1" } # hewo

@@ -24,6 +24,7 @@ # todo

zoa-script 2-call-me-from-anotha # . ./test/2-call-me-from-anotha +ls -lat echo i am main

@@ -43,6 +44,6 @@ zoa-file demo /tmp/zoa-file-test echo $PASSTHROUGH

ls /tmp/zoa-file-test # ensure that zoa-script works in an if statement -if true; then +if printf "%s\n" "testing if statement followed by custom helper"; then zoa-script another-thing fi
M test/scripts/2-call-me-from-anothatest/scripts/2-call-me-from-anotha

@@ -1,7 +1,7 @@

-echo "$PASSTHROUGH" - -uname -a +[ "$PASSTHROUGH" = "bananas" ] -ls -l +echo i am script 2 zoa-script 3-more + +echo i am script 2
A test/scripts/another-thing

@@ -0,0 +1,1 @@

+println "surprise, tests have completed successfully! :D"
M utils/utils.goutils/utils.go

@@ -7,6 +7,12 @@ "io"

"os" ) +var ZoaRoot string + +func SetZoaRoot(root string) { + ZoaRoot = root +} + // Copy just copiez files, it's only used by zoaCopy rn func Copy(src, dst string) error { in, err := os.Open(src)