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:
		@@ -25,6 +25,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/storage"
 | 
			
		||||
	auth_service "code.gitea.io/gitea/services/auth"
 | 
			
		||||
	"code.gitea.io/gitea/services/auth/source/oauth2"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
 | 
			
		||||
	"github.com/urfave/cli"
 | 
			
		||||
)
 | 
			
		||||
@@ -612,7 +613,7 @@ func runRegenerateHooks(_ *cli.Context) error {
 | 
			
		||||
	if err := initDB(ctx); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return repo_module.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
 | 
			
		||||
	return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runRegenerateKeys(_ *cli.Context) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,9 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
@@ -72,7 +72,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
 | 
			
		||||
 | 
			
		||||
	// Make a new branch in repo1
 | 
			
		||||
	newBranch := "test_branch"
 | 
			
		||||
	err := repo_module.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	err := repo_service.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	// Get the commit ID of the default branch
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo1.RepoPath())
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,9 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
@@ -73,7 +73,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
 | 
			
		||||
 | 
			
		||||
	// Make a new branch in repo1
 | 
			
		||||
	newBranch := "test_branch"
 | 
			
		||||
	err := repo_module.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	err := repo_service.CreateNewBranch(user2, repo1, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	// Get the commit ID of the default branch
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo1.RepoPath())
 | 
			
		||||
 
 | 
			
		||||
@@ -24,92 +24,3 @@ func GetBranch(repo *models.Repository, branch string) (*git.Branch, error) {
 | 
			
		||||
 | 
			
		||||
	return gitRepo.GetBranch(branch)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,19 +5,13 @@
 | 
			
		||||
package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/builder"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getHookTemplates() (hookNames, hookTpls, giteaHookTpls []string) {
 | 
			
		||||
@@ -240,38 +234,3 @@ func CheckDelegateHooks(repoPath string) ([]string, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return results, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 := createDelegateHooks(repo.RepoPath()); err != nil {
 | 
			
		||||
				return fmt.Errorf("SyncRepositoryHook: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			if repo.HasWiki() {
 | 
			
		||||
				if err := createDelegateHooks(repo.WikiPath()); err != nil {
 | 
			
		||||
					return fmt.Errorf("SyncRepositoryHook: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Finished: SyncRepositoryHooks")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,136 +0,0 @@
 | 
			
		||||
// 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"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"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 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
 | 
			
		||||
}
 | 
			
		||||
@@ -176,7 +176,7 @@ func CreateBranch(ctx *context.APIContext) {
 | 
			
		||||
		opt.OldBranchName = ctx.Repo.Repository.DefaultBranch
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := repo_module.CreateNewBranch(ctx.User, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName)
 | 
			
		||||
	err := repo_service.CreateNewBranch(ctx.User, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrBranchDoesNotExist(err) {
 | 
			
		||||
@@ -257,7 +257,7 @@ func ListBranches(ctx *context.APIContext) {
 | 
			
		||||
 | 
			
		||||
	listOptions := utils.GetListOptions(ctx)
 | 
			
		||||
	skip, _ := listOptions.GetStartEnd()
 | 
			
		||||
	branches, totalNumOfBranches, err := repo_module.GetBranches(ctx.Repo.Repository, skip, listOptions.PageSize)
 | 
			
		||||
	branches, totalNumOfBranches, err := repo_service.GetBranches(ctx.Repo.Repository, skip, listOptions.PageSize)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "GetBranches", err)
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/markup"
 | 
			
		||||
	"code.gitea.io/gitea/modules/markup/external"
 | 
			
		||||
	"code.gitea.io/gitea/modules/notification"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/ssh"
 | 
			
		||||
	"code.gitea.io/gitea/modules/storage"
 | 
			
		||||
@@ -45,7 +44,7 @@ import (
 | 
			
		||||
	repo_migrations "code.gitea.io/gitea/services/migrations"
 | 
			
		||||
	mirror_service "code.gitea.io/gitea/services/mirror"
 | 
			
		||||
	pull_service "code.gitea.io/gitea/services/pull"
 | 
			
		||||
	"code.gitea.io/gitea/services/repository"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
	"code.gitea.io/gitea/services/webhook"
 | 
			
		||||
 | 
			
		||||
	"gitea.com/go-chi/session"
 | 
			
		||||
@@ -73,7 +72,7 @@ func mustInitCtx(ctx context.Context, fn func(ctx context.Context) error) {
 | 
			
		||||
func InitGitServices() {
 | 
			
		||||
	setting.NewServices()
 | 
			
		||||
	mustInit(storage.Init)
 | 
			
		||||
	mustInit(repository.NewContext)
 | 
			
		||||
	mustInit(repo_service.NewContext)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func syncAppPathForGit(ctx context.Context) error {
 | 
			
		||||
@@ -85,7 +84,7 @@ func syncAppPathForGit(ctx context.Context) error {
 | 
			
		||||
		log.Info("AppPath changed from '%s' to '%s'", runtimeState.LastAppPath, setting.AppPath)
 | 
			
		||||
 | 
			
		||||
		log.Info("re-sync repository hooks ...")
 | 
			
		||||
		mustInitCtx(ctx, repo_module.SyncRepositoryHooks)
 | 
			
		||||
		mustInitCtx(ctx, repo_service.SyncRepositoryHooks)
 | 
			
		||||
 | 
			
		||||
		log.Info("re-write ssh public keys ...")
 | 
			
		||||
		mustInit(models.RewriteAllPublicKeys)
 | 
			
		||||
 
 | 
			
		||||
@@ -171,7 +171,7 @@ func loadBranches(ctx *context.Context, skip, limit int) ([]*Branch, int) {
 | 
			
		||||
		return nil, 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawBranches, totalNumOfBranches, err := repo_module.GetBranches(ctx.Repo.Repository, skip, limit)
 | 
			
		||||
	rawBranches, totalNumOfBranches, err := repo_service.GetBranches(ctx.Repo.Repository, skip, limit)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("GetBranches: %v", err)
 | 
			
		||||
		ctx.ServerError("GetBranches", err)
 | 
			
		||||
@@ -350,11 +350,11 @@ func CreateBranch(ctx *context.Context) {
 | 
			
		||||
			err = release_service.CreateNewTag(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName, "")
 | 
			
		||||
		}
 | 
			
		||||
	} else if ctx.Repo.IsViewBranch {
 | 
			
		||||
		err = repo_module.CreateNewBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
 | 
			
		||||
		err = repo_service.CreateNewBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
 | 
			
		||||
	} else if ctx.Repo.IsViewTag {
 | 
			
		||||
		err = repo_module.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName)
 | 
			
		||||
		err = repo_service.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName)
 | 
			
		||||
	} else {
 | 
			
		||||
		err = repo_module.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
 | 
			
		||||
		err = repo_service.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrTagAlreadyExists(err) {
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ func registerRepositoryUpdateHook() {
 | 
			
		||||
		RunAtStart: false,
 | 
			
		||||
		Schedule:   "@every 72h",
 | 
			
		||||
	}, func(ctx context.Context, _ *models.User, _ Config) error {
 | 
			
		||||
		return repo_module.SyncRepositoryHooks(ctx)
 | 
			
		||||
		return repo_service.SyncRepositoryHooks(ctx)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -333,7 +333,7 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("SyncMirrors [repo: %-v]: invalidating mirror branch caches...", m.Repo)
 | 
			
		||||
	branches, _, err := repo_module.GetBranches(m.Repo, 0, 0)
 | 
			
		||||
	branches, _, err := git.GetBranchesByPath(m.Repo.RepoPath(), 0, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("GetBranches: %v", err)
 | 
			
		||||
		return nil, false
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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