diff --git a/internal/api/runner/judge.go b/internal/api/runner/judge.go index 09242e4..113c5a5 100644 --- a/internal/api/runner/judge.go +++ b/internal/api/runner/judge.go @@ -29,10 +29,10 @@ func (h *handler) Judge(_ context.Context, t *asynq.Task) error { // 1. write user code userCode := filepath.Join(runner.UserDir, user, fmt.Sprintf("%s.%s", user, p.Submission.Language)) - if !file.FileTouch(userCode) { + if !file.Touch(userCode) { return e.InternalError, 0, systemError } - err := file.FileWrite(userCode, []byte(p.Submission.Code)) + err := file.Write(userCode, []byte(p.Submission.Code)) if err != nil { return e.InternalError, 0, systemError } diff --git a/internal/misc/config/conf.go b/internal/misc/config/conf.go index ca3adf2..d47e0e8 100644 --- a/internal/misc/config/conf.go +++ b/internal/misc/config/conf.go @@ -19,7 +19,7 @@ type Service interface { func NewService(i *do.Injector) (Service, error) { cliCtx := do.MustInvoke[*cli.Context](i) - data, err := file.FileRead(cliCtx.String("config")) + data, err := file.Read(cliCtx.String("config")) if err != nil { log.Printf("Failed to setup config: %s\n", err.Error()) return nil, err diff --git a/internal/service/runner/common.go b/internal/service/runner/common.go index e1aa973..378186f 100644 --- a/internal/service/runner/common.go +++ b/internal/service/runner/common.go @@ -57,10 +57,10 @@ func (s *service) checkAndExecute(version uint, user string, lang string, script func (s *service) ProblemExists(version uint) bool { problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version)) - return file.FileExist(problemPath) + return file.Exist(problemPath) } func (s *service) userExists(user string, name string) bool { userPath := filepath.Join(UserDir, user, name) - return file.FileExist(userPath) + return file.Exist(userPath) } diff --git a/internal/service/runner/compile.go b/internal/service/runner/compile.go index ce2699b..6b794d1 100644 --- a/internal/service/runner/compile.go +++ b/internal/service/runner/compile.go @@ -20,7 +20,7 @@ func (s *service) Compile(version uint, user string, lang string) (JudgeStatus, msg = utils.If(err == nil, msg, nil) msgText := string(msg) - if !file.FileExist(target) || file.FileEmpty(target) { + if !file.Exist(targetFile) || file.Empty(targetFile) { return JudgeStatus{ Message: "compile failed", Tasks: []TaskStatus{{Verdict: VerdictCompileError, Message: msgText}}}, diff --git a/internal/service/runner/deps.go b/internal/service/runner/deps.go index d798b4c..1c3b88e 100644 --- a/internal/service/runner/deps.go +++ b/internal/service/runner/deps.go @@ -21,7 +21,7 @@ func (s *service) loadImage(cfg *depConfig) e.Status { err := utils.NewTryErr(). Try(func() error { // import from tarball - if !file.FileExist(cfg.tarball) { + if !file.Exist(cfg.tarball) { return errors.New("tarball not exists") } return s.execute("bash", "-c", fmt.Sprintf("gzip -d -c %s | podman load", cfg.tarball)) @@ -32,7 +32,7 @@ func (s *service) loadImage(cfg *depConfig) e.Status { }). Or(func() error { // build from dockerfile - if !file.FileExist(cfg.dockerfile) { + if !file.Exist(cfg.dockerfile) { return errors.New("dockerfile not exists") } return s.execute("podman", "build", "-f", cfg.dockerfile, "-t", cfg.image, ".") @@ -53,7 +53,7 @@ func (s *service) EnsureDeps(force bool) e.Status { // check mark if force { _ = os.Remove(mark) - } else if file.FileExist(mark) { + } else if file.Exist(mark) { return e.Success } diff --git a/internal/service/runner/new_problem.go b/internal/service/runner/new_problem.go index ec8b3de..c93a43b 100644 --- a/internal/service/runner/new_problem.go +++ b/internal/service/runner/new_problem.go @@ -39,22 +39,22 @@ func (s *service) prebuild(version uint, force bool) e.Status { mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), ".mark.prebuild") if force { _ = os.Remove(mark) - } else if file.FileExist(mark) { + } else if file.Exist(mark) { return e.Success } prebuildScript := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "judge", "prebuild.Makefile") - if !file.FileExist(prebuildScript) { + if !file.Exist(prebuildScript) { s.log.Info("prebuild script not found", zap.String("path", prebuildScript), zap.Uint("version", version)) return e.Success } - dataPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "data") - judgePath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "judge") + dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "data") + judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "judge") args := []string{ - "-v", dataPath + ":/woj/problem/data", - "-v", judgePath + ":/woj/problem/judge", + "-v", dataDir + ":/woj/problem/data", + "-v", judgeDir + ":/woj/problem/judge", "-e", "PREFIX=/woj/problem", "git.0x7f.app/woj/ubuntu-full:latest", "sh", "-c", "cd /woj/problem/judge && make -f prebuild.Makefile prebuild && touch .mark.prebuild", diff --git a/internal/service/runner/status.go b/internal/service/runner/status.go index c751792..95ddfd8 100644 --- a/internal/service/runner/status.go +++ b/internal/service/runner/status.go @@ -57,7 +57,7 @@ func (t *TaskStatus) getInfoText(infoFile string) *TaskStatus { } var err error - t.infoText, err = file.FileRead(infoFile) + t.infoText, err = file.Read(infoFile) if err != nil { t.Verdict = VerdictSystemError t.Message = "cannot read info file" @@ -128,7 +128,7 @@ func (t *TaskStatus) getJudgeText(judgeFile string) *TaskStatus { return t } - j, err := file.FileRead(judgeFile) + j, err := file.Read(judgeFile) if err != nil { t.Verdict = VerdictSystemError t.Message = "cannot read judge file" diff --git a/pkg/file/file.go b/pkg/file/file.go index d0ad4a6..9c34dab 100644 --- a/pkg/file/file.go +++ b/pkg/file/file.go @@ -7,7 +7,7 @@ import ( "path/filepath" ) -func FileRead(filePath string) ([]byte, error) { +func Read(filePath string) ([]byte, error) { f, err := os.Open(filePath) if err != nil { return nil, err @@ -15,16 +15,16 @@ func FileRead(filePath string) ([]byte, error) { return io.ReadAll(f) } -func FileWrite(filePath string, content []byte) error { +func Write(filePath string, content []byte) error { return os.WriteFile(filePath, content, 0644) } -func FileExist(filePath string) bool { +func Exist(filePath string) bool { _, err := os.Stat(filePath) return utils.If(err == nil || os.IsExist(err), true, false) } -func FileEmpty(filePath string) bool { +func Empty(filePath string) bool { stat, err := os.Stat(filePath) if err != nil { return true @@ -32,9 +32,14 @@ func FileEmpty(filePath string) bool { return stat.Size() == 0 } -func FileTouch(filePath string) bool { +func Touch(filePath string) bool { + err := TouchErr(filePath) + return utils.If(err == nil, true, false) +} + +func TouchErr(filePath string) error { base := filepath.Dir(filePath) _ = os.MkdirAll(base, 0755) _, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644) - return utils.If(err == nil, true, false) + return err } diff --git a/pkg/utils/must.go b/pkg/utils/must.go new file mode 100644 index 0000000..75b24e3 --- /dev/null +++ b/pkg/utils/must.go @@ -0,0 +1,20 @@ +package utils + +type MustChain struct { + err error +} + +func NewMust() *MustChain { + return &MustChain{} +} + +func (c *MustChain) Do(callback func() error) *MustChain { + if c.err == nil { + c.err = callback() + } + return c +} + +func (c *MustChain) Done() error { + return c.err +}