package runner import ( "fmt" "git.0x7f.app/WOJ/woj-server/internal/e" "git.0x7f.app/WOJ/woj-server/pkg/down" "git.0x7f.app/WOJ/woj-server/pkg/file" "git.0x7f.app/WOJ/woj-server/pkg/unzip" "go.uber.org/zap" "os" "path/filepath" "time" ) func (s *service) download(version uint, url string) e.Status { zipPath := filepath.Join(TmpDir, fmt.Sprintf("%d.zip", version)) problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version)) err := down.Down(zipPath, url) if err != nil { s.log.Error("download problem failed", zap.Error(err)) return e.RunnerDownloadFailed } err = unzip.Unzip(zipPath, problemPath) if err != nil { s.log.Warn("unzip problem failed", zap.Error(err)) return e.RunnerUnzipFailed } return e.Success } func (s *service) prebuild(version uint, force bool) e.Status { if !s.ProblemExists(version) { return e.RunnerProblemNotExist } mark := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), ".mark.prebuild") if force { _ = os.Remove(mark) } else if file.Exist(mark) { return e.Success } prebuildScript := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "judge", "prebuild.Makefile") if !file.Exist(prebuildScript) { s.log.Info("prebuild script not found", zap.String("path", prebuildScript), zap.Uint("version", version)) return e.Success } dataDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "data") judgeDir := filepath.Join(ProblemDir, fmt.Sprintf("%d", version), "judge") args := []string{ "-v", fmt.Sprintf("%s:/woj/problem/data", dataDir), "-v", fmt.Sprintf("%s:/woj/problem/judge", judgeDir), "-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", } runArgs := &podmanArgs{ executeArgs: executeArgs{ args: args, timeout: 300 * time.Second, }, memory: "1g", } err := s.podmanRun(runArgs) if err != nil { s.log.Warn("prebuild problem failed", zap.Error(err), zap.Uint("version", version)) return e.RunnerProblemPrebuildFailed } return e.Success } func (s *service) NewProblem(version uint, url string, force bool) (Config, e.Status) { if force { problemPath := filepath.Join(ProblemDir, fmt.Sprintf("%d", version)) _ = os.RemoveAll(problemPath) } if !s.ProblemExists(version) { status := s.download(version, url) if status != e.Success { return Config{}, status } } cfg, err := s.ParseConfig(version, false) if err != nil { // TODO: err is dropped here, should return to server: add a new column in problem_version table return Config{}, e.RunnerProblemParseFailed } status := s.prebuild(version, true) if status != e.Success { return Config{}, status } return cfg, e.Success }