Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 44 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,24 @@ func runTime(cmd *exec.Cmd) error {
}

func gorun(srcFilename string, env []string, buildDir string, runDir string, args ...string) error {
exeDir, err := os.MkdirTemp("", "goeval*")
if err != nil {
return err
}
defer func() {
if err := os.RemoveAll(exeDir); err != nil {
log.Printf("RemoveAll(%q): %v", exeDir, err)
exePath := buildOutput
if exePath == "" {

exeDir, err := os.MkdirTemp("", "goeval*")
if err != nil {
return err
}
}()

exePath := filepath.Join(exeDir, "goeval-run")
if runtime.GOOS == "windows" {
exePath += ".exe"
defer func() {
if err := os.RemoveAll(exeDir); err != nil {
log.Printf("RemoveAll(%q): %v", exeDir, err)
}
}()

exePath = filepath.Join(exeDir, "goeval-run")
if runtime.GOOS == "windows" {
exePath += ".exe"
}
}

cmdBuild := exec.Command(goCmd, "build",
Expand All @@ -171,6 +176,11 @@ func gorun(srcFilename string, env []string, buildDir string, runDir string, arg
return fmt.Errorf("failed to build: %w", err)
}

// actionBuild: don't run
if buildOutput != "" {
return nil
}

cmdRun := exec.Command(exePath, args...)
cmdRun.Env = env
cmdRun.Dir = runDir // In Go module mode we run from the temp module dir
Expand Down Expand Up @@ -212,6 +222,7 @@ type actionBits uint

const (
actionRun actionBits = iota
actionBuild // -o ...
actionDump // -E
actionDumpPlay // -Eplay
actionPlay // -play
Expand All @@ -220,15 +231,20 @@ const (
actionDefault = actionRun
)

var action actionBits
var (
action actionBits
buildOutput string // -o

errActionExclusive = errors.New("flags -o, -E, -Eplay, -play and -share are exclusive")
)

func flagAction(name string, a actionBits, target *string, usage string) {
flag.BoolFunc(name, usage, func(value string) error {
if target == nil && value != "true" {
return errors.New("no value expected")
}
if action != actionDefault {
return errors.New("flags -E, -Eplay, -play and -share are exclusive")
return errActionExclusive
}
action = a
return nil
Expand Down Expand Up @@ -256,6 +272,18 @@ func _main() error {

// TODO allow to optionally set a different endpoint for the Go Playground

flag.Func("o", "just build a binary, don't execute.", func(value string) (err error) {
if action != actionDefault {
return errActionExclusive
}
if value == "" {
return errors.New("invalid empty output file")
}
action = actionBuild
buildOutput, err = filepath.Abs(value)
return
})

showCmds := flag.Bool("x", false, "print commands executed.")

flag.Usage = func() {
Expand Down Expand Up @@ -294,7 +322,7 @@ func _main() error {
args := flag.Args()[1:]
if len(args) > 0 {
switch action {
case actionDump:
case actionBuild, actionDump:
return errors.New("arguments not expected")
}
}
Expand Down Expand Up @@ -445,7 +473,7 @@ func _main() error {
tail func() error
)
switch action {
case actionRun:
case actionRun, actionBuild:
f, err := os.CreateTemp(dir, "*.go")
if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -521,7 +549,7 @@ func _main() error {
*/

// dump go.mod, go.sum
if moduleMode && action != actionRun {
if moduleMode && action >= actionDump {
gomod, err := os.Open(dir + "/go.mod")
if err != nil {
log.Fatal(err)
Expand Down
29 changes: 29 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"bytes"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
)

Expand Down Expand Up @@ -126,3 +128,30 @@ func TestPrintStack(t *testing.T) {
// PrintStack sends output to stderr
goevalPrint(t.Log, t.Log, `-i=runtime/debug`, `-goimports=`, `debug.PrintStack()`)
}

// Test "goeval -o ..."
func TestBuild(t *testing.T) {
tempDir := t.TempDir()

exe := filepath.Join(tempDir, "x")
if runtime.GOOS == "windows" {
exe += ".exe"
}
t.Logf("Building %q...", exe)

goevalT(t, `-o`, exe, `fmt.Print(os.Args[1])`)

_, err := os.Stat(exe)
if err != nil {
t.Fatalf(`%q: %v`, exe, err)
}

cmd := exec.Command(exe, `toto`)
out, err := cmd.Output()
if err != nil {
t.Fatalf(`exec(%q): %v`, exe, err)
}
if string(out) != "toto" {
t.Errorf(`output: got %q, expected "toto"`, out)
}
}