forked from u-root/u-root
/
run.go
96 lines (84 loc) · 2.13 KB
/
run.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2012-2017 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Run executes its arguments as a Go program.
//
// Synopsis:
// run [-v] GO_CODE..
//
// Examples:
// run {fmt.Println("hello")}
//
// Options:
// -v: verbose display of processing
package main
import (
"flag"
"log"
"os"
"os/exec"
"golang.org/x/tools/imports"
)
var verbose = flag.Bool("v", false, "Verbose display of processing")
func main() {
opts := imports.Options{
Fragment: true,
AllErrors: true,
Comments: true,
TabIndent: true,
TabWidth: 8,
}
flag.Parse()
// Interesting problem:
// We want a combination of args and arbitrary Go code.
// Possibly, we should take the entire Go code as the one arg,
// i.e. in a 'string', and then take the args following.
a := "func main()"
for _, v := range flag.Args() {
a = a + v
}
if *verbose {
log.Printf("Pre-import version: '%v'", a)
}
goCode, err := imports.Process("commandline", []byte(a), &opts)
if err != nil {
log.Fatalf("bad parse: '%v': %v", a, err)
}
if *verbose {
log.Printf("Post-import version: '%v'", string(goCode))
}
// of course we have to deal with the Unix issue that /tmp is not private.
f, err := TempFile("", "run%s.go")
if err != nil {
log.Fatalf("Script: opening TempFile: %v", err)
}
if _, err := f.Write([]byte(goCode)); err != nil {
log.Fatalf("Script: Writing %v: %v", f, err)
}
if err := f.Close(); err != nil {
log.Fatalf("Script: Closing %v: %v", f, err)
}
os.Setenv("GOBIN", "/tmp")
cmd := exec.Command("go", "install", "-x", f.Name())
cmd.Dir = "/"
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
log.Printf("Install %v", f.Name())
if err = cmd.Run(); err != nil {
log.Printf("%v\n", err)
}
// stupid, but hey ...
execName := f.Name()
// strip .go from the name.
execName = execName[:len(execName)-3]
cmd = exec.Command(execName)
cmd.Dir = "/tmp"
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
log.Printf("Run %v", f.Name())
if err := cmd.Run(); err != nil {
log.Printf("%v\n", err)
}
}