This commit brings support of whitelisted characters during repo healthcheck/non-ascii file check. Supported by an extra switch to `repo-health-checker`, `-whitelistedChars`. The argument takes a comma-separated list of non-ASCII characters and ignores them during repo healthcheck. Illegal cmdline input is logged by the logger. Co-Authored-By: GitHub Copilot <noreply@microsoft.com> <details> <summary>Copilot Prompt</summary> <br> This is a repo for an online judge orchestrator system «JOJ3». Under `cmd/` lies a source directory for a Go command, `repo-health-checker`. You tell from its name that it checks the repo for stuff like repo size, commit message, non-ASCII character usage, etc. before sending the work to the actual judging and grading system. Now, I want the non-ASCII character checking function of the repo health checker to be flexible - it shall accept a list of non-ASCII characters and deem them acceptable. ## Your task - Accept this new cmdline arg. In `cmd/repo-health-checker/main.go`, accept a new command line flag `-whitelisted-chars`, which shall take exactly one string of comma-separated non-ASCII characters. This string shall be passed to the actual healthcheck package. - Respect this list while scanning the files. In `pkg/healthcheck/nonascii.go`, function `getNonASCII()`, we utilize a bufio *Scanner* to scan through all files for non-ASCII characters. We would like the list of acceptable chars to be passed from the cmdline to here, and modify the scanner logic to actually accept the corresponding characters. - Error handling and reporting. This command line arg, `-whitelisted-chars`, could be completely abscent; in which case, no characters shall be escaped by default. The comma-separated list passed to the command may contain ASCII characters or multiple characters that are not properly separated; in which case, ignore that element, and report the incident via the SLog logging framework used in this project. - Test your work. Create new testcases under `examples/healthcheck/` to reflect this change. Reflect to `examples/healthcheck/asciifile/` to learn about how to configure the repo health checker. Integrate your work to the Go test framework such that it could be invoked by running `make test` at the terminal. - Note: Use `git init` to init your testcase directory and make a initial commit - this project, JOJ3, only runs in Git repos. ## Notes - Directory structure. `cmd/` for invokable commands, `pkg/` for the actual logic, `internal` - something you don't need to worry about. - JOJ3 vs. Health Check. `joj3` is a separate executable; in this session we are only working on the `repo-health-checker`. - Extras. Make sure to read `README.md` and the directory structure before you go; also, create To-do before you execute your plan. </details> Reviewed-on: https://focs.ji.sjtu.edu.cn/git/JOJ/JOJ3/pulls/100 Reviewed-by: 张泊明518370910136 <bomingzh@sjtu.edu.cn> Co-authored-by: Mack Wang <mac-wang@sjtu.edu.cn> Co-committed-by: Mack Wang <mac-wang@sjtu.edu.cn>
99 lines
2.9 KiB
Go
99 lines
2.9 KiB
Go
// Package main provides a repo-health-checker executable that checks the
|
|
// health of a repository. Its output should be parsed by the healthcheck
|
|
// parser.
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
|
|
"github.com/joint-online-judge/JOJ3/pkg/healthcheck"
|
|
)
|
|
|
|
// parseMultiValueFlag parses a multi-value command-line flag and appends its values to the provided slice.
|
|
// It registers a flag with the specified name and description, associating it with a multiStringValue receiver.
|
|
func parseMultiValueFlag(values *[]string, flagName, description string) {
|
|
flag.Var((*multiStringValue)(values), flagName, description)
|
|
}
|
|
|
|
type multiStringValue []string
|
|
|
|
// Set appends a new value to the multiStringValue slice.
|
|
// It satisfies the flag.Value interface, allowing multiStringValue to be used as a flag value.
|
|
func (m *multiStringValue) Set(value string) error {
|
|
*m = append(*m, value)
|
|
return nil
|
|
}
|
|
|
|
func (m *multiStringValue) String() string {
|
|
return fmt.Sprintf("%v", *m)
|
|
}
|
|
|
|
func setupSlog() {
|
|
opts := &slog.HandlerOptions{}
|
|
handler := slog.NewTextHandler(os.Stderr, opts)
|
|
logger := slog.New(handler)
|
|
slog.SetDefault(logger)
|
|
}
|
|
|
|
var (
|
|
rootDir string
|
|
repoSize float64
|
|
checkFileNameList string
|
|
checkFileSumList string
|
|
metaFile []string
|
|
whitelistedChars string
|
|
allowedDomainList string
|
|
actorCsvPath string
|
|
showVersion *bool
|
|
Version string
|
|
)
|
|
|
|
func init() {
|
|
showVersion = flag.Bool("version", false, "print current version")
|
|
flag.StringVar(&rootDir, "root", ".", "root dir for forbidden files check")
|
|
flag.Float64Var(&repoSize, "repoSize", 2, "maximum size of the repo in MiB")
|
|
flag.StringVar(&checkFileNameList, "checkFileNameList", "", "comma-separated list of files to check")
|
|
flag.StringVar(&checkFileSumList, "checkFileSumList", "", "comma-separated list of expected checksums")
|
|
flag.StringVar(&whitelistedChars, "whitelistedChars", "", "comma-separated list of non-ASCII characters allowed in files")
|
|
flag.StringVar(&allowedDomainList, "allowedDomainList", "sjtu.edu.cn", "comma-separated list of allowed domains for commit author email")
|
|
flag.StringVar(&actorCsvPath, "actorCsvPath", "/home/tt/.config/joj/students.csv", "path to actor csv file")
|
|
parseMultiValueFlag(&metaFile, "meta", "meta files to check")
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
if *showVersion {
|
|
fmt.Println(Version)
|
|
return
|
|
}
|
|
setupSlog()
|
|
slog.Info("start repo-health-checker", "version", Version)
|
|
slog.Debug("cli args",
|
|
"repoSize", repoSize,
|
|
"checkFileNameList", checkFileNameList,
|
|
"checkFileSumList", checkFileSumList,
|
|
"whitelistedChars", whitelistedChars,
|
|
"meta", metaFile,
|
|
)
|
|
res := healthcheck.All(
|
|
rootDir,
|
|
checkFileNameList,
|
|
checkFileSumList,
|
|
whitelistedChars,
|
|
allowedDomainList,
|
|
actorCsvPath,
|
|
metaFile,
|
|
repoSize,
|
|
)
|
|
jsonRes, err := json.Marshal(res)
|
|
if err != nil {
|
|
slog.Error("marshal result", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println(string(jsonRes))
|
|
}
|