Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if label template exist first #14384

Merged
merged 5 commits into from
Jan 18, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions models/issue_label.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type Label struct {
func GetLabelTemplateFile(name string) ([][3]string, error) {
data, err := GetRepoInitFile("label", name)
if err != nil {
return nil, fmt.Errorf("GetRepoInitFile: %v", err)
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %v", err)}
}

lines := strings.Split(string(data), "\n")
Expand All @@ -62,15 +62,15 @@ func GetLabelTemplateFile(name string) ([][3]string, error) {

fields := strings.SplitN(parts[0], " ", 2)
if len(fields) != 2 {
return nil, fmt.Errorf("line is malformed: %s", line)
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, fmt.Errorf("bad HTML color code in line: %s", line)
return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("bad HTML color code in line: %s", line)}
}

var description string
Expand Down Expand Up @@ -167,7 +167,7 @@ func (label *Label) ForegroundColor() template.CSS {
func loadLabels(labelTemplate string) ([]string, error) {
list, err := GetLabelTemplateFile(labelTemplate)
if err != nil {
return nil, ErrIssueLabelTemplateLoad{labelTemplate, err}
return nil, err
}

labels := make([]string, len(list))
Expand All @@ -186,7 +186,7 @@ func LoadLabelsFormatted(labelTemplate string) (string, error) {
func initializeLabels(e Engine, id int64, labelTemplate string, isOrg bool) error {
list, err := GetLabelTemplateFile(labelTemplate)
if err != nil {
return ErrIssueLabelTemplateLoad{labelTemplate, err}
return err
}

labels := make([]*Label, len(list))
Expand Down
99 changes: 54 additions & 45 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1512,60 +1512,82 @@ func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes [

// DeleteRepository deletes a repository for a user or organization.
func DeleteRepository(doer *User, uid, repoID int64) error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}

if err := deleteRepository(sess, doer, uid, repoID); err != nil {
return err
}

if err := sess.Commit(); err != nil {
6543 marked this conversation as resolved.
Show resolved Hide resolved
sess.Close()
// We need to rewrite the public keys because the commit failed
if err2 := RewriteAllPublicKeys(); err2 != nil {
return fmt.Errorf("Commit: %v SSH Keys: %v", err, err2)
}
return fmt.Errorf("Commit: %v", err)
}

return sess.Close()
}

// DeleteRepositoryWithContext deletes a repository for a user or organization.
func DeleteRepositoryWithContext(ctx DBContext, doer *User, uid, repoID int64) error {
return deleteRepository(ctx.e, doer, uid, repoID)
}

func deleteRepository(e Engine, doer *User, uid, repoID int64) error {
// In case is a organization.
org, err := GetUserByID(uid)
org, err := getUserByID(e, uid)
if err != nil {
return err
}
if org.IsOrganization() {
if err = org.GetTeams(&SearchTeamOptions{}); err != nil {
if err = org.getTeams(e); err != nil {
return err
}
}

sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}

repo := &Repository{ID: repoID, OwnerID: uid}
has, err := sess.Get(repo)
repo := &Repository{OwnerID: uid}
has, err := e.ID(repoID).Get(repo)
if err != nil {
return err
} else if !has {
return ErrRepoNotExist{repoID, uid, "", ""}
}

// Delete Deploy Keys
deployKeys, err := listDeployKeys(sess, repo.ID, ListOptions{})
deployKeys, err := listDeployKeys(e, repo.ID, ListOptions{})
if err != nil {
return fmt.Errorf("listDeployKeys: %v", err)
}
for _, dKey := range deployKeys {
if err := deleteDeployKey(sess, doer, dKey.ID); err != nil {
if err := deleteDeployKey(e, doer, dKey.ID); err != nil {
return fmt.Errorf("deleteDeployKeys: %v", err)
}
}

if cnt, err := sess.ID(repoID).Delete(&Repository{}); err != nil {
if cnt, err := e.ID(repoID).Delete(&Repository{}); err != nil {
return err
} else if cnt != 1 {
return ErrRepoNotExist{repoID, uid, "", ""}
}

if org.IsOrganization() {
for _, t := range org.Teams {
if !t.hasRepository(sess, repoID) {
if !t.hasRepository(e, repoID) {
continue
} else if err = t.removeRepository(sess, repo, false); err != nil {
} else if err = t.removeRepository(e, repo, false); err != nil {
return err
}
}
}

attachments := make([]*Attachment, 0, 20)
if err = sess.Join("INNER", "`release`", "`release`.id = `attachment`.release_id").
if err = e.Join("INNER", "`release`", "`release`.id = `attachment`.release_id").
Where("`release`.repo_id = ?", repoID).
Find(&attachments); err != nil {
return err
Expand All @@ -1575,11 +1597,11 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
releaseAttachments = append(releaseAttachments, attachments[i].RelativePath())
}

if _, err = sess.Exec("UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repo.ID); err != nil {
if _, err = e.Exec("UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repo.ID); err != nil {
return err
}

if err = deleteBeans(sess,
if err = deleteBeans(e,
&Access{RepoID: repo.ID},
&Action{RepoID: repo.ID},
&Watch{RepoID: repoID},
Expand All @@ -1605,92 +1627,79 @@ func DeleteRepository(doer *User, uid, repoID int64) error {

// Delete Issues and related objects
var attachmentPaths []string
if attachmentPaths, err = deleteIssuesByRepoID(sess, repoID); err != nil {
if attachmentPaths, err = deleteIssuesByRepoID(e, repoID); err != nil {
return err
}

if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
if _, err = e.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
return err
}

if repo.IsFork {
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
if _, err = e.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
return fmt.Errorf("decrease fork count: %v", err)
}
}

if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
if _, err = e.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
return err
}

if len(repo.Topics) > 0 {
if err = removeTopicsFromRepo(sess, repo.ID); err != nil {
if err = removeTopicsFromRepo(e, repo.ID); err != nil {
return err
}
}

projects, _, err := getProjects(sess, ProjectSearchOptions{
projects, _, err := getProjects(e, ProjectSearchOptions{
RepoID: repoID,
})
if err != nil {
return fmt.Errorf("get projects: %v", err)
}
for i := range projects {
if err := deleteProjectByID(sess, projects[i].ID); err != nil {
if err := deleteProjectByID(e, projects[i].ID); err != nil {
return fmt.Errorf("delete project [%d]: %v", projects[i].ID, err)
}
}

// FIXME: Remove repository files should be executed after transaction succeed.
repoPath := repo.RepoPath()
removeAllWithNotice(sess, "Delete repository files", repoPath)
removeAllWithNotice(e, "Delete repository files", repoPath)

err = repo.deleteWiki(sess)
err = repo.deleteWiki(e)
if err != nil {
return err
}

// Remove LFS objects
var lfsObjects []*LFSMetaObject
if err = sess.Where("repository_id=?", repoID).Find(&lfsObjects); err != nil {
if err = e.Where("repository_id=?", repoID).Find(&lfsObjects); err != nil {
return err
}

for _, v := range lfsObjects {
count, err := sess.Count(&LFSMetaObject{Oid: v.Oid})
count, err := e.Count(&LFSMetaObject{Oid: v.Oid})
if err != nil {
return err
}
if count > 1 {
continue
}

removeStorageWithNotice(sess, storage.LFS, "Delete orphaned LFS file", v.RelativePath())
removeStorageWithNotice(e, storage.LFS, "Delete orphaned LFS file", v.RelativePath())
}

if _, err := sess.Delete(&LFSMetaObject{RepositoryID: repoID}); err != nil {
if _, err := e.Delete(&LFSMetaObject{RepositoryID: repoID}); err != nil {
return err
}

if repo.NumForks > 0 {
if _, err = sess.Exec("UPDATE `repository` SET fork_id=0,is_fork=? WHERE fork_id=?", false, repo.ID); err != nil {
if _, err = e.Exec("UPDATE `repository` SET fork_id=0,is_fork=? WHERE fork_id=?", false, repo.ID); err != nil {
log.Error("reset 'fork_id' and 'is_fork': %v", err)
}
}

if err = sess.Commit(); err != nil {
sess.Close()
if len(deployKeys) > 0 {
// We need to rewrite the public keys because the commit failed
if err2 := RewriteAllPublicKeys(); err2 != nil {
return fmt.Errorf("Commit: %v SSH Keys: %v", err, err2)
}
}
return fmt.Errorf("Commit: %v", err)
}

sess.Close()

// We should always delete the files after the database transaction succeed. If
// we delete the file but the database rollback, the repository will be borken.
6543 marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
11 changes: 9 additions & 2 deletions modules/repository/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (*mod
opts.DefaultBranch = setting.Repository.DefaultBranch
}

// Check if label template exist
if len(opts.IssueLabels) > 0 {
if _, err := models.GetLabelTemplateFile(opts.IssueLabels); err != nil {
return nil, err
}
}

repo := &models.Repository{
OwnerID: u.ID,
Owner: u,
Expand Down Expand Up @@ -88,7 +95,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (*mod
// Initialize Issue Labels if selected
if len(opts.IssueLabels) > 0 {
if err := models.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != nil {
if errDelete := models.DeleteRepositoryWithContext(ctx, doer, u.ID, repo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
}
return fmt.Errorf("InitializeLabels: %v", err)
Expand All @@ -99,7 +106,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (*mod
SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)).
RunInDir(repoPath); err != nil {
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != nil {
if errDelete := models.DeleteRepositoryWithContext(ctx, doer, u.ID, repo.ID); errDelete != nil {
log.Error("Rollback deleteRepository: %v", errDelete)
}
return fmt.Errorf("CreateRepository(git update-server-info): %v", err)
Expand Down
2 changes: 1 addition & 1 deletion modules/structs/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ type CreateRepoOption struct {
Description string `json:"description" binding:"MaxSize(255)"`
// Whether the repository is private
Private bool `json:"private"`
// Issue Label set to use
// Label-Set to use
IssueLabels string `json:"issue_labels"`
// Whether the repository should be auto-intialized?
AutoInit bool `json:"auto_init"`
Expand Down
2 changes: 1 addition & 1 deletion templates/swagger/v1_json.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12488,7 +12488,7 @@
"x-go-name": "Gitignores"
},
"issue_labels": {
"description": "Issue Label set to use",
"description": "Label-Set to use",
"type": "string",
"x-go-name": "IssueLabels"
},
Expand Down