Add option to initialize repository with labels (#6061)
* Add optional label sets on repo creation * Fix CRLF * Instead of hardcoding default, make it the helper * Move label set init out of repo init Add a new error for the router Combine router label init with repo creation label init Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add issue labels to Swagger for repo creation Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update models/issue_label.go Co-Authored-By: Lauris BH <lauris@nix.lv> * Update models/issue_label.go Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									d4e11ebb18
								
							
						
					
					
						commit
						0118b6aaf8
					
				
					 11 changed files with 87 additions and 16 deletions
				
			
		|  | @ -1058,6 +1058,22 @@ func (err ErrIssueNotExist) Error() string { | |||
| 	return fmt.Sprintf("issue does not exist [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) | ||||
| } | ||||
| 
 | ||||
| // __________      .__  .__ __________                                     __
 | ||||
| // \______   \__ __|  | |  |\______   \ ____  ________ __   ____   _______/  |_
 | ||||
| //  |     ___/  |  \  | |  | |       _// __ \/ ____/  |  \_/ __ \ /  ___/\   __\
 | ||||
|  |  | |||
|  | @ -127,6 +127,34 @@ func (label *Label) ForegroundColor() template.CSS { | |||
| 	return template.CSS("#000") | ||||
| } | ||||
| 
 | ||||
| func initalizeLabels(e Engine, repoID int64, labelTemplate string) error { | ||||
| 	list, err := GetLabelTemplateFile(labelTemplate) | ||||
| 	if err != nil { | ||||
| 		return ErrIssueLabelTemplateLoad{labelTemplate, err} | ||||
| 	} | ||||
| 
 | ||||
| 	labels := make([]*Label, len(list)) | ||||
| 	for i := 0; i < len(list); i++ { | ||||
| 		labels[i] = &Label{ | ||||
| 			RepoID:      repoID, | ||||
| 			Name:        list[i][0], | ||||
| 			Description: list[i][2], | ||||
| 			Color:       list[i][1], | ||||
| 		} | ||||
| 	} | ||||
| 	for _, label := range labels { | ||||
| 		if err = newLabel(e, label); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // InitalizeLabels adds a label set to a repository using a template
 | ||||
| func InitalizeLabels(repoID int64, labelTemplate string) error { | ||||
| 	return initalizeLabels(x, repoID, labelTemplate) | ||||
| } | ||||
| 
 | ||||
| func newLabel(e Engine, label *Label) error { | ||||
| 	_, err := e.Insert(label) | ||||
| 	return err | ||||
|  |  | |||
|  | @ -1098,6 +1098,7 @@ type CreateRepoOptions struct { | |||
| 	Description string | ||||
| 	OriginalURL string | ||||
| 	Gitignores  string | ||||
| 	IssueLabels string | ||||
| 	License     string | ||||
| 	Readme      string | ||||
| 	IsPrivate   bool | ||||
|  | @ -1394,6 +1395,13 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err | |||
| 			return nil, fmt.Errorf("initRepository: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		// Initialize Issue Labels if selected
 | ||||
| 		if len(opts.IssueLabels) > 0 { | ||||
| 			if err = initalizeLabels(sess, repo.ID, opts.IssueLabels); err != nil { | ||||
| 				return nil, fmt.Errorf("initalizeLabels: %v", err) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		_, stderr, err := process.GetManager().ExecDir(-1, | ||||
| 			repoPath, fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath), | ||||
| 			git.GitExecutable, "update-server-info") | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ type CreateRepoForm struct { | |||
| 	Description string `binding:"MaxSize(255)"` | ||||
| 	AutoInit    bool | ||||
| 	Gitignores  string | ||||
| 	IssueLabels string | ||||
| 	License     string | ||||
| 	Readme      string | ||||
| } | ||||
|  |  | |||
|  | @ -67,6 +67,8 @@ type CreateRepoOption struct { | |||
| 	Description string `json:"description" binding:"MaxSize(255)"` | ||||
| 	// Whether the repository is private
 | ||||
| 	Private bool `json:"private"` | ||||
| 	// Issue Label set to use
 | ||||
| 	IssueLabels string `json:"issue_labels"` | ||||
| 	// Whether the repository should be auto-intialized?
 | ||||
| 	AutoInit bool `json:"auto_init"` | ||||
| 	// Gitignores to use
 | ||||
|  |  | |||
|  | @ -578,6 +578,8 @@ fork_visibility_helper = The visibility of a forked repository cannot be changed | |||
| repo_desc = Description | ||||
| repo_lang = Language | ||||
| repo_gitignore_helper = Select .gitignore templates. | ||||
| issue_labels = Issue Labels | ||||
| issue_labels_helper = Select an issue label set. | ||||
| license = License | ||||
| license_helper = Select a license file. | ||||
| readme = README | ||||
|  |  | |||
|  | @ -206,6 +206,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR | |||
| 	repo, err := models.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ | ||||
| 		Name:        opt.Name, | ||||
| 		Description: opt.Description, | ||||
| 		IssueLabels: opt.IssueLabels, | ||||
| 		Gitignores:  opt.Gitignores, | ||||
| 		License:     opt.License, | ||||
| 		Readme:      opt.Readme, | ||||
|  |  | |||
|  | @ -33,24 +33,15 @@ func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) { | |||
| 		ctx.Redirect(ctx.Repo.RepoLink + "/labels") | ||||
| 		return | ||||
| 	} | ||||
| 	list, err := models.GetLabelTemplateFile(form.TemplateName) | ||||
| 	if err != nil { | ||||
| 		ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, err)) | ||||
| 		ctx.Redirect(ctx.Repo.RepoLink + "/labels") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	labels := make([]*models.Label, len(list)) | ||||
| 	for i := 0; i < len(list); i++ { | ||||
| 		labels[i] = &models.Label{ | ||||
| 			RepoID:      ctx.Repo.Repository.ID, | ||||
| 			Name:        list[i][0], | ||||
| 			Description: list[i][2], | ||||
| 			Color:       list[i][1], | ||||
| 	if err := models.InitalizeLabels(ctx.Repo.Repository.ID, form.TemplateName); err != nil { | ||||
| 		if models.IsErrIssueLabelTemplateLoad(err) { | ||||
| 			originalErr := err.(models.ErrIssueLabelTemplateLoad).OriginalError | ||||
| 			ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr)) | ||||
| 			ctx.Redirect(ctx.Repo.RepoLink + "/labels") | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if err := models.NewLabels(labels...); err != nil { | ||||
| 		ctx.ServerError("NewLabels", err) | ||||
| 		ctx.ServerError("InitalizeLabels", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Redirect(ctx.Repo.RepoLink + "/labels") | ||||
|  |  | |||
|  | @ -115,6 +115,7 @@ func Create(ctx *context.Context) { | |||
| 
 | ||||
| 	// Give default value for template to render.
 | ||||
| 	ctx.Data["Gitignores"] = models.Gitignores | ||||
| 	ctx.Data["LabelTemplates"] = models.LabelTemplates | ||||
| 	ctx.Data["Licenses"] = models.Licenses | ||||
| 	ctx.Data["Readmes"] = models.Readmes | ||||
| 	ctx.Data["readme"] = "Default" | ||||
|  | @ -155,6 +156,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
| 	ctx.Data["Title"] = ctx.Tr("new_repo") | ||||
| 
 | ||||
| 	ctx.Data["Gitignores"] = models.Gitignores | ||||
| 	ctx.Data["LabelTemplates"] = models.LabelTemplates | ||||
| 	ctx.Data["Licenses"] = models.Licenses | ||||
| 	ctx.Data["Readmes"] = models.Readmes | ||||
| 
 | ||||
|  | @ -173,6 +175,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
| 		Name:        form.RepoName, | ||||
| 		Description: form.Description, | ||||
| 		Gitignores:  form.Gitignores, | ||||
| 		IssueLabels: form.IssueLabels, | ||||
| 		License:     form.License, | ||||
| 		Readme:      form.Readme, | ||||
| 		IsPrivate:   form.Private || setting.Repository.ForcePrivate, | ||||
|  |  | |||
|  | @ -56,6 +56,20 @@ | |||
| 						<textarea id="description" name="description">{{.description}}</textarea> | ||||
| 					</div> | ||||
| 
 | ||||
| 					<div class="inline field"> | ||||
| 						<label>{{.i18n.Tr "repo.issue_labels"}}</label> | ||||
| 						<div class="ui search normal selection dropdown"> | ||||
| 							<input type="hidden" name="issue_labels" value="{{.issueLabels}}"> | ||||
| 							<div class="default text">{{.i18n.Tr "repo.issue_labels_helper"}}</div> | ||||
| 							<div class="menu"> | ||||
| 								<div class="item" data-value="">{{.i18n.Tr "repo.issue_labels_helper"}}</div> | ||||
|                                 {{range .LabelTemplates}} | ||||
| 									<div class="item" data-value="{{.}}">{{.}}</div> | ||||
|                                 {{end}} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 
 | ||||
| 					<div class="ui divider"></div> | ||||
| 
 | ||||
| 					<div class="inline field"> | ||||
|  |  | |||
|  | @ -7843,6 +7843,11 @@ | |||
|           "type": "string", | ||||
|           "x-go-name": "Gitignores" | ||||
|         }, | ||||
|         "issue_labels": { | ||||
|           "description": "Issue Label set to use", | ||||
|           "type": "string", | ||||
|           "x-go-name": "IssueLabels" | ||||
|         }, | ||||
|         "license": { | ||||
|           "description": "License to use", | ||||
|           "type": "string", | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue