Build & Run
This commit is contained in:
parent
efe527c1fd
commit
a5b2ecb5a5
1
main.go
1
main.go
|
@ -40,6 +40,7 @@ func main() {
|
||||||
|
|
||||||
http.HandleFunc("/", indexHandler)
|
http.HandleFunc("/", indexHandler)
|
||||||
|
|
||||||
|
http.HandleFunc("/build", output.BuildHandler)
|
||||||
http.HandleFunc("/run", output.RunHandler)
|
http.HandleFunc("/run", output.RunHandler)
|
||||||
http.HandleFunc("/output/ws", output.WSHandler)
|
http.HandleFunc("/output/ws", output.WSHandler)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var outputWS = map[string]*websocket.Conn{}
|
var outputWS = map[string]*websocket.Conn{}
|
||||||
|
@ -41,31 +43,11 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := args["file"].(string)
|
filePath := args["executable"].(string)
|
||||||
|
curDir := filePath[:strings.LastIndex(filePath, string(os.PathSeparator))]
|
||||||
|
|
||||||
fout, err := os.Create(filePath)
|
cmd := exec.Command(filePath)
|
||||||
|
cmd.Dir = curDir
|
||||||
if nil != err {
|
|
||||||
glog.Error(err)
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
code := args["code"].(string)
|
|
||||||
|
|
||||||
fout.WriteString(code)
|
|
||||||
|
|
||||||
if err := fout.Close(); nil != err {
|
|
||||||
glog.Error(err)
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
argv := []string{"run", filePath}
|
|
||||||
|
|
||||||
cmd := exec.Command("go", argv...)
|
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -119,3 +101,104 @@ func RunHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write(ret)
|
w.Write(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := session.Store.Get(r, "wide-session")
|
||||||
|
sid := session.Values["id"].(string)
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
|
||||||
|
var args map[string]interface{}
|
||||||
|
|
||||||
|
if err := decoder.Decode(&args); err != nil {
|
||||||
|
glog.Error(err)
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := args["file"].(string)
|
||||||
|
curDir := filePath[:strings.LastIndex(filePath, string(os.PathSeparator))]
|
||||||
|
|
||||||
|
fout, err := os.Create(filePath)
|
||||||
|
|
||||||
|
if nil != err {
|
||||||
|
glog.Error(err)
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
code := args["code"].(string)
|
||||||
|
|
||||||
|
fout.WriteString(code)
|
||||||
|
|
||||||
|
if err := fout.Close(); nil != err {
|
||||||
|
glog.Error(err)
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
suffix := ""
|
||||||
|
if "windows" == runtime.GOOS {
|
||||||
|
suffix = ".exe"
|
||||||
|
}
|
||||||
|
executable := "main" + suffix
|
||||||
|
argv := []string{"build", "-o", executable, filePath}
|
||||||
|
|
||||||
|
cmd := exec.Command("go", argv...)
|
||||||
|
cmd.Dir = curDir
|
||||||
|
|
||||||
|
glog.Info("go build ", filePath)
|
||||||
|
|
||||||
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
if nil != err {
|
||||||
|
glog.Error(err)
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stderr, err := cmd.StderrPipe()
|
||||||
|
if nil != err {
|
||||||
|
glog.Error(err)
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := io.MultiReader(stdout, stderr)
|
||||||
|
|
||||||
|
cmd.Start()
|
||||||
|
|
||||||
|
go func(runningId int) {
|
||||||
|
glog.Infof("Session [%s] is building [id=%d, file=%s]", sid, runningId, filePath)
|
||||||
|
|
||||||
|
// 一次性读取
|
||||||
|
buf := make([]byte, 1024*8)
|
||||||
|
count, _ := reader.Read(buf)
|
||||||
|
|
||||||
|
channelRet := map[string]interface{}{}
|
||||||
|
|
||||||
|
channelRet["output"] = string(buf[:count])
|
||||||
|
channelRet["cmd"] = "build"
|
||||||
|
channelRet["nextCmd"] = "run"
|
||||||
|
channelRet["executable"] = curDir + string(os.PathSeparator) + executable
|
||||||
|
|
||||||
|
if nil != outputWS[sid] {
|
||||||
|
glog.Infof("Session [%s] 's build [id=%d, file=%s] has done", sid, runningId, filePath)
|
||||||
|
|
||||||
|
err := outputWS[sid].WriteJSON(&channelRet)
|
||||||
|
if nil != err {
|
||||||
|
glog.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}(rand.Int())
|
||||||
|
|
||||||
|
ret, _ := json.Marshal(map[string]interface{}{"succ": true})
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write(ret)
|
||||||
|
}
|
||||||
|
|
|
@ -74,5 +74,5 @@ ul {
|
||||||
}
|
}
|
||||||
|
|
||||||
.shellOutput {
|
.shellOutput {
|
||||||
height: 125px;
|
height: 80px;
|
||||||
}
|
}
|
|
@ -5,9 +5,30 @@ outputWS.onopen = function() {
|
||||||
outputWS.onmessage = function(e) {
|
outputWS.onmessage = function(e) {
|
||||||
console.log('[output onmessage]' + e.data);
|
console.log('[output onmessage]' + e.data);
|
||||||
var data = JSON.parse(e.data);
|
var data = JSON.parse(e.data);
|
||||||
|
|
||||||
if ('init-output' !== data.cmd) {
|
if ('init-output' !== data.cmd) {
|
||||||
$('#output').val($('#output').val() + data.output);
|
$('#output').val($('#output').val() + data.output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('build' == data.cmd) {
|
||||||
|
if ('run' === data.nextCmd) {
|
||||||
|
var request = {
|
||||||
|
"executable": data.executable
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/run',
|
||||||
|
data: JSON.stringify(request),
|
||||||
|
dataType: "json",
|
||||||
|
beforeSend: function(data) {
|
||||||
|
$('#output').val('');
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
outputWS.onclose = function(e) {
|
outputWS.onclose = function(e) {
|
||||||
console.log('[output onclose] disconnected (' + e.code + ')');
|
console.log('[output onclose] disconnected (' + e.code + ')');
|
||||||
|
@ -80,16 +101,21 @@ var wide = {
|
||||||
"file": wide.curNode.path,
|
"file": wide.curNode.path,
|
||||||
"code": wide.curEditor.getValue()
|
"code": wide.curEditor.getValue()
|
||||||
};
|
};
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/run',
|
url: '/build',
|
||||||
data: JSON.stringify(request),
|
data: JSON.stringify(request),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
beforeSend: function(data) {
|
beforeSend: function(data) {
|
||||||
$('#output').val('');
|
$('#output').val('');
|
||||||
},
|
},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
console.log(data);
|
executable = data.executable;
|
||||||
|
|
||||||
|
if (data.succ) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<div>
|
<div>
|
||||||
<button id="saveBtn" onclick="wide.save()">Save</button>
|
<button id="saveBtn" onclick="wide.save()">Save</button>
|
||||||
<button id="fmtBtn" onclick="wide.fmt()">Format</button>
|
<button id="fmtBtn" onclick="wide.fmt()">Format</button>
|
||||||
<button id="runBtn" onclick="wide.run()">Run</button>
|
<button id="runBtn" onclick="wide.run()">Build & Run</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
Loading…
Reference in New Issue