diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-04-10 16:44:02 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-10 16:44:02 +0800 |
commit | 4e3348135723dfc03dcc91b196b5da6f20b8a4ea (patch) | |
tree | 8734e1d537d93243dd6ba478b9f2890cc8ac0d89 /modules/repository/init.go | |
parent | bb6c670cff1a081d9f5f8bdb3dc91abe5d9e35b9 (diff) | |
download | gitea-4e3348135723dfc03dcc91b196b5da6f20b8a4ea.tar.gz gitea-4e3348135723dfc03dcc91b196b5da6f20b8a4ea.zip |
Make label templates have consistent behavior and priority (#23749)
Fix https://github.com/go-gitea/gitea/issues/23715
Other related PRs:
* #23717
* #23716
* #23719
This PR is different from others, it tries to resolve the problem fundamentally (and brings more benefits)
Although it looks like some more lines are added, actually many new lines are for tests.
----
Before, the code was just "guessing" the file type and try to parse them.
<details>
![image](https://user-images.githubusercontent.com/2114189/228002245-57d58e27-1078-4da9-bf42-5bc0b264c6ce.png)
</details>
This PR:
* Always remember the original option file names, and always use correct parser for them.
* Another benefit is that we can sort the Label Templates now (before there was a map, its key order is undefined)
![image](https://user-images.githubusercontent.com/2114189/228002432-931b9f18-3908-484b-a36b-04760c9ad132.png)
Diffstat (limited to 'modules/repository/init.go')
-rw-r--r-- | modules/repository/init.go | 117 |
1 files changed, 69 insertions, 48 deletions
diff --git a/modules/repository/init.go b/modules/repository/init.go index f9a33cd4f6..38dd8a0c4f 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "os" - "path" "path/filepath" "sort" "strings" @@ -27,6 +26,11 @@ import ( asymkey_service "code.gitea.io/gitea/services/asymkey" ) +type OptionFile struct { + DisplayName string + Description string +} + var ( // Gitignores contains the gitiginore files Gitignores []string @@ -37,65 +41,73 @@ var ( // Readmes contains the readme files Readmes []string - // LabelTemplates contains the label template files and the list of labels for each file - LabelTemplates map[string]string + // LabelTemplateFiles contains the label template files, each item has its DisplayName and Description + LabelTemplateFiles []OptionFile + labelTemplateFileMap = map[string]string{} // DisplayName => FileName mapping ) +type optionFileList struct { + all []string // all files provided by bindata & custom-path. Sorted. + custom []string // custom files provided by custom-path. Non-sorted, internal use only. +} + +// mergeCustomLabelFiles merges the custom label files. Always use the file's main name (DisplayName) as the key to de-duplicate. +func mergeCustomLabelFiles(fl optionFileList) []string { + exts := map[string]int{"": 0, ".yml": 1, ".yaml": 2} // "yaml" file has the highest priority to be used. + + m := map[string]string{} + merge := func(list []string) { + sort.Slice(list, func(i, j int) bool { return exts[filepath.Ext(list[i])] < exts[filepath.Ext(list[j])] }) + for _, f := range list { + m[strings.TrimSuffix(f, filepath.Ext(f))] = f + } + } + merge(fl.all) + merge(fl.custom) + + files := make([]string, 0, len(m)) + for _, f := range m { + files = append(files, f) + } + sort.Strings(files) + return files +} + // LoadRepoConfig loads the repository config -func LoadRepoConfig() { - // Load .gitignore and license files and readme templates. - types := []string{"gitignore", "license", "readme", "label"} - typeFiles := make([][]string, 4) +func LoadRepoConfig() error { + types := []string{"gitignore", "license", "readme", "label"} // option file directories + typeFiles := make([]optionFileList, len(types)) for i, t := range types { - files, err := options.Dir(t) - if err != nil { - log.Fatal("Failed to get %s files: %v", t, err) + var err error + if typeFiles[i].all, err = options.Dir(t); err != nil { + return fmt.Errorf("failed to list %s files: %w", t, err) } - if t == "label" { - for i, f := range files { - ext := strings.ToLower(filepath.Ext(f)) - if ext == ".yaml" || ext == ".yml" { - files[i] = f[:len(f)-len(ext)] - } + sort.Strings(typeFiles[i].all) + customPath := filepath.Join(setting.CustomPath, "options", t) + if isDir, err := util.IsDir(customPath); err != nil { + return fmt.Errorf("failed to check custom %s dir: %w", t, err) + } else if isDir { + if typeFiles[i].custom, err = util.StatDir(customPath); err != nil { + return fmt.Errorf("failed to list custom %s files: %w", t, err) } } - customPath := path.Join(setting.CustomPath, "options", t) - isDir, err := util.IsDir(customPath) - if err != nil { - log.Fatal("Failed to get custom %s files: %v", t, err) - } - if isDir { - customFiles, err := util.StatDir(customPath) - if err != nil { - log.Fatal("Failed to get custom %s files: %v", t, err) - } - - for _, f := range customFiles { - if !util.SliceContainsString(files, f, true) { - files = append(files, f) - } - } - } - typeFiles[i] = files } - Gitignores = typeFiles[0] - Licenses = typeFiles[1] - Readmes = typeFiles[2] - LabelTemplatesFiles := typeFiles[3] - sort.Strings(Gitignores) - sort.Strings(Licenses) - sort.Strings(Readmes) - sort.Strings(LabelTemplatesFiles) + Gitignores = typeFiles[0].all + Licenses = typeFiles[1].all + Readmes = typeFiles[2].all // Load label templates - LabelTemplates = make(map[string]string) - for _, templateFile := range LabelTemplatesFiles { - labels, err := label.LoadFormatted(templateFile) + LabelTemplateFiles = nil + labelTemplateFileMap = map[string]string{} + for _, file := range mergeCustomLabelFiles(typeFiles[3]) { + description, err := label.LoadTemplateDescription(file) if err != nil { - log.Error("Failed to load labels: %v", err) + return fmt.Errorf("failed to load labels: %w", err) } - LabelTemplates[templateFile] = labels + displayName := strings.TrimSuffix(file, filepath.Ext(file)) + labelTemplateFileMap[displayName] = file + LabelTemplateFiles = append(LabelTemplateFiles, OptionFile{DisplayName: displayName, Description: description}) } // Filter out invalid names and promote preferred licenses. @@ -111,6 +123,7 @@ func LoadRepoConfig() { } } Licenses = sortedLicenses + return nil } func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts CreateRepoOptions) error { @@ -344,7 +357,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re // InitializeLabels adds a label set to a repository using a template func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg bool) error { - list, err := label.GetTemplateFile(labelTemplate) + list, err := LoadTemplateLabelsByDisplayName(labelTemplate) if err != nil { return err } @@ -370,3 +383,11 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg } return nil } + +// LoadTemplateLabelsByDisplayName loads a label template by its display name +func LoadTemplateLabelsByDisplayName(displayName string) ([]*label.Label, error) { + if fileName, ok := labelTemplateFileMap[displayName]; ok { + return label.LoadTemplateFile(fileName) + } + return nil, label.ErrTemplateLoad{TemplateFile: displayName, OriginalError: fmt.Errorf("label template %q not found", displayName)} +} |