181 lines
4.6 KiB
Go
181 lines
4.6 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
|
"github.com/criyle/go-judge/pb"
|
|
)
|
|
|
|
// copied from https://github.com/criyle/go-judge/blob/master/cmd/go-judge-shell/grpc.go
|
|
func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType {
|
|
var ret []*pb.Request_CmdType
|
|
for _, c := range cmd {
|
|
ret = append(ret, &pb.Request_CmdType{
|
|
Args: c.Args,
|
|
Env: c.Env,
|
|
Tty: c.TTY,
|
|
Files: convertPBFiles(c.Files),
|
|
CpuTimeLimit: c.CPULimit,
|
|
ClockTimeLimit: c.ClockLimit,
|
|
MemoryLimit: c.MemoryLimit,
|
|
StackLimit: c.StackLimit,
|
|
ProcLimit: c.ProcLimit,
|
|
CpuRateLimit: c.CPURateLimit,
|
|
CpuSetLimit: c.CPUSetLimit,
|
|
DataSegmentLimit: c.DataSegmentLimit,
|
|
AddressSpaceLimit: c.AddressSpaceLimit,
|
|
CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInCwd),
|
|
CopyOut: convertPBCopyOut(c.CopyOut),
|
|
CopyOutCached: convertPBCopyOut(c.CopyOutCached),
|
|
CopyOutMax: c.CopyOutMax,
|
|
CopyOutDir: c.CopyOutDir,
|
|
Symlinks: convertSymlink(c.CopyIn),
|
|
})
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func convertPBCopyIn(copyIn map[string]stage.CmdFile, copyInCwd bool) map[string]*pb.Request_File {
|
|
if copyInCwd {
|
|
_ = filepath.Walk(".",
|
|
func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
absPath, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if !info.IsDir() {
|
|
copyIn[path] = stage.CmdFile{Src: &absPath}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
rt := make(map[string]*pb.Request_File, len(copyIn))
|
|
for k, i := range copyIn {
|
|
if i.Symlink != nil {
|
|
continue
|
|
}
|
|
rt[k] = convertPBFile(i)
|
|
}
|
|
return rt
|
|
}
|
|
|
|
func convertPBCopyOut(copyOut []string) []*pb.Request_CmdCopyOutFile {
|
|
rt := make([]*pb.Request_CmdCopyOutFile, 0, len(copyOut))
|
|
for _, n := range copyOut {
|
|
optional := false
|
|
if strings.HasSuffix(n, "?") {
|
|
optional = true
|
|
n = strings.TrimSuffix(n, "?")
|
|
}
|
|
rt = append(rt, &pb.Request_CmdCopyOutFile{
|
|
Name: n,
|
|
Optional: optional,
|
|
})
|
|
}
|
|
return rt
|
|
}
|
|
|
|
func convertSymlink(copyIn map[string]stage.CmdFile) map[string]string {
|
|
ret := make(map[string]string)
|
|
for k, v := range copyIn {
|
|
if v.Symlink == nil {
|
|
continue
|
|
}
|
|
ret[k] = *v.Symlink
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func convertPBFiles(files []*stage.CmdFile) []*pb.Request_File {
|
|
var ret []*pb.Request_File
|
|
for _, f := range files {
|
|
if f == nil {
|
|
ret = append(ret, nil)
|
|
} else {
|
|
ret = append(ret, convertPBFile(*f))
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func convertPBFile(i stage.CmdFile) *pb.Request_File {
|
|
switch {
|
|
case i.Src != nil:
|
|
if !filepath.IsAbs(*i.Src) {
|
|
absPath, err := filepath.Abs(*i.Src)
|
|
if err == nil {
|
|
i.Src = &absPath
|
|
}
|
|
}
|
|
return &pb.Request_File{File: &pb.Request_File_Local{Local: &pb.Request_LocalFile{Src: *i.Src}}}
|
|
case i.Content != nil:
|
|
s := strToBytes(*i.Content)
|
|
return &pb.Request_File{File: &pb.Request_File_Memory{Memory: &pb.Request_MemoryFile{Content: s}}}
|
|
case i.FileID != nil:
|
|
return &pb.Request_File{File: &pb.Request_File_Cached{Cached: &pb.Request_CachedFile{FileID: *i.FileID}}}
|
|
case i.Name != nil && i.Max != nil:
|
|
return &pb.Request_File{File: &pb.Request_File_Pipe{Pipe: &pb.Request_PipeCollector{Name: *i.Name, Max: *i.Max, Pipe: i.Pipe}}}
|
|
case i.StreamIn:
|
|
return &pb.Request_File{File: &pb.Request_File_StreamIn{}}
|
|
case i.StreamOut:
|
|
return &pb.Request_File{File: &pb.Request_File_StreamOut{}}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func convertAbsPath(cmdFile *stage.CmdFile) error {
|
|
if cmdFile.Src != nil && !filepath.IsAbs(*cmdFile.Src) {
|
|
absPath, err := filepath.Abs(*cmdFile.Src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmdFile.Src = &absPath
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func convertPBResult(res []*pb.Response_Result) []stage.ExecutorResult {
|
|
var ret []stage.ExecutorResult
|
|
for _, r := range res {
|
|
ret = append(ret, stage.ExecutorResult{
|
|
Status: stage.Status(r.Status),
|
|
ExitStatus: int(r.ExitStatus),
|
|
Error: r.Error,
|
|
Time: r.Time,
|
|
RunTime: r.RunTime,
|
|
Memory: r.Memory,
|
|
Files: convertFiles(r.Files),
|
|
Buffs: r.Files,
|
|
FileIDs: r.FileIDs,
|
|
FileError: convertPBFileError(r.FileError),
|
|
})
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func convertFiles(buf map[string][]byte) map[string]string {
|
|
ret := make(map[string]string, len(buf))
|
|
for k, v := range buf {
|
|
ret[k] = byteArrayToString(v)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func convertPBFileError(fe []*pb.Response_FileError) []stage.FileError {
|
|
var ret []stage.FileError
|
|
for _, v := range fe {
|
|
ret = append(ret, stage.FileError{
|
|
Name: v.Name,
|
|
Type: stage.FileErrorType(v.Type),
|
|
Message: v.Message,
|
|
})
|
|
}
|
|
return ret
|
|
}
|