88 "context"
99 "fmt"
1010 "os"
11- "path"
1211 "path/filepath"
1312 "sort"
1413 "strings"
@@ -27,6 +26,11 @@ import (
2726 asymkey_service "code.gitea.io/gitea/services/asymkey"
2827)
2928
29+ type OptionFile struct {
30+ DisplayName string
31+ Description string
32+ }
33+
3034var (
3135 // Gitignores contains the gitiginore files
3236 Gitignores []string
@@ -37,65 +41,73 @@ var (
3741 // Readmes contains the readme files
3842 Readmes []string
3943
40- // LabelTemplates contains the label template files and the list of labels for each file
41- LabelTemplates map [string ]string
44+ // LabelTemplateFiles contains the label template files, each item has its DisplayName and Description
45+ LabelTemplateFiles []OptionFile
46+ labelTemplateFileMap = map [string ]string {} // DisplayName => FileName mapping
4247)
4348
49+ type optionFileList struct {
50+ all []string // all files provided by bindata & custom-path. Sorted.
51+ custom []string // custom files provided by custom-path. Non-sorted, internal use only.
52+ }
53+
54+ // mergeCustomLabelFiles merges the custom label files. Always use the file's main name (DisplayName) as the key to de-duplicate.
55+ func mergeCustomLabelFiles (fl optionFileList ) []string {
56+ exts := map [string ]int {"" : 0 , ".yml" : 1 , ".yaml" : 2 } // "yaml" file has the highest priority to be used.
57+
58+ m := map [string ]string {}
59+ merge := func (list []string ) {
60+ sort .Slice (list , func (i , j int ) bool { return exts [filepath .Ext (list [i ])] < exts [filepath .Ext (list [j ])] })
61+ for _ , f := range list {
62+ m [strings .TrimSuffix (f , filepath .Ext (f ))] = f
63+ }
64+ }
65+ merge (fl .all )
66+ merge (fl .custom )
67+
68+ files := make ([]string , 0 , len (m ))
69+ for _ , f := range m {
70+ files = append (files , f )
71+ }
72+ sort .Strings (files )
73+ return files
74+ }
75+
4476// LoadRepoConfig loads the repository config
45- func LoadRepoConfig () {
46- // Load .gitignore and license files and readme templates.
47- types := []string {"gitignore" , "license" , "readme" , "label" }
48- typeFiles := make ([][]string , 4 )
77+ func LoadRepoConfig () error {
78+ types := []string {"gitignore" , "license" , "readme" , "label" } // option file directories
79+ typeFiles := make ([]optionFileList , len (types ))
4980 for i , t := range types {
50- files , err := options . Dir ( t )
51- if err != nil {
52- log . Fatal ( "Failed to get %s files: %v " , t , err )
81+ var err error
82+ if typeFiles [ i ]. all , err = options . Dir ( t ); err != nil {
83+ return fmt . Errorf ( "failed to list %s files: %w " , t , err )
5384 }
54- if t == "label" {
55- for i , f := range files {
56- ext := strings .ToLower (filepath .Ext (f ))
57- if ext == ".yaml" || ext == ".yml" {
58- files [i ] = f [:len (f )- len (ext )]
59- }
85+ sort .Strings (typeFiles [i ].all )
86+ customPath := filepath .Join (setting .CustomPath , "options" , t )
87+ if isDir , err := util .IsDir (customPath ); err != nil {
88+ return fmt .Errorf ("failed to check custom %s dir: %w" , t , err )
89+ } else if isDir {
90+ if typeFiles [i ].custom , err = util .StatDir (customPath ); err != nil {
91+ return fmt .Errorf ("failed to list custom %s files: %w" , t , err )
6092 }
6193 }
62- customPath := path .Join (setting .CustomPath , "options" , t )
63- isDir , err := util .IsDir (customPath )
64- if err != nil {
65- log .Fatal ("Failed to get custom %s files: %v" , t , err )
66- }
67- if isDir {
68- customFiles , err := util .StatDir (customPath )
69- if err != nil {
70- log .Fatal ("Failed to get custom %s files: %v" , t , err )
71- }
72-
73- for _ , f := range customFiles {
74- if ! util .SliceContainsString (files , f , true ) {
75- files = append (files , f )
76- }
77- }
78- }
79- typeFiles [i ] = files
8094 }
8195
82- Gitignores = typeFiles [0 ]
83- Licenses = typeFiles [1 ]
84- Readmes = typeFiles [2 ]
85- LabelTemplatesFiles := typeFiles [3 ]
86- sort .Strings (Gitignores )
87- sort .Strings (Licenses )
88- sort .Strings (Readmes )
89- sort .Strings (LabelTemplatesFiles )
96+ Gitignores = typeFiles [0 ].all
97+ Licenses = typeFiles [1 ].all
98+ Readmes = typeFiles [2 ].all
9099
91100 // Load label templates
92- LabelTemplates = make (map [string ]string )
93- for _ , templateFile := range LabelTemplatesFiles {
94- labels , err := label .LoadFormatted (templateFile )
101+ LabelTemplateFiles = nil
102+ labelTemplateFileMap = map [string ]string {}
103+ for _ , file := range mergeCustomLabelFiles (typeFiles [3 ]) {
104+ description , err := label .LoadTemplateDescription (file )
95105 if err != nil {
96- log . Error ( "Failed to load labels: %v " , err )
106+ return fmt . Errorf ( "failed to load labels: %w " , err )
97107 }
98- LabelTemplates [templateFile ] = labels
108+ displayName := strings .TrimSuffix (file , filepath .Ext (file ))
109+ labelTemplateFileMap [displayName ] = file
110+ LabelTemplateFiles = append (LabelTemplateFiles , OptionFile {DisplayName : displayName , Description : description })
99111 }
100112
101113 // Filter out invalid names and promote preferred licenses.
@@ -111,6 +123,7 @@ func LoadRepoConfig() {
111123 }
112124 }
113125 Licenses = sortedLicenses
126+ return nil
114127}
115128
116129func 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
344357
345358// InitializeLabels adds a label set to a repository using a template
346359func InitializeLabels (ctx context.Context , id int64 , labelTemplate string , isOrg bool ) error {
347- list , err := label . GetTemplateFile (labelTemplate )
360+ list , err := LoadTemplateLabelsByDisplayName (labelTemplate )
348361 if err != nil {
349362 return err
350363 }
@@ -370,3 +383,11 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg
370383 }
371384 return nil
372385}
386+
387+ // LoadTemplateLabelsByDisplayName loads a label template by its display name
388+ func LoadTemplateLabelsByDisplayName (displayName string ) ([]* label.Label , error ) {
389+ if fileName , ok := labelTemplateFileMap [displayName ]; ok {
390+ return label .LoadTemplateFile (fileName )
391+ }
392+ return nil , label.ErrTemplateLoad {TemplateFile : displayName , OriginalError : fmt .Errorf ("label template %q not found" , displayName )}
393+ }
0 commit comments