mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Move some functions into services/repository (#17677)
This commit is contained in:
		@@ -6,6 +6,7 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
@@ -15,6 +16,95 @@ import (
 | 
			
		||||
	pull_service "code.gitea.io/gitea/services/pull"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CreateNewBranch creates a new repository branch
 | 
			
		||||
func CreateNewBranch(doer *models.User, repo *models.Repository, oldBranchName, branchName string) (err error) {
 | 
			
		||||
	// Check if branch name can be used
 | 
			
		||||
	if err := checkBranchName(repo, branchName); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !git.IsBranchExist(repo.RepoPath(), oldBranchName) {
 | 
			
		||||
		return models.ErrBranchDoesNotExist{
 | 
			
		||||
			BranchName: oldBranchName,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := git.Push(repo.RepoPath(), git.PushOptions{
 | 
			
		||||
		Remote: repo.RepoPath(),
 | 
			
		||||
		Branch: fmt.Sprintf("%s:%s%s", oldBranchName, git.BranchPrefix, branchName),
 | 
			
		||||
		Env:    models.PushingEnvironment(doer, repo),
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return fmt.Errorf("Push: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetBranches returns branches from the repository, skipping skip initial branches and
 | 
			
		||||
// returning at most limit branches, or all branches if limit is 0.
 | 
			
		||||
func GetBranches(repo *models.Repository, skip, limit int) ([]*git.Branch, int, error) {
 | 
			
		||||
	return git.GetBranchesByPath(repo.RepoPath(), skip, limit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// checkBranchName validates branch name with existing repository branches
 | 
			
		||||
func checkBranchName(repo *models.Repository, name string) error {
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	branches, _, err := GetBranches(repo, 0, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, branch := range branches {
 | 
			
		||||
		if branch.Name == name {
 | 
			
		||||
			return models.ErrBranchAlreadyExists{
 | 
			
		||||
				BranchName: branch.Name,
 | 
			
		||||
			}
 | 
			
		||||
		} else if (len(branch.Name) < len(name) && branch.Name+"/" == name[0:len(branch.Name)+1]) ||
 | 
			
		||||
			(len(branch.Name) > len(name) && name+"/" == branch.Name[0:len(name)+1]) {
 | 
			
		||||
			return models.ErrBranchNameConflict{
 | 
			
		||||
				BranchName: branch.Name,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := gitRepo.GetTag(name); err == nil {
 | 
			
		||||
		return models.ErrTagAlreadyExists{
 | 
			
		||||
			TagName: name,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateNewBranchFromCommit creates a new repository branch
 | 
			
		||||
func CreateNewBranchFromCommit(doer *models.User, repo *models.Repository, commit, branchName string) (err error) {
 | 
			
		||||
	// Check if branch name can be used
 | 
			
		||||
	if err := checkBranchName(repo, branchName); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := git.Push(repo.RepoPath(), git.PushOptions{
 | 
			
		||||
		Remote: repo.RepoPath(),
 | 
			
		||||
		Branch: fmt.Sprintf("%s:%s%s", commit, git.BranchPrefix, branchName),
 | 
			
		||||
		Env:    models.PushingEnvironment(doer, repo),
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return fmt.Errorf("Push: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RenameBranch rename a branch
 | 
			
		||||
func RenameBranch(repo *models.Repository, doer *models.User, gitRepo *git.Repository, from, to string) (string, error) {
 | 
			
		||||
	if from == to {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								services/repository/cache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								services/repository/cache.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// 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 (
 | 
			
		||||
	"context"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/modules/cache"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getRefName(fullRefName string) string {
 | 
			
		||||
	if strings.HasPrefix(fullRefName, git.TagPrefix) {
 | 
			
		||||
		return fullRefName[len(git.TagPrefix):]
 | 
			
		||||
	} else if strings.HasPrefix(fullRefName, git.BranchPrefix) {
 | 
			
		||||
		return fullRefName[len(git.BranchPrefix):]
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CacheRef cachhe last commit information of the branch or the tag
 | 
			
		||||
func CacheRef(ctx context.Context, repo *models.Repository, gitRepo *git.Repository, fullRefName string) error {
 | 
			
		||||
	if !setting.CacheService.LastCommit.Enabled {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commit, err := gitRepo.GetCommit(fullRefName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commitsCount, err := cache.GetInt64(repo.GetCommitsCountCacheKey(getRefName(fullRefName), true), commit.CommitsCount)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if commitsCount < setting.CacheService.LastCommit.CommitsCount {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commitCache := git.NewLastCommitCache(repo.FullName(), gitRepo, setting.LastCommitCacheTTLSeconds, cache.GetCache())
 | 
			
		||||
 | 
			
		||||
	return commitCache.CacheCommit(ctx, commit)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								services/repository/hooks.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								services/repository/hooks.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
// Copyright 2021 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 (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/builder"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SyncRepositoryHooks rewrites all repositories' pre-receive, update and post-receive hooks
 | 
			
		||||
// to make sure the binary and custom conf path are up-to-date.
 | 
			
		||||
func SyncRepositoryHooks(ctx context.Context) error {
 | 
			
		||||
	log.Trace("Doing: SyncRepositoryHooks")
 | 
			
		||||
 | 
			
		||||
	if err := db.Iterate(
 | 
			
		||||
		db.DefaultContext,
 | 
			
		||||
		new(models.Repository),
 | 
			
		||||
		builder.Gt{"id": 0},
 | 
			
		||||
		func(idx int, bean interface{}) error {
 | 
			
		||||
			repo := bean.(*models.Repository)
 | 
			
		||||
			select {
 | 
			
		||||
			case <-ctx.Done():
 | 
			
		||||
				return db.ErrCancelledf("before sync repository hooks for %s", repo.FullName())
 | 
			
		||||
			default:
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err := repo_module.CreateDelegateHooks(repo.RepoPath()); err != nil {
 | 
			
		||||
				return fmt.Errorf("SyncRepositoryHook: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			if repo.HasWiki() {
 | 
			
		||||
				if err := repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
 | 
			
		||||
					return fmt.Errorf("SyncRepositoryHook: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Finished: SyncRepositoryHooks")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -5,8 +5,10 @@
 | 
			
		||||
package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
@@ -20,6 +22,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/repofiles"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
			
		||||
	pull_service "code.gitea.io/gitea/services/pull"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +213,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Cache for big repository
 | 
			
		||||
				if err := repo_module.CacheRef(graceful.GetManager().HammerContext(), repo, gitRepo, opts.RefFullName); err != nil {
 | 
			
		||||
				if err := CacheRef(graceful.GetManager().HammerContext(), repo, gitRepo, opts.RefFullName); err != nil {
 | 
			
		||||
					log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
@@ -229,7 +232,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
 | 
			
		||||
			log.Trace("Non-tag and non-branch commits pushed.")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err := repo_module.PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil {
 | 
			
		||||
	if err := PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil {
 | 
			
		||||
		return fmt.Errorf("PushUpdateAddDeleteTags: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -240,3 +243,122 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PushUpdateAddDeleteTags updates a number of added and delete tags
 | 
			
		||||
func PushUpdateAddDeleteTags(repo *models.Repository, gitRepo *git.Repository, addTags, delTags []string) error {
 | 
			
		||||
	return db.WithTx(func(ctx context.Context) 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 context.Context, 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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user