Move init repository related functions to modules (#19159)
* Move init repository related functions to modules * Fix lint * Use ctx but db.DefaultContext Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
b06b9a056c
commit
76aa33d884
15 changed files with 259 additions and 269 deletions
|
@ -703,22 +703,6 @@ func (err ErrIssueIsClosed) Error() string {
|
||||||
return fmt.Sprintf("issue is closed [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
|
return fmt.Sprintf("issue is closed [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrIssueLabelTemplateLoad represents a "ErrIssueLabelTemplateLoad" kind of error.
|
|
||||||
type ErrIssueLabelTemplateLoad struct {
|
|
||||||
TemplateFile string
|
|
||||||
OriginalError error
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrIssueLabelTemplateLoad checks if an error is a ErrIssueLabelTemplateLoad.
|
|
||||||
func IsErrIssueLabelTemplateLoad(err error) bool {
|
|
||||||
_, ok := err.(ErrIssueLabelTemplateLoad)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrIssueLabelTemplateLoad) Error() string {
|
|
||||||
return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrNewIssueInsert is used when the INSERT statement in newIssue fails
|
// ErrNewIssueInsert is used when the INSERT statement in newIssue fails
|
||||||
type ErrNewIssueInsert struct {
|
type ErrNewIssueInsert struct {
|
||||||
OriginalError error
|
OriginalError error
|
||||||
|
|
|
@ -50,50 +50,6 @@ func init() {
|
||||||
db.RegisterModel(new(IssueLabel))
|
db.RegisterModel(new(IssueLabel))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLabelTemplateFile loads the label template file by given name,
|
|
||||||
// then parses and returns a list of name-color pairs and optionally description.
|
|
||||||
func GetLabelTemplateFile(name string) ([][3]string, error) {
|
|
||||||
data, err := GetRepoInitFile("label", name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %v", err)}
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(data), "\n")
|
|
||||||
list := make([][3]string, 0, len(lines))
|
|
||||||
for i := 0; i < len(lines); i++ {
|
|
||||||
line := strings.TrimSpace(lines[i])
|
|
||||||
if len(line) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.SplitN(line, ";", 2)
|
|
||||||
|
|
||||||
fields := strings.SplitN(parts[0], " ", 2)
|
|
||||||
if len(fields) != 2 {
|
|
||||||
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
|
|
||||||
}
|
|
||||||
|
|
||||||
color := strings.Trim(fields[0], " ")
|
|
||||||
if len(color) == 6 {
|
|
||||||
color = "#" + color
|
|
||||||
}
|
|
||||||
if !LabelColorPattern.MatchString(color) {
|
|
||||||
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("bad HTML color code in line: %s", line)}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description string
|
|
||||||
|
|
||||||
if len(parts) > 1 {
|
|
||||||
description = strings.TrimSpace(parts[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
fields[1] = strings.TrimSpace(fields[1])
|
|
||||||
list = append(list, [3]string{fields[1], color, description})
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues.
|
// CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues.
|
||||||
func (label *Label) CalOpenIssues() {
|
func (label *Label) CalOpenIssues() {
|
||||||
label.NumOpenIssues = label.NumIssues - label.NumClosedIssues
|
label.NumOpenIssues = label.NumIssues - label.NumClosedIssues
|
||||||
|
@ -191,70 +147,8 @@ func (label *Label) ForegroundColor() template.CSS {
|
||||||
return template.CSS("#000")
|
return template.CSS("#000")
|
||||||
}
|
}
|
||||||
|
|
||||||
// .____ ___. .__
|
|
||||||
// | | _____ \_ |__ ____ | |
|
|
||||||
// | | \__ \ | __ \_/ __ \| |
|
|
||||||
// | |___ / __ \| \_\ \ ___/| |__
|
|
||||||
// >_______ (____ /___ /\___ >____/
|
|
||||||
|
|
||||||
func loadLabels(labelTemplate string) ([]string, error) {
|
|
||||||
list, err := GetLabelTemplateFile(labelTemplate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := make([]string, len(list))
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
labels[i] = list[i][0]
|
|
||||||
}
|
|
||||||
return labels, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadLabelsFormatted loads the labels' list of a template file as a string separated by comma
|
|
||||||
func LoadLabelsFormatted(labelTemplate string) (string, error) {
|
|
||||||
labels, err := loadLabels(labelTemplate)
|
|
||||||
return strings.Join(labels, ", "), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func initializeLabels(e db.Engine, id int64, labelTemplate string, isOrg bool) error {
|
|
||||||
list, err := GetLabelTemplateFile(labelTemplate)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := make([]*Label, len(list))
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
labels[i] = &Label{
|
|
||||||
Name: list[i][0],
|
|
||||||
Description: list[i][2],
|
|
||||||
Color: list[i][1],
|
|
||||||
}
|
|
||||||
if isOrg {
|
|
||||||
labels[i].OrgID = id
|
|
||||||
} else {
|
|
||||||
labels[i].RepoID = id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, label := range labels {
|
|
||||||
if err = newLabel(e, label); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitializeLabels adds a label set to a repository using a template
|
|
||||||
func InitializeLabels(ctx context.Context, repoID int64, labelTemplate string, isOrg bool) error {
|
|
||||||
return initializeLabels(db.GetEngine(ctx), repoID, labelTemplate, isOrg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLabel(e db.Engine, label *Label) error {
|
|
||||||
_, err := e.Insert(label)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLabel creates a new label
|
// NewLabel creates a new label
|
||||||
func NewLabel(label *Label) error {
|
func NewLabel(ctx context.Context, label *Label) error {
|
||||||
if !LabelColorPattern.MatchString(label.Color) {
|
if !LabelColorPattern.MatchString(label.Color) {
|
||||||
return fmt.Errorf("bad color code: %s", label.Color)
|
return fmt.Errorf("bad color code: %s", label.Color)
|
||||||
}
|
}
|
||||||
|
@ -275,7 +169,7 @@ func NewLabel(label *Label) error {
|
||||||
label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
|
label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newLabel(db.GetEngine(db.DefaultContext), label)
|
return db.Insert(ctx, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLabels creates new labels
|
// NewLabels creates new labels
|
||||||
|
@ -290,7 +184,7 @@ func NewLabels(labels ...*Label) error {
|
||||||
if !LabelColorPattern.MatchString(label.Color) {
|
if !LabelColorPattern.MatchString(label.Color) {
|
||||||
return fmt.Errorf("bad color code: %s", label.Color)
|
return fmt.Errorf("bad color code: %s", label.Color)
|
||||||
}
|
}
|
||||||
if err := newLabel(db.GetEngine(ctx), label); err != nil {
|
if err := db.Insert(ctx, label); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,11 @@ func TestNewLabels(t *testing.T) {
|
||||||
{RepoID: 4, Name: "labelName4", Color: "ABCDEF"},
|
{RepoID: 4, Name: "labelName4", Color: "ABCDEF"},
|
||||||
{RepoID: 5, Name: "labelName5", Color: "DEF"},
|
{RepoID: 5, Name: "labelName5", Color: "DEF"},
|
||||||
}
|
}
|
||||||
assert.Error(t, NewLabel(&Label{RepoID: 3, Name: "invalid Color", Color: ""}))
|
assert.Error(t, NewLabel(db.DefaultContext, &Label{RepoID: 3, Name: "invalid Color", Color: ""}))
|
||||||
assert.Error(t, NewLabel(&Label{RepoID: 3, Name: "invalid Color", Color: "#45G"}))
|
assert.Error(t, NewLabel(db.DefaultContext, &Label{RepoID: 3, Name: "invalid Color", Color: "#45G"}))
|
||||||
assert.Error(t, NewLabel(&Label{RepoID: 3, Name: "invalid Color", Color: "#12345G"}))
|
assert.Error(t, NewLabel(db.DefaultContext, &Label{RepoID: 3, Name: "invalid Color", Color: "#12345G"}))
|
||||||
assert.Error(t, NewLabel(&Label{RepoID: 3, Name: "invalid Color", Color: "45G"}))
|
assert.Error(t, NewLabel(db.DefaultContext, &Label{RepoID: 3, Name: "invalid Color", Color: "45G"}))
|
||||||
assert.Error(t, NewLabel(&Label{RepoID: 3, Name: "invalid Color", Color: "12345G"}))
|
assert.Error(t, NewLabel(db.DefaultContext, &Label{RepoID: 3, Name: "invalid Color", Color: "12345G"}))
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
unittest.AssertNotExistsBean(t, label)
|
unittest.AssertNotExistsBean(t, label)
|
||||||
}
|
}
|
||||||
|
|
112
models/repo.go
112
models/repo.go
|
@ -10,7 +10,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -28,7 +27,6 @@ import (
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/lfs"
|
"code.gitea.io/gitea/modules/lfs"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/options"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -37,90 +35,11 @@ import (
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// Gitignores contains the gitiginore files
|
|
||||||
Gitignores []string
|
|
||||||
|
|
||||||
// Licenses contains the license files
|
|
||||||
Licenses []string
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// ItemsPerPage maximum items per page in forks, watchers and stars of a repo
|
// ItemsPerPage maximum items per page in forks, watchers and stars of a repo
|
||||||
ItemsPerPage = 40
|
var ItemsPerPage = 40
|
||||||
)
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
for i, t := range types {
|
|
||||||
files, err := options.Dir(t)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to get %s files: %v", 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.IsStringInSlice(f, files, 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)
|
|
||||||
|
|
||||||
// Load label templates
|
|
||||||
LabelTemplates = make(map[string]string)
|
|
||||||
for _, templateFile := range LabelTemplatesFiles {
|
|
||||||
labels, err := LoadLabelsFormatted(templateFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to load labels: %v", err)
|
|
||||||
}
|
|
||||||
LabelTemplates[templateFile] = labels
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out invalid names and promote preferred licenses.
|
|
||||||
sortedLicenses := make([]string, 0, len(Licenses))
|
|
||||||
for _, name := range setting.Repository.PreferredLicenses {
|
|
||||||
if util.IsStringInSlice(name, Licenses, true) {
|
|
||||||
sortedLicenses = append(sortedLicenses, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, name := range Licenses {
|
|
||||||
if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) {
|
|
||||||
sortedLicenses = append(sortedLicenses, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Licenses = sortedLicenses
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRepoContext creates a new repository context
|
// NewRepoContext creates a new repository context
|
||||||
func NewRepoContext() {
|
func NewRepoContext() {
|
||||||
loadRepoConfig()
|
|
||||||
unit.LoadUnitConfig()
|
unit.LoadUnitConfig()
|
||||||
|
|
||||||
admin_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath)
|
admin_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath)
|
||||||
|
@ -441,35 +360,6 @@ type CreateRepoOptions struct {
|
||||||
MirrorInterval string
|
MirrorInterval string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRepoInitFile returns repository init files
|
|
||||||
func GetRepoInitFile(tp, name string) ([]byte, error) {
|
|
||||||
cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
|
|
||||||
relPath := path.Join("options", tp, cleanedName)
|
|
||||||
|
|
||||||
// Use custom file when available.
|
|
||||||
customPath := path.Join(setting.CustomPath, relPath)
|
|
||||||
isFile, err := util.IsFile(customPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
|
|
||||||
}
|
|
||||||
if isFile {
|
|
||||||
return os.ReadFile(customPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tp {
|
|
||||||
case "readme":
|
|
||||||
return options.Readme(cleanedName)
|
|
||||||
case "gitignore":
|
|
||||||
return options.Gitignore(cleanedName)
|
|
||||||
case "license":
|
|
||||||
return options.License(cleanedName)
|
|
||||||
case "label":
|
|
||||||
return options.Labels(cleanedName)
|
|
||||||
default:
|
|
||||||
return []byte{}, fmt.Errorf("Invalid init file type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRepository creates a repository for the user/organization.
|
// CreateRepository creates a repository for the user/organization.
|
||||||
func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt bool) (err error) {
|
func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt bool) (err error) {
|
||||||
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
|
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
|
||||||
|
|
|
@ -110,7 +110,7 @@ func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_m
|
||||||
Description: templateLabel.Description,
|
Description: templateLabel.Description,
|
||||||
Color: templateLabel.Color,
|
Color: templateLabel.Color,
|
||||||
}
|
}
|
||||||
if err := newLabel(db.GetEngine(ctx), generateLabel); err != nil {
|
if err := db.Insert(ctx, generateLabel); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (
|
||||||
|
|
||||||
// Check if label template exist
|
// Check if label template exist
|
||||||
if len(opts.IssueLabels) > 0 {
|
if len(opts.IssueLabels) > 0 {
|
||||||
if _, err := models.GetLabelTemplateFile(opts.IssueLabels); err != nil {
|
if _, err := GetLabelTemplateFile(opts.IssueLabels); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (
|
||||||
|
|
||||||
// Initialize Issue Labels if selected
|
// Initialize Issue Labels if selected
|
||||||
if len(opts.IssueLabels) > 0 {
|
if len(opts.IssueLabels) > 0 {
|
||||||
if err = models.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
|
if err = InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
|
||||||
rollbackRepo = repo
|
rollbackRepo = repo
|
||||||
rollbackRepo.OwnerID = u.ID
|
rollbackRepo.OwnerID = u.ID
|
||||||
return fmt.Errorf("InitializeLabels: %v", err)
|
return fmt.Errorf("InitializeLabels: %v", err)
|
||||||
|
|
|
@ -9,7 +9,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/options"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
|
@ -25,6 +28,192 @@ import (
|
||||||
"github.com/unknwon/com"
|
"github.com/unknwon/com"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Gitignores contains the gitiginore files
|
||||||
|
Gitignores []string
|
||||||
|
|
||||||
|
// Licenses contains the license files
|
||||||
|
Licenses []string
|
||||||
|
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrIssueLabelTemplateLoad represents a "ErrIssueLabelTemplateLoad" kind of error.
|
||||||
|
type ErrIssueLabelTemplateLoad struct {
|
||||||
|
TemplateFile string
|
||||||
|
OriginalError error
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrIssueLabelTemplateLoad checks if an error is a ErrIssueLabelTemplateLoad.
|
||||||
|
func IsErrIssueLabelTemplateLoad(err error) bool {
|
||||||
|
_, ok := err.(ErrIssueLabelTemplateLoad)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrIssueLabelTemplateLoad) Error() string {
|
||||||
|
return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoInitFile returns repository init files
|
||||||
|
func GetRepoInitFile(tp, name string) ([]byte, error) {
|
||||||
|
cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
|
||||||
|
relPath := path.Join("options", tp, cleanedName)
|
||||||
|
|
||||||
|
// Use custom file when available.
|
||||||
|
customPath := path.Join(setting.CustomPath, relPath)
|
||||||
|
isFile, err := util.IsFile(customPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
|
||||||
|
}
|
||||||
|
if isFile {
|
||||||
|
return os.ReadFile(customPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tp {
|
||||||
|
case "readme":
|
||||||
|
return options.Readme(cleanedName)
|
||||||
|
case "gitignore":
|
||||||
|
return options.Gitignore(cleanedName)
|
||||||
|
case "license":
|
||||||
|
return options.License(cleanedName)
|
||||||
|
case "label":
|
||||||
|
return options.Labels(cleanedName)
|
||||||
|
default:
|
||||||
|
return []byte{}, fmt.Errorf("Invalid init file type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLabelTemplateFile loads the label template file by given name,
|
||||||
|
// then parses and returns a list of name-color pairs and optionally description.
|
||||||
|
func GetLabelTemplateFile(name string) ([][3]string, error) {
|
||||||
|
data, err := GetRepoInitFile("label", name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %v", err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
list := make([][3]string, 0, len(lines))
|
||||||
|
for i := 0; i < len(lines); i++ {
|
||||||
|
line := strings.TrimSpace(lines[i])
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(line, ";", 2)
|
||||||
|
|
||||||
|
fields := strings.SplitN(parts[0], " ", 2)
|
||||||
|
if len(fields) != 2 {
|
||||||
|
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
|
||||||
|
}
|
||||||
|
|
||||||
|
color := strings.Trim(fields[0], " ")
|
||||||
|
if len(color) == 6 {
|
||||||
|
color = "#" + color
|
||||||
|
}
|
||||||
|
if !models.LabelColorPattern.MatchString(color) {
|
||||||
|
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("bad HTML color code in line: %s", line)}
|
||||||
|
}
|
||||||
|
|
||||||
|
var description string
|
||||||
|
|
||||||
|
if len(parts) > 1 {
|
||||||
|
description = strings.TrimSpace(parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
fields[1] = strings.TrimSpace(fields[1])
|
||||||
|
list = append(list, [3]string{fields[1], color, description})
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadLabels(labelTemplate string) ([]string, error) {
|
||||||
|
list, err := GetLabelTemplateFile(labelTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make([]string, len(list))
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
labels[i] = list[i][0]
|
||||||
|
}
|
||||||
|
return labels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadLabelsFormatted loads the labels' list of a template file as a string separated by comma
|
||||||
|
func LoadLabelsFormatted(labelTemplate string) (string, error) {
|
||||||
|
labels, err := loadLabels(labelTemplate)
|
||||||
|
return strings.Join(labels, ", "), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
for i, t := range types {
|
||||||
|
files, err := options.Dir(t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to get %s files: %v", 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.IsStringInSlice(f, files, 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)
|
||||||
|
|
||||||
|
// Load label templates
|
||||||
|
LabelTemplates = make(map[string]string)
|
||||||
|
for _, templateFile := range LabelTemplatesFiles {
|
||||||
|
labels, err := LoadLabelsFormatted(templateFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to load labels: %v", err)
|
||||||
|
}
|
||||||
|
LabelTemplates[templateFile] = labels
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out invalid names and promote preferred licenses.
|
||||||
|
sortedLicenses := make([]string, 0, len(Licenses))
|
||||||
|
for _, name := range setting.Repository.PreferredLicenses {
|
||||||
|
if util.IsStringInSlice(name, Licenses, true) {
|
||||||
|
sortedLicenses = append(sortedLicenses, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, name := range Licenses {
|
||||||
|
if !util.IsStringInSlice(name, setting.Repository.PreferredLicenses, true) {
|
||||||
|
sortedLicenses = append(sortedLicenses, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Licenses = sortedLicenses
|
||||||
|
}
|
||||||
|
|
||||||
func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts models.CreateRepoOptions) error {
|
func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts models.CreateRepoOptions) error {
|
||||||
commitTimeStr := time.Now().Format(time.RFC3339)
|
commitTimeStr := time.Now().Format(time.RFC3339)
|
||||||
authorSig := repo.Owner.NewGitSig()
|
authorSig := repo.Owner.NewGitSig()
|
||||||
|
@ -48,7 +237,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
// README
|
// README
|
||||||
data, err := models.GetRepoInitFile("readme", opts.Readme)
|
data, err := GetRepoInitFile("readme", opts.Readme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetRepoInitFile[%s]: %v", opts.Readme, err)
|
return fmt.Errorf("GetRepoInitFile[%s]: %v", opts.Readme, err)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +260,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
names := strings.Split(opts.Gitignores, ",")
|
names := strings.Split(opts.Gitignores, ",")
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
data, err = models.GetRepoInitFile("gitignore", name)
|
data, err = GetRepoInitFile("gitignore", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetRepoInitFile[%s]: %v", name, err)
|
return fmt.Errorf("GetRepoInitFile[%s]: %v", name, err)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +278,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
|
||||||
|
|
||||||
// LICENSE
|
// LICENSE
|
||||||
if len(opts.License) > 0 {
|
if len(opts.License) > 0 {
|
||||||
data, err = models.GetRepoInitFile("license", opts.License)
|
data, err = GetRepoInitFile("license", opts.License)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetRepoInitFile[%s]: %v", opts.License, err)
|
return fmt.Errorf("GetRepoInitFile[%s]: %v", opts.License, err)
|
||||||
}
|
}
|
||||||
|
@ -257,3 +446,31 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 := GetLabelTemplateFile(labelTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make([]*models.Label, len(list))
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
labels[i] = &models.Label{
|
||||||
|
Name: list[i][0],
|
||||||
|
Description: list[i][2],
|
||||||
|
Color: list[i][1],
|
||||||
|
}
|
||||||
|
if isOrg {
|
||||||
|
labels[i].OrgID = id
|
||||||
|
} else {
|
||||||
|
labels[i].RepoID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, label := range labels {
|
||||||
|
if err = models.NewLabel(ctx, label); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ func CreateLabel(ctx *context.APIContext) {
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
}
|
}
|
||||||
if err := models.NewLabel(label); err != nil {
|
if err := models.NewLabel(ctx, label); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
|
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ func CreateLabel(ctx *context.APIContext) {
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
}
|
}
|
||||||
if err := models.NewLabel(label); err != nil {
|
if err := models.NewLabel(ctx, label); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
|
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
)
|
)
|
||||||
|
@ -48,7 +49,7 @@ func NewLabel(ctx *context.Context) {
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Color: form.Color,
|
Color: form.Color,
|
||||||
}
|
}
|
||||||
if err := models.NewLabel(l); err != nil {
|
if err := models.NewLabel(ctx, l); err != nil {
|
||||||
ctx.ServerError("NewLabel", err)
|
ctx.ServerError("NewLabel", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -100,9 +101,9 @@ func InitializeLabels(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.InitializeLabels(ctx, ctx.Org.Organization.ID, form.TemplateName, true); err != nil {
|
if err := repo_module.InitializeLabels(ctx, ctx.Org.Organization.ID, form.TemplateName, true); err != nil {
|
||||||
if models.IsErrIssueLabelTemplateLoad(err) {
|
if repo_module.IsErrIssueLabelTemplateLoad(err) {
|
||||||
originalErr := err.(models.ErrIssueLabelTemplateLoad).OriginalError
|
originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError
|
||||||
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
|
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
|
||||||
ctx.Redirect(ctx.Org.OrgLink + "/settings/labels")
|
ctx.Redirect(ctx.Org.OrgLink + "/settings/labels")
|
||||||
return
|
return
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
user_setting "code.gitea.io/gitea/routers/web/user/setting"
|
user_setting "code.gitea.io/gitea/routers/web/user/setting"
|
||||||
|
@ -232,6 +233,6 @@ func Labels(ctx *context.Context) {
|
||||||
ctx.Data["PageIsOrgSettings"] = true
|
ctx.Data["PageIsOrgSettings"] = true
|
||||||
ctx.Data["PageIsOrgSettingsLabels"] = true
|
ctx.Data["PageIsOrgSettingsLabels"] = true
|
||||||
ctx.Data["RequireTribute"] = true
|
ctx.Data["RequireTribute"] = true
|
||||||
ctx.Data["LabelTemplates"] = models.LabelTemplates
|
ctx.Data["LabelTemplates"] = repo_module.LabelTemplates
|
||||||
ctx.HTML(http.StatusOK, tplSettingsLabels)
|
ctx.HTML(http.StatusOK, tplSettingsLabels)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
"code.gitea.io/gitea/services/forms"
|
"code.gitea.io/gitea/services/forms"
|
||||||
issue_service "code.gitea.io/gitea/services/issue"
|
issue_service "code.gitea.io/gitea/services/issue"
|
||||||
|
@ -28,7 +29,7 @@ func Labels(ctx *context.Context) {
|
||||||
ctx.Data["PageIsIssueList"] = true
|
ctx.Data["PageIsIssueList"] = true
|
||||||
ctx.Data["PageIsLabels"] = true
|
ctx.Data["PageIsLabels"] = true
|
||||||
ctx.Data["RequireTribute"] = true
|
ctx.Data["RequireTribute"] = true
|
||||||
ctx.Data["LabelTemplates"] = models.LabelTemplates
|
ctx.Data["LabelTemplates"] = repo_module.LabelTemplates
|
||||||
ctx.HTML(http.StatusOK, tplLabels)
|
ctx.HTML(http.StatusOK, tplLabels)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +41,9 @@ func InitializeLabels(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil {
|
if err := repo_module.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil {
|
||||||
if models.IsErrIssueLabelTemplateLoad(err) {
|
if repo_module.IsErrIssueLabelTemplateLoad(err) {
|
||||||
originalErr := err.(models.ErrIssueLabelTemplateLoad).OriginalError
|
originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError
|
||||||
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
|
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||||
return
|
return
|
||||||
|
@ -116,7 +117,7 @@ func NewLabel(ctx *context.Context) {
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Color: form.Color,
|
Color: form.Color,
|
||||||
}
|
}
|
||||||
if err := models.NewLabel(l); err != nil {
|
if err := models.NewLabel(ctx, l); err != nil {
|
||||||
ctx.ServerError("NewLabel", err)
|
ctx.ServerError("NewLabel", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -129,10 +130,10 @@ func Create(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("new_repo")
|
ctx.Data["Title"] = ctx.Tr("new_repo")
|
||||||
|
|
||||||
// Give default value for template to render.
|
// Give default value for template to render.
|
||||||
ctx.Data["Gitignores"] = models.Gitignores
|
ctx.Data["Gitignores"] = repo_module.Gitignores
|
||||||
ctx.Data["LabelTemplates"] = models.LabelTemplates
|
ctx.Data["LabelTemplates"] = repo_module.LabelTemplates
|
||||||
ctx.Data["Licenses"] = models.Licenses
|
ctx.Data["Licenses"] = repo_module.Licenses
|
||||||
ctx.Data["Readmes"] = models.Readmes
|
ctx.Data["Readmes"] = repo_module.Readmes
|
||||||
ctx.Data["readme"] = "Default"
|
ctx.Data["readme"] = "Default"
|
||||||
ctx.Data["private"] = getRepoPrivate(ctx)
|
ctx.Data["private"] = getRepoPrivate(ctx)
|
||||||
ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
||||||
|
@ -197,10 +198,10 @@ func CreatePost(ctx *context.Context) {
|
||||||
form := web.GetForm(ctx).(*forms.CreateRepoForm)
|
form := web.GetForm(ctx).(*forms.CreateRepoForm)
|
||||||
ctx.Data["Title"] = ctx.Tr("new_repo")
|
ctx.Data["Title"] = ctx.Tr("new_repo")
|
||||||
|
|
||||||
ctx.Data["Gitignores"] = models.Gitignores
|
ctx.Data["Gitignores"] = repo_module.Gitignores
|
||||||
ctx.Data["LabelTemplates"] = models.LabelTemplates
|
ctx.Data["LabelTemplates"] = repo_module.LabelTemplates
|
||||||
ctx.Data["Licenses"] = models.Licenses
|
ctx.Data["Licenses"] = repo_module.Licenses
|
||||||
ctx.Data["Readmes"] = models.Readmes
|
ctx.Data["Readmes"] = repo_module.Readmes
|
||||||
|
|
||||||
ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo()
|
ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo()
|
||||||
ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit()
|
ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit()
|
||||||
|
|
|
@ -79,7 +79,7 @@ func AdoptRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (*
|
||||||
|
|
||||||
// Initialize Issue Labels if selected
|
// Initialize Issue Labels if selected
|
||||||
if len(opts.IssueLabels) > 0 {
|
if len(opts.IssueLabels) > 0 {
|
||||||
if err := models.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
|
if err := repo_module.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
|
||||||
return fmt.Errorf("InitializeLabels: %v", err)
|
return fmt.Errorf("InitializeLabels: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,5 +74,6 @@ func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_mo
|
||||||
|
|
||||||
// NewContext start repository service
|
// NewContext start repository service
|
||||||
func NewContext() error {
|
func NewContext() error {
|
||||||
|
repo_module.LoadRepoConfig()
|
||||||
return initPushQueue()
|
return initPushQueue()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue