@@ -29,12 +29,12 @@ import (
29
29
"os/exec"
30
30
"path/filepath"
31
31
"runtime"
32
- "strconv"
33
32
"strings"
34
33
"time"
35
34
"unicode/utf8"
36
35
37
36
"golang.org/x/net/websocket"
37
+ "golang.org/x/tools/txtar"
38
38
)
39
39
40
40
// RunScripts specifies whether the socket handler should execute shell scripts
@@ -162,7 +162,7 @@ type process struct {
162
162
out chan <- * Message
163
163
done chan struct {} // closed when wait completes
164
164
run * exec.Cmd
165
- bin string
165
+ path string
166
166
}
167
167
168
168
// startProcess builds and runs the given program, sending its output
@@ -203,8 +203,8 @@ func startProcess(id, body string, dest chan<- *Message, opt *Options) *process
203
203
// end sends an "end" message to the client, containing the process id and the
204
204
// given error value. It also removes the binary, if present.
205
205
func (p * process ) end (err error ) {
206
- if p .bin != "" {
207
- defer os .Remove (p .bin )
206
+ if p .path != "" {
207
+ defer os .RemoveAll (p .path )
208
208
}
209
209
m := & Message {Kind : "end" }
210
210
if err != nil {
@@ -355,22 +355,37 @@ func (p *process) start(body string, opt *Options) error {
355
355
// (rather than the go tool process).
356
356
// This makes Kill work.
357
357
358
- bin := filepath .Join (tmpdir , "compile" + strconv .Itoa (<- uniq ))
359
- src := bin + ".go"
358
+ path , err := ioutil .TempDir ("" , "present-" )
359
+ if err != nil {
360
+ return err
361
+ }
362
+ defer os .RemoveAll (path )
363
+
364
+ out := "prog"
360
365
if runtime .GOOS == "windows" {
361
- bin + = ".exe"
366
+ out = "prog .exe"
362
367
}
368
+ bin := filepath .Join (path , out )
363
369
364
- // write body to x.go
365
- defer os .Remove (src )
366
- err := ioutil .WriteFile (src , []byte (body ), 0666 )
367
- if err != nil {
368
- return err
370
+ // write body to x.go files
371
+ a := txtar .Parse ([]byte (body ))
372
+ if len (a .Comment ) != 0 {
373
+ a .Files = append (a .Files , txtar.File {Name : "prog.go" , Data : a .Comment })
374
+ a .Comment = nil
375
+ }
376
+ hasModfile := false
377
+ for _ , f := range a .Files {
378
+ err = ioutil .WriteFile (filepath .Join (path , f .Name ), f .Data , 0666 )
379
+ if err != nil {
380
+ return err
381
+ }
382
+ if f .Name == "go.mod" {
383
+ hasModfile = true
384
+ }
369
385
}
370
386
371
387
// build x.go, creating x
372
- p .bin = bin // to be removed by p.end
373
- dir , file := filepath .Split (src )
388
+ p .path = path // to be removed by p.end
374
389
args := []string {"go" , "build" , "-tags" , "OMIT" }
375
390
if opt != nil && opt .Race {
376
391
p .out <- & Message {
@@ -379,8 +394,11 @@ func (p *process) start(body string, opt *Options) error {
379
394
}
380
395
args = append (args , "-race" )
381
396
}
382
- args = append (args , "-o" , bin , file )
383
- cmd := p .cmd (dir , args ... )
397
+ args = append (args , "-o" , bin )
398
+ cmd := p .cmd (path , args ... )
399
+ if ! hasModfile {
400
+ cmd .Env = append (cmd .Env , "GO111MODULE=off" )
401
+ }
384
402
cmd .Stdout = cmd .Stderr // send compiler output to stderr
385
403
if err := cmd .Run (); err != nil {
386
404
return err
@@ -501,24 +519,3 @@ func safeString(b []byte) string {
501
519
}
502
520
return buf .String ()
503
521
}
504
-
505
- var tmpdir string
506
-
507
- func init () {
508
- // find real path to temporary directory
509
- var err error
510
- tmpdir , err = filepath .EvalSymlinks (os .TempDir ())
511
- if err != nil {
512
- log .Fatal (err )
513
- }
514
- }
515
-
516
- var uniq = make (chan int ) // a source of numbers for naming temporary files
517
-
518
- func init () {
519
- go func () {
520
- for i := 0 ; ; i ++ {
521
- uniq <- i
522
- }
523
- }()
524
- }
0 commit comments