@@ -311,33 +311,57 @@ func compileAndRun(req *request) (*response, error) {
311
311
}
312
312
defer os .RemoveAll (tmpDir )
313
313
314
- src := []byte (req .Body )
315
- in := filepath .Join (tmpDir , progName )
316
- if err := ioutil .WriteFile (in , src , 0400 ); err != nil {
317
- return nil , fmt .Errorf ("error creating temp file %q: %v" , in , err )
314
+ files , err := splitFiles ([]byte (req .Body ))
315
+ if err != nil {
316
+ return & response {Errors : err .Error ()}, nil
318
317
}
319
318
320
- fset := token .NewFileSet ()
319
+ var testParam string
320
+ var buildPkgArg = "."
321
+ if files .Num () == 1 && len (files .Data (progName )) > 0 {
322
+ buildPkgArg = progName
323
+ src := files .Data (progName )
324
+ if code := getTestProg (src ); code != nil {
325
+ testParam = "-test.v"
326
+ files .AddFile (progName , code )
327
+ }
328
+ }
321
329
322
- f , err := parser . ParseFile ( fset , in , nil , parser . PackageClauseOnly )
323
- if err == nil && f . Name . Name != "main" {
324
- return & response { Errors : "package name must be main" }, nil
330
+ useModules := allowModuleDownloads ( files )
331
+ if ! files . Contains ( "go.mod" ) && useModules {
332
+ files . AddFile ( "go.mod" , [] byte ( "module play \n " ))
325
333
}
326
334
327
- var testParam string
328
- if code := getTestProg (src ); code != nil {
329
- testParam = "-test.v"
330
- if err := ioutil .WriteFile (in , code , 0400 ); err != nil {
335
+ for f , src := range files .m {
336
+ // Before multi-file support we required that the
337
+ // program be in package main, so continue to do that
338
+ // for now. But permit anything in subdirectories to have other
339
+ // packages.
340
+ if ! strings .Contains (f , "/" ) {
341
+ fset := token .NewFileSet ()
342
+ f , err := parser .ParseFile (fset , f , src , parser .PackageClauseOnly )
343
+ if err == nil && f .Name .Name != "main" {
344
+ return & response {Errors : "package name must be main" }, nil
345
+ }
346
+ }
347
+
348
+ in := filepath .Join (tmpDir , f )
349
+ if strings .Contains (f , "/" ) {
350
+ if err := os .MkdirAll (filepath .Dir (in ), 0755 ); err != nil {
351
+ return nil , err
352
+ }
353
+ }
354
+ if err := ioutil .WriteFile (in , src , 0644 ); err != nil {
331
355
return nil , fmt .Errorf ("error creating temp file %q: %v" , in , err )
332
356
}
333
357
}
334
358
335
359
exe := filepath .Join (tmpDir , "a.out" )
336
360
goCache := filepath .Join (tmpDir , "gocache" )
337
- cmd := exec .Command ("go" , "build" , "-o" , exe , in )
361
+ cmd := exec .Command ("go" , "build" , "-o" , exe , buildPkgArg )
362
+ cmd .Dir = tmpDir
338
363
var goPath string
339
364
cmd .Env = []string {"GOOS=nacl" , "GOARCH=amd64p32" , "GOCACHE=" + goCache }
340
- useModules := allowModuleDownloads (src )
341
365
if useModules {
342
366
// Create a GOPATH just for modules to be downloaded
343
367
// into GOPATH/pkg/mod.
@@ -356,9 +380,8 @@ func compileAndRun(req *request) (*response, error) {
356
380
if _ , ok := err .(* exec.ExitError ); ok {
357
381
// Return compile errors to the user.
358
382
359
- // Rewrite compiler errors to refer to progName
360
- // instead of '/tmp/sandbox1234/prog.go'.
361
- errs := strings .Replace (string (out ), in , progName , - 1 )
383
+ // Rewrite compiler errors to strip the tmpDir name.
384
+ errs := strings .Replace (string (out ), tmpDir + "/" , "" , - 1 )
362
385
363
386
// "go build", invoked with a file name, puts this odd
364
387
// message before any compile errors; strip it.
@@ -422,8 +445,8 @@ func compileAndRun(req *request) (*response, error) {
422
445
423
446
// allowModuleDownloads reports whether the code snippet in src should be allowed
424
447
// to download modules.
425
- func allowModuleDownloads (src [] byte ) bool {
426
- if bytes .Contains (src , []byte (`"code.google.com/p/go-tour/` )) {
448
+ func allowModuleDownloads (files * fileSet ) bool {
449
+ if files . Num () == 1 && bytes .Contains (files . Data ( progName ) , []byte (`"code.google.com/p/go-tour/` )) {
427
450
// This domain doesn't exist anymore but we want old snippets using
428
451
// these packages to still run, so the Dockerfile adds these packages
429
452
// at this name in $GOPATH. Any snippets using this old name wouldn't
0 commit comments