diff --git a/go.work b/go.work index 63100b9f6..6c9ffbf68 100644 --- a/go.work +++ b/go.work @@ -1,17 +1,18 @@ -go 1.19 +go 1.21.5 use ( . ./test/typecheck ./tools/changelog + ./tools/component + ./tools/data-conversion + ./tools/formitychecker //./tools/imctl ./tools/infra ./tools/ncpu ./tools/openim-web + ./tools/up35 + ./tools/url2im ./tools/versionchecker ./tools/yamlfmt - ./tools/component - ./tools/url2im - ./tools/data-conversion - ./tools/up35 ) diff --git a/tools/formitychecker/checker/checker.go b/tools/formitychecker/checker/checker.go new file mode 100644 index 000000000..187b509bc --- /dev/null +++ b/tools/formitychecker/checker/checker.go @@ -0,0 +1,97 @@ +package checker + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/openimsdk/open-im-server/tools/formitychecker/config" +) + +var ( + underscoreRegex = regexp.MustCompile(`^[a-zA-Z0-9_]+\.[a-zA-Z0-9]+$`) + hyphenRegex = regexp.MustCompile(`^[a-zA-Z0-9\-]+\.[a-zA-Z0-9]+$`) +) + +// CheckDirectoCheckDirectoryries initiates the checking process for the specified directories using configuration from config.Config. +func CheckDirectory(cfg *config.Config) error { + ignoreMap := make(map[string]struct{}) + for _, dir := range cfg.IgnoreDirs { + ignoreMap[dir] = struct{}{} + } + + for _, targetDir := range cfg.TargetDirs { + err := filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Skip if the directory is in the ignore list + dirName := filepath.Base(filepath.Dir(path)) + if _, ok := ignoreMap[dirName]; ok && info.IsDir() { + return filepath.SkipDir + } + + // Check the naming convention + if err := checkNamingConvention(path, info); err != nil { + fmt.Println(err) + } + + return nil + }) + + if err != nil { + return fmt.Errorf("error checking directory '%s': %w", targetDir, err) + } + } + + return nil +} + +// checkNamingConvention checks if the file or directory name conforms to the standard naming conventions. +func checkNamingConvention(path string, info os.FileInfo) error { + fileName := info.Name() + + // Handle special cases for directories like .git + if info.IsDir() && strings.HasPrefix(fileName, ".") { + return nil // Skip special directories + } + + // Extract the main part of the name (without extension for files) + mainName := fileName + if !info.IsDir() { + mainName = strings.TrimSuffix(fileName, filepath.Ext(fileName)) + } + + // Determine the type of file and apply corresponding naming rule + switch { + case info.IsDir(): + if !isValidName(mainName, "_") { // Directory names must only contain underscores + return fmt.Errorf("!!! invalid directory name: %s", path) + } + case strings.HasSuffix(fileName, ".go"): + if !isValidName(mainName, "_") { // Go files must only contain underscores + return fmt.Errorf("!!! invalid Go file name: %s", path) + } + case strings.HasSuffix(fileName, ".yml"), strings.HasSuffix(fileName, ".yaml"), strings.HasSuffix(fileName, ".md"): + if !isValidName(mainName, "-") { // YML, YAML, and Markdown files must only contain hyphens + return fmt.Errorf("!!! invalid file name: %s", path) + } + } + + return nil +} + +// isValidName checks if the file name conforms to the specified rule (underscore or hyphen). +func isValidName(name, charType string) bool { + switch charType { + case "_": + return underscoreRegex.MatchString(name) + case "-": + return hyphenRegex.MatchString(name) + default: + return false + } +} diff --git a/tools/formitychecker/config/config.go b/tools/formitychecker/config/config.go new file mode 100644 index 000000000..95bcee346 --- /dev/null +++ b/tools/formitychecker/config/config.go @@ -0,0 +1,27 @@ +package config + +import ( + "strings" +) + +// Config holds all the configuration parameters for the checker. +type Config struct { + TargetDirs []string // Directories to check + IgnoreDirs []string // Directories to ignore +} + +// NewConfig creates and returns a new Config instance. +func NewConfig(targetDirs, ignoreDirs string) *Config { + return &Config{ + TargetDirs: parseDirs(targetDirs), + IgnoreDirs: parseDirs(ignoreDirs), + } +} + +// parseDirs splits a comma-separated string into a slice of directory names. +func parseDirs(dirs string) []string { + if dirs == "" { + return nil + } + return strings.Split(dirs, ",") +} diff --git a/tools/formitychecker/formitychecker.go b/tools/formitychecker/formitychecker.go new file mode 100644 index 000000000..d078009b6 --- /dev/null +++ b/tools/formitychecker/formitychecker.go @@ -0,0 +1,27 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/openimsdk/open-im-server/tools/formitychecker/checker" + "github.com/openimsdk/open-im-server/tools/formitychecker/config" +) + +func main() { + defaultTargetDirs := "." + defaultIgnoreDirs := "components,.git" + + var targetDirs string + var ignoreDirs string + flag.StringVar(&targetDirs, "target", defaultTargetDirs, "Directories to check (default: current directory)") + flag.StringVar(&ignoreDirs, "ignore", defaultIgnoreDirs, "Directories to ignore (default: A/, B/)") + flag.Parse() + + conf := config.NewConfig(targetDirs, ignoreDirs) + + err := checker.CheckDirectory(conf) + if err != nil { + fmt.Println("Error:", err) + } +} diff --git a/tools/formitychecker/go.mod b/tools/formitychecker/go.mod new file mode 100644 index 000000000..756318c14 --- /dev/null +++ b/tools/formitychecker/go.mod @@ -0,0 +1,3 @@ +module github.com/openimsdk/open-im-server/tools/formitychecker + +go 1.21.5