Move PushUpdateAddDeleteTags to repository module from models (#10106)
* Move PushUpdateAddDeleteTags to repository module from models * Fix deadlock on sqlite
This commit is contained in:
		
							parent
							
								
									e959d1a48b
								
							
						
					
					
						commit
						48ce135cc9
					
				| @ -10,6 +10,19 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // env keys for git hooks need
 | ||||
| const ( | ||||
| 	EnvRepoName     = "GITEA_REPO_NAME" | ||||
| 	EnvRepoUsername = "GITEA_REPO_USER_NAME" | ||||
| 	EnvRepoIsWiki   = "GITEA_REPO_IS_WIKI" | ||||
| 	EnvPusherName   = "GITEA_PUSHER_NAME" | ||||
| 	EnvPusherEmail  = "GITEA_PUSHER_EMAIL" | ||||
| 	EnvPusherID     = "GITEA_PUSHER_ID" | ||||
| 	EnvKeyID        = "GITEA_KEY_ID" | ||||
| 	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY" | ||||
| 	EnvIsInternal   = "GITEA_INTERNAL_PUSH" | ||||
| ) | ||||
| 
 | ||||
| // InternalPushingEnvironment returns an os environment to switch off hooks on push
 | ||||
| // It is recommended to avoid using this unless you are pushing within a transaction
 | ||||
| // or if you absolutely are sure that post-receive and pre-receive will do nothing
 | ||||
|  | ||||
| @ -119,9 +119,15 @@ func InsertRelease(rel *Release) error { | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // InsertReleasesContext insert releases
 | ||||
| func InsertReleasesContext(ctx DBContext, rels []*Release) error { | ||||
| 	_, err := ctx.e.Insert(rels) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // UpdateRelease updates all columns of a release
 | ||||
| func UpdateRelease(rel *Release) error { | ||||
| 	_, err := x.ID(rel.ID).AllCols().Update(rel) | ||||
| func UpdateRelease(ctx DBContext, rel *Release) error { | ||||
| 	_, err := ctx.e.ID(rel.ID).AllCols().Update(rel) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| @ -212,10 +218,10 @@ func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, er | ||||
| } | ||||
| 
 | ||||
| // GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
 | ||||
| func GetReleasesByRepoIDAndNames(repoID int64, tagNames []string) (rels []*Release, err error) { | ||||
| 	err = x. | ||||
| 		Desc("created_unix"). | ||||
| func GetReleasesByRepoIDAndNames(ctx DBContext, repoID int64, tagNames []string) (rels []*Release, err error) { | ||||
| 	err = ctx.e. | ||||
| 		In("tag_name", tagNames). | ||||
| 		Desc("created_unix"). | ||||
| 		Find(&rels, Release{RepoID: repoID}) | ||||
| 	return rels, err | ||||
| } | ||||
|  | ||||
							
								
								
									
										158
									
								
								models/update.go
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								models/update.go
									
									
									
									
									
								
							| @ -7,42 +7,8 @@ package models | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| ) | ||||
| 
 | ||||
| // env keys for git hooks need
 | ||||
| const ( | ||||
| 	EnvRepoName     = "GITEA_REPO_NAME" | ||||
| 	EnvRepoUsername = "GITEA_REPO_USER_NAME" | ||||
| 	EnvRepoIsWiki   = "GITEA_REPO_IS_WIKI" | ||||
| 	EnvPusherName   = "GITEA_PUSHER_NAME" | ||||
| 	EnvPusherEmail  = "GITEA_PUSHER_EMAIL" | ||||
| 	EnvPusherID     = "GITEA_PUSHER_ID" | ||||
| 	EnvKeyID        = "GITEA_KEY_ID" | ||||
| 	EnvIsDeployKey  = "GITEA_IS_DEPLOY_KEY" | ||||
| 	EnvIsInternal   = "GITEA_INTERNAL_PUSH" | ||||
| ) | ||||
| 
 | ||||
| // PushUpdateAddDeleteTags updates a number of added and delete tags
 | ||||
| func PushUpdateAddDeleteTags(repo *Repository, gitRepo *git.Repository, addTags, delTags []string) error { | ||||
| 	sess := x.NewSession() | ||||
| 	defer sess.Close() | ||||
| 	if err := sess.Begin(); err != nil { | ||||
| 		return fmt.Errorf("Unable to begin sess in PushUpdateDeleteTags: %v", err) | ||||
| 	} | ||||
| 	if err := pushUpdateDeleteTags(sess, repo, delTags); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := pushUpdateAddTags(sess, repo, gitRepo, addTags); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return sess.Commit() | ||||
| } | ||||
| 
 | ||||
| // PushUpdateDeleteTags updates a number of delete tags
 | ||||
| func PushUpdateDeleteTags(repo *Repository, tags []string) error { | ||||
| 	sess := x.NewSession() | ||||
| @ -57,6 +23,11 @@ func PushUpdateDeleteTags(repo *Repository, tags []string) error { | ||||
| 	return sess.Commit() | ||||
| } | ||||
| 
 | ||||
| // PushUpdateDeleteTagsContext updates a number of delete tags with context
 | ||||
| func PushUpdateDeleteTagsContext(ctx DBContext, repo *Repository, tags []string) error { | ||||
| 	return pushUpdateDeleteTags(ctx.e, repo, tags) | ||||
| } | ||||
| 
 | ||||
| func pushUpdateDeleteTags(e Engine, repo *Repository, tags []string) error { | ||||
| 	if len(tags) == 0 { | ||||
| 		return nil | ||||
| @ -111,125 +82,6 @@ func PushUpdateDeleteTag(repo *Repository, tagName string) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // PushUpdateAddTags updates a number of add tags
 | ||||
| func PushUpdateAddTags(repo *Repository, gitRepo *git.Repository, tags []string) error { | ||||
| 	sess := x.NewSession() | ||||
| 	defer sess.Close() | ||||
| 	if err := sess.Begin(); err != nil { | ||||
| 		return fmt.Errorf("Unable to begin sess in PushUpdateAddTags: %v", err) | ||||
| 	} | ||||
| 	if err := pushUpdateAddTags(sess, repo, gitRepo, tags); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return sess.Commit() | ||||
| } | ||||
| func pushUpdateAddTags(e Engine, repo *Repository, gitRepo *git.Repository, tags []string) error { | ||||
| 	if len(tags) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	lowerTags := make([]string, 0, len(tags)) | ||||
| 	for _, tag := range tags { | ||||
| 		lowerTags = append(lowerTags, strings.ToLower(tag)) | ||||
| 	} | ||||
| 
 | ||||
| 	releases := make([]Release, 0, len(tags)) | ||||
| 	if err := e.Where("repo_id = ?", repo.ID). | ||||
| 		In("lower_tag_name", lowerTags).Find(&releases); err != nil { | ||||
| 		return fmt.Errorf("GetRelease: %v", err) | ||||
| 	} | ||||
| 	relMap := make(map[string]*Release) | ||||
| 	for _, rel := range releases { | ||||
| 		relMap[rel.LowerTagName] = &rel | ||||
| 	} | ||||
| 
 | ||||
| 	newReleases := make([]*Release, 0, len(lowerTags)-len(relMap)) | ||||
| 
 | ||||
| 	emailToUser := make(map[string]*User) | ||||
| 
 | ||||
| 	for i, lowerTag := range lowerTags { | ||||
| 		tag, err := gitRepo.GetTag(tags[i]) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("GetTag: %v", err) | ||||
| 		} | ||||
| 		commit, err := tag.Commit() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("Commit: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		sig := tag.Tagger | ||||
| 		if sig == nil { | ||||
| 			sig = commit.Author | ||||
| 		} | ||||
| 		if sig == nil { | ||||
| 			sig = commit.Committer | ||||
| 		} | ||||
| 		var author *User | ||||
| 		var createdAt = time.Unix(1, 0) | ||||
| 
 | ||||
| 		if sig != nil { | ||||
| 			var ok bool | ||||
| 			author, ok = emailToUser[sig.Email] | ||||
| 			if !ok { | ||||
| 				author, err = GetUserByEmail(sig.Email) | ||||
| 				if err != nil && !IsErrUserNotExist(err) { | ||||
| 					return fmt.Errorf("GetUserByEmail: %v", err) | ||||
| 				} | ||||
| 			} | ||||
| 			createdAt = sig.When | ||||
| 		} | ||||
| 
 | ||||
| 		commitsCount, err := commit.CommitsCount() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("CommitsCount: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		rel, has := relMap[lowerTag] | ||||
| 
 | ||||
| 		if !has { | ||||
| 			rel = &Release{ | ||||
| 				RepoID:       repo.ID, | ||||
| 				Title:        "", | ||||
| 				TagName:      tags[i], | ||||
| 				LowerTagName: lowerTag, | ||||
| 				Target:       "", | ||||
| 				Sha1:         commit.ID.String(), | ||||
| 				NumCommits:   commitsCount, | ||||
| 				Note:         "", | ||||
| 				IsDraft:      false, | ||||
| 				IsPrerelease: false, | ||||
| 				IsTag:        true, | ||||
| 				CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()), | ||||
| 			} | ||||
| 			if author != nil { | ||||
| 				rel.PublisherID = author.ID | ||||
| 			} | ||||
| 
 | ||||
| 			newReleases = append(newReleases, rel) | ||||
| 		} else { | ||||
| 			rel.Sha1 = commit.ID.String() | ||||
| 			rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix()) | ||||
| 			rel.NumCommits = commitsCount | ||||
| 			rel.IsDraft = false | ||||
| 			if rel.IsTag && author != nil { | ||||
| 				rel.PublisherID = author.ID | ||||
| 			} | ||||
| 			if _, err = e.ID(rel.ID).AllCols().Update(rel); err != nil { | ||||
| 				return fmt.Errorf("Update: %v", err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(newReleases) > 0 { | ||||
| 		if _, err := e.Insert(newReleases); err != nil { | ||||
| 			return fmt.Errorf("Insert: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SaveOrUpdateTag must be called for any push actions to add tag
 | ||||
| func SaveOrUpdateTag(repo *Repository, newRel *Release) error { | ||||
| 	rel, err := GetRelease(repo.ID, newRel.TagName) | ||||
|  | ||||
| @ -1452,6 +1452,11 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List { | ||||
| 
 | ||||
| // GetUserByEmail returns the user object by given e-mail if exists.
 | ||||
| func GetUserByEmail(email string) (*User, error) { | ||||
| 	return GetUserByEmailContext(DefaultDBContext(), email) | ||||
| } | ||||
| 
 | ||||
| // GetUserByEmailContext returns the user object by given e-mail if exists with db context
 | ||||
| func GetUserByEmailContext(ctx DBContext, email string) (*User, error) { | ||||
| 	if len(email) == 0 { | ||||
| 		return nil, ErrUserNotExist{0, email, 0} | ||||
| 	} | ||||
| @ -1459,7 +1464,7 @@ func GetUserByEmail(email string) (*User, error) { | ||||
| 	email = strings.ToLower(email) | ||||
| 	// First try to find the user by primary email
 | ||||
| 	user := &User{Email: email} | ||||
| 	has, err := x.Get(user) | ||||
| 	has, err := ctx.e.Get(user) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -1469,19 +1474,19 @@ func GetUserByEmail(email string) (*User, error) { | ||||
| 
 | ||||
| 	// Otherwise, check in alternative list for activated email addresses
 | ||||
| 	emailAddress := &EmailAddress{Email: email, IsActivated: true} | ||||
| 	has, err = x.Get(emailAddress) | ||||
| 	has, err = ctx.e.Get(emailAddress) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if has { | ||||
| 		return GetUserByID(emailAddress.UID) | ||||
| 		return getUserByID(ctx.e, emailAddress.UID) | ||||
| 	} | ||||
| 
 | ||||
| 	// Finally, if email address is the protected email address:
 | ||||
| 	if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) { | ||||
| 		username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) | ||||
| 		user := &User{LowerName: username} | ||||
| 		has, err := x.Get(user) | ||||
| 		has, err := ctx.e.Get(user) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| @ -732,7 +732,7 @@ func createCommitRepoActions(repo *models.Repository, gitRepo *git.Repository, o | ||||
| 			Commits:           commits, | ||||
| 		}) | ||||
| 	} | ||||
| 	if err := models.PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil { | ||||
| 	if err := repo_module.PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil { | ||||
| 		return nil, fmt.Errorf("PushUpdateAddDeleteTags: %v", err) | ||||
| 	} | ||||
| 	return actions, nil | ||||
|  | ||||
							
								
								
									
										134
									
								
								modules/repository/update.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								modules/repository/update.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,134 @@ | ||||
| // Copyright 2020 The Gitea Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a MIT-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package repository | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| ) | ||||
| 
 | ||||
| // PushUpdateAddDeleteTags updates a number of added and delete tags
 | ||||
| func PushUpdateAddDeleteTags(repo *models.Repository, gitRepo *git.Repository, addTags, delTags []string) error { | ||||
| 	return models.WithTx(func(ctx models.DBContext) error { | ||||
| 		if err := models.PushUpdateDeleteTagsContext(ctx, repo, delTags); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return pushUpdateAddTags(ctx, repo, gitRepo, addTags) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // pushUpdateAddTags updates a number of add tags
 | ||||
| func pushUpdateAddTags(ctx models.DBContext, repo *models.Repository, gitRepo *git.Repository, tags []string) error { | ||||
| 	if len(tags) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	lowerTags := make([]string, 0, len(tags)) | ||||
| 	for _, tag := range tags { | ||||
| 		lowerTags = append(lowerTags, strings.ToLower(tag)) | ||||
| 	} | ||||
| 
 | ||||
| 	releases, err := models.GetReleasesByRepoIDAndNames(ctx, repo.ID, lowerTags) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("GetReleasesByRepoIDAndNames: %v", err) | ||||
| 	} | ||||
| 	relMap := make(map[string]*models.Release) | ||||
| 	for _, rel := range releases { | ||||
| 		relMap[rel.LowerTagName] = rel | ||||
| 	} | ||||
| 
 | ||||
| 	newReleases := make([]*models.Release, 0, len(lowerTags)-len(relMap)) | ||||
| 
 | ||||
| 	emailToUser := make(map[string]*models.User) | ||||
| 
 | ||||
| 	for i, lowerTag := range lowerTags { | ||||
| 		tag, err := gitRepo.GetTag(tags[i]) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("GetTag: %v", err) | ||||
| 		} | ||||
| 		commit, err := tag.Commit() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("Commit: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		sig := tag.Tagger | ||||
| 		if sig == nil { | ||||
| 			sig = commit.Author | ||||
| 		} | ||||
| 		if sig == nil { | ||||
| 			sig = commit.Committer | ||||
| 		} | ||||
| 		var author *models.User | ||||
| 		var createdAt = time.Unix(1, 0) | ||||
| 
 | ||||
| 		if sig != nil { | ||||
| 			var ok bool | ||||
| 			author, ok = emailToUser[sig.Email] | ||||
| 			if !ok { | ||||
| 				author, err = models.GetUserByEmailContext(ctx, sig.Email) | ||||
| 				if err != nil && !models.IsErrUserNotExist(err) { | ||||
| 					return fmt.Errorf("GetUserByEmail: %v", err) | ||||
| 				} | ||||
| 				if author != nil { | ||||
| 					emailToUser[sig.Email] = author | ||||
| 				} | ||||
| 			} | ||||
| 			createdAt = sig.When | ||||
| 		} | ||||
| 
 | ||||
| 		commitsCount, err := commit.CommitsCount() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("CommitsCount: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		rel, has := relMap[lowerTag] | ||||
| 
 | ||||
| 		if !has { | ||||
| 			rel = &models.Release{ | ||||
| 				RepoID:       repo.ID, | ||||
| 				Title:        "", | ||||
| 				TagName:      tags[i], | ||||
| 				LowerTagName: lowerTag, | ||||
| 				Target:       "", | ||||
| 				Sha1:         commit.ID.String(), | ||||
| 				NumCommits:   commitsCount, | ||||
| 				Note:         "", | ||||
| 				IsDraft:      false, | ||||
| 				IsPrerelease: false, | ||||
| 				IsTag:        true, | ||||
| 				CreatedUnix:  timeutil.TimeStamp(createdAt.Unix()), | ||||
| 			} | ||||
| 			if author != nil { | ||||
| 				rel.PublisherID = author.ID | ||||
| 			} | ||||
| 
 | ||||
| 			newReleases = append(newReleases, rel) | ||||
| 		} else { | ||||
| 			rel.Sha1 = commit.ID.String() | ||||
| 			rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix()) | ||||
| 			rel.NumCommits = commitsCount | ||||
| 			rel.IsDraft = false | ||||
| 			if rel.IsTag && author != nil { | ||||
| 				rel.PublisherID = author.ID | ||||
| 			} | ||||
| 			if err = models.UpdateRelease(ctx, rel); err != nil { | ||||
| 				return fmt.Errorf("Update: %v", err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(newReleases) > 0 { | ||||
| 		if err = models.InsertReleasesContext(ctx, newReleases); err != nil { | ||||
| 			return fmt.Errorf("Insert: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| @ -420,7 +420,7 @@ func RedirectDownload(ctx *context.Context) { | ||||
| 	) | ||||
| 	tagNames := []string{vTag} | ||||
| 	curRepo := ctx.Repo.Repository | ||||
| 	releases, err := models.GetReleasesByRepoIDAndNames(curRepo.ID, tagNames) | ||||
| 	releases, err := models.GetReleasesByRepoIDAndNames(models.DefaultDBContext(), curRepo.ID, tagNames) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrAttachmentNotExist(err) { | ||||
| 			ctx.Error(404) | ||||
|  | ||||
| @ -102,7 +102,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea | ||||
| 	} | ||||
| 	rel.LowerTagName = strings.ToLower(rel.TagName) | ||||
| 
 | ||||
| 	if err = models.UpdateRelease(rel); err != nil { | ||||
| 	if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| @ -145,7 +145,7 @@ func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error { | ||||
| 		rel.Title = "" | ||||
| 		rel.Note = "" | ||||
| 
 | ||||
| 		if err = models.UpdateRelease(rel); err != nil { | ||||
| 		if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil { | ||||
| 			return fmt.Errorf("Update: %v", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user