mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add avatar and issue labels to template repositories (#9149)
* Add avatar and issue labels Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix redundant if-err Signed-off-by: jolheiser <john.olheiser@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							95c3dc856a
						
					
				
				
					commit
					62bcb2b7f1
				
			@@ -279,10 +279,9 @@ func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
 | 
				
			|||||||
		Find(&labels)
 | 
							Find(&labels)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
 | 
					func getLabelsByRepoID(e Engine, repoID int64, sortType string) ([]*Label, error) {
 | 
				
			||||||
func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) {
 | 
					 | 
				
			||||||
	labels := make([]*Label, 0, 10)
 | 
						labels := make([]*Label, 0, 10)
 | 
				
			||||||
	sess := x.Where("repo_id = ?", repoID)
 | 
						sess := e.Where("repo_id = ?", repoID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch sortType {
 | 
						switch sortType {
 | 
				
			||||||
	case "reversealphabetically":
 | 
						case "reversealphabetically":
 | 
				
			||||||
@@ -298,6 +297,11 @@ func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) {
 | 
				
			|||||||
	return labels, sess.Find(&labels)
 | 
						return labels, sess.Find(&labels)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetLabelsByRepoID returns all labels that belong to given repository by ID.
 | 
				
			||||||
 | 
					func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) {
 | 
				
			||||||
 | 
						return getLabelsByRepoID(x, repoID, sortType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
 | 
					func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
 | 
				
			||||||
	var labels []*Label
 | 
						var labels []*Label
 | 
				
			||||||
	return labels, e.Where("issue_label.issue_id = ?", issueID).
 | 
						return labels, e.Where("issue_label.issue_id = ?", issueID).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1257,22 +1257,6 @@ type CreateRepoOptions struct {
 | 
				
			|||||||
	Status      RepositoryStatus
 | 
						Status      RepositoryStatus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GenerateRepoOptions contains the template units to generate
 | 
					 | 
				
			||||||
type GenerateRepoOptions struct {
 | 
					 | 
				
			||||||
	Name        string
 | 
					 | 
				
			||||||
	Description string
 | 
					 | 
				
			||||||
	Private     bool
 | 
					 | 
				
			||||||
	GitContent  bool
 | 
					 | 
				
			||||||
	Topics      bool
 | 
					 | 
				
			||||||
	GitHooks    bool
 | 
					 | 
				
			||||||
	Webhooks    bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsValid checks whether at least one option is chosen for generation
 | 
					 | 
				
			||||||
func (gro GenerateRepoOptions) IsValid() bool {
 | 
					 | 
				
			||||||
	return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks // or other items as they are added
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getRepoInitFile(tp, name string) ([]byte, error) {
 | 
					func getRepoInitFile(tp, name string) ([]byte, error) {
 | 
				
			||||||
	cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
 | 
						cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
 | 
				
			||||||
	relPath := path.Join("options", tp, cleanedName)
 | 
						relPath := path.Join("options", tp, cleanedName)
 | 
				
			||||||
@@ -2957,8 +2941,12 @@ func (repo *Repository) GetTreePathLock(treePath string) (*LFSLock, error) {
 | 
				
			|||||||
	return nil, nil
 | 
						return nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateRepositoryCols updates repository's columns
 | 
					func updateRepositoryCols(e Engine, repo *Repository, cols ...string) error {
 | 
				
			||||||
func UpdateRepositoryCols(repo *Repository, cols ...string) error {
 | 
						_, err := e.ID(repo.ID).Cols(cols...).Update(repo)
 | 
				
			||||||
	_, err := x.ID(repo.ID).Cols(cols...).Update(repo)
 | 
					 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateRepositoryCols updates repository's columns
 | 
				
			||||||
 | 
					func UpdateRepositoryCols(repo *Repository, cols ...string) error {
 | 
				
			||||||
 | 
						return updateRepositoryCols(x, repo, cols...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -17,6 +18,24 @@ import (
 | 
				
			|||||||
	"github.com/unknwon/com"
 | 
						"github.com/unknwon/com"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateRepoOptions contains the template units to generate
 | 
				
			||||||
 | 
					type GenerateRepoOptions struct {
 | 
				
			||||||
 | 
						Name        string
 | 
				
			||||||
 | 
						Description string
 | 
				
			||||||
 | 
						Private     bool
 | 
				
			||||||
 | 
						GitContent  bool
 | 
				
			||||||
 | 
						Topics      bool
 | 
				
			||||||
 | 
						GitHooks    bool
 | 
				
			||||||
 | 
						Webhooks    bool
 | 
				
			||||||
 | 
						Avatar      bool
 | 
				
			||||||
 | 
						IssueLabels bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsValid checks whether at least one option is chosen for generation
 | 
				
			||||||
 | 
					func (gro GenerateRepoOptions) IsValid() bool {
 | 
				
			||||||
 | 
						return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// generateRepository initializes repository from template
 | 
					// generateRepository initializes repository from template
 | 
				
			||||||
func generateRepository(e Engine, repo, templateRepo *Repository) (err error) {
 | 
					func generateRepository(e Engine, repo, templateRepo *Repository) (err error) {
 | 
				
			||||||
	tmpDir := filepath.Join(os.TempDir(), "gitea-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond()))
 | 
						tmpDir := filepath.Join(os.TempDir(), "gitea-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond()))
 | 
				
			||||||
@@ -160,3 +179,34 @@ func GenerateWebhooks(ctx DBContext, templateRepo, generateRepo *Repository) err
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateAvatar generates the avatar from a template repository
 | 
				
			||||||
 | 
					func GenerateAvatar(ctx DBContext, templateRepo, generateRepo *Repository) error {
 | 
				
			||||||
 | 
						generateRepo.Avatar = strings.Replace(templateRepo.Avatar, strconv.FormatInt(templateRepo.ID, 10), strconv.FormatInt(generateRepo.ID, 10), 1)
 | 
				
			||||||
 | 
						if err := com.Copy(templateRepo.CustomAvatarPath(), generateRepo.CustomAvatarPath()); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return updateRepositoryCols(ctx.e, generateRepo, "avatar")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateIssueLabels generates issue labels from a template repository
 | 
				
			||||||
 | 
					func GenerateIssueLabels(ctx DBContext, templateRepo, generateRepo *Repository) error {
 | 
				
			||||||
 | 
						templateLabels, err := getLabelsByRepoID(ctx.e, templateRepo.ID, "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, templateLabel := range templateLabels {
 | 
				
			||||||
 | 
							generateLabel := &Label{
 | 
				
			||||||
 | 
								RepoID:      generateRepo.ID,
 | 
				
			||||||
 | 
								Name:        templateLabel.Name,
 | 
				
			||||||
 | 
								Description: templateLabel.Description,
 | 
				
			||||||
 | 
								Color:       templateLabel.Color,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := newLabel(ctx.e, generateLabel); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,8 @@ type CreateRepoForm struct {
 | 
				
			|||||||
	Topics       bool
 | 
						Topics       bool
 | 
				
			||||||
	GitHooks     bool
 | 
						GitHooks     bool
 | 
				
			||||||
	Webhooks     bool
 | 
						Webhooks     bool
 | 
				
			||||||
 | 
						Avatar       bool
 | 
				
			||||||
 | 
						Labels       bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Validate validates the fields
 | 
					// Validate validates the fields
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -641,6 +641,8 @@ template.git_hooks = Git Hooks
 | 
				
			|||||||
template.git_hooks_tooltip = You are currently unable to modify or remove git hooks once added. Select this only if you trust the template repository.
 | 
					template.git_hooks_tooltip = You are currently unable to modify or remove git hooks once added. Select this only if you trust the template repository.
 | 
				
			||||||
template.webhooks = Webhooks
 | 
					template.webhooks = Webhooks
 | 
				
			||||||
template.topics = Topics
 | 
					template.topics = Topics
 | 
				
			||||||
 | 
					template.avatar = Avatar
 | 
				
			||||||
 | 
					template.issue_labels = Issue Labels
 | 
				
			||||||
template.one_item = Must select at least one template item
 | 
					template.one_item = Must select at least one template item
 | 
				
			||||||
template.invalid = Must select a template repository
 | 
					template.invalid = Must select a template repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,6 +190,8 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
 | 
				
			|||||||
			Topics:      form.Topics,
 | 
								Topics:      form.Topics,
 | 
				
			||||||
			GitHooks:    form.GitHooks,
 | 
								GitHooks:    form.GitHooks,
 | 
				
			||||||
			Webhooks:    form.Webhooks,
 | 
								Webhooks:    form.Webhooks,
 | 
				
			||||||
 | 
								Avatar:      form.Avatar,
 | 
				
			||||||
 | 
								IssueLabels: form.Labels,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !opts.IsValid() {
 | 
							if !opts.IsValid() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,20 @@ func GenerateRepository(doer, owner *models.User, templateRepo *models.Repositor
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Avatar
 | 
				
			||||||
 | 
							if opts.Avatar && len(templateRepo.Avatar) > 0 {
 | 
				
			||||||
 | 
								if err = models.GenerateAvatar(ctx, templateRepo, generateRepo); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Issue Labels
 | 
				
			||||||
 | 
							if opts.IssueLabels {
 | 
				
			||||||
 | 
								if err = models.GenerateIssueLabels(ctx, templateRepo, generateRepo); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		if generateRepo != nil {
 | 
							if generateRepo != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,6 +88,17 @@
 | 
				
			|||||||
								<label>{{.i18n.Tr "repo.template.topics"}}</label>
 | 
													<label>{{.i18n.Tr "repo.template.topics"}}</label>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
 | 
											<div class="inline field">
 | 
				
			||||||
 | 
												<label></label>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input class="hidden" name="avatar" type="checkbox" tabindex="0" {{if .avatar}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.template.avatar"}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input class="hidden" name="labels" type="checkbox" tabindex="0" {{if .labels}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.template.issue_labels"}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					<div id="non_template">
 | 
										<div id="non_template">
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user