Move some functions into services/repository (#17677)
This commit is contained in:
parent
750a8465f5
commit
5233051e64
15 changed files with 283 additions and 285 deletions
|
@ -25,6 +25,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
auth_service "code.gitea.io/gitea/services/auth"
|
auth_service "code.gitea.io/gitea/services/auth"
|
||||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||||
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
@ -612,7 +613,7 @@ func runRegenerateHooks(_ *cli.Context) error {
|
||||||
if err := initDB(ctx); err != nil {
|
if err := initDB(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return repo_module.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRegenerateKeys(_ *cli.Context) error {
|
func runRegenerateKeys(_ *cli.Context) error {
|
||||||
|
|
|
@ -13,9 +13,9 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
|
||||||
|
|
||||||
// Make a new branch in repo1
|
// Make a new branch in repo1
|
||||||
newBranch := "test_branch"
|
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)
|
assert.NoError(t, err)
|
||||||
// Get the commit ID of the default branch
|
// Get the commit ID of the default branch
|
||||||
gitRepo, err := git.OpenRepository(repo1.RepoPath())
|
gitRepo, err := git.OpenRepository(repo1.RepoPath())
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -73,7 +73,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
|
||||||
|
|
||||||
// Make a new branch in repo1
|
// Make a new branch in repo1
|
||||||
newBranch := "test_branch"
|
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)
|
assert.NoError(t, err)
|
||||||
// Get the commit ID of the default branch
|
// Get the commit ID of the default branch
|
||||||
gitRepo, err := git.OpenRepository(repo1.RepoPath())
|
gitRepo, err := git.OpenRepository(repo1.RepoPath())
|
||||||
|
|
|
@ -24,92 +24,3 @@ func GetBranch(repo *models.Repository, branch string) (*git.Branch, error) {
|
||||||
|
|
||||||
return gitRepo.GetBranch(branch)
|
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
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getHookTemplates() (hookNames, hookTpls, giteaHookTpls []string) {
|
func getHookTemplates() (hookNames, hookTpls, giteaHookTpls []string) {
|
||||||
|
@ -240,38 +234,3 @@ func CheckDelegateHooks(repoPath string) ([]string, error) {
|
||||||
}
|
}
|
||||||
return results, nil
|
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
|
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 err != nil {
|
||||||
if models.IsErrBranchDoesNotExist(err) {
|
if models.IsErrBranchDoesNotExist(err) {
|
||||||
|
@ -257,7 +257,7 @@ func ListBranches(ctx *context.APIContext) {
|
||||||
|
|
||||||
listOptions := utils.GetListOptions(ctx)
|
listOptions := utils.GetListOptions(ctx)
|
||||||
skip, _ := listOptions.GetStartEnd()
|
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 {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetBranches", err)
|
ctx.Error(http.StatusInternalServerError, "GetBranches", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/markup/external"
|
"code.gitea.io/gitea/modules/markup/external"
|
||||||
"code.gitea.io/gitea/modules/notification"
|
"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/setting"
|
||||||
"code.gitea.io/gitea/modules/ssh"
|
"code.gitea.io/gitea/modules/ssh"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
@ -45,7 +44,7 @@ import (
|
||||||
repo_migrations "code.gitea.io/gitea/services/migrations"
|
repo_migrations "code.gitea.io/gitea/services/migrations"
|
||||||
mirror_service "code.gitea.io/gitea/services/mirror"
|
mirror_service "code.gitea.io/gitea/services/mirror"
|
||||||
pull_service "code.gitea.io/gitea/services/pull"
|
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"
|
"code.gitea.io/gitea/services/webhook"
|
||||||
|
|
||||||
"gitea.com/go-chi/session"
|
"gitea.com/go-chi/session"
|
||||||
|
@ -73,7 +72,7 @@ func mustInitCtx(ctx context.Context, fn func(ctx context.Context) error) {
|
||||||
func InitGitServices() {
|
func InitGitServices() {
|
||||||
setting.NewServices()
|
setting.NewServices()
|
||||||
mustInit(storage.Init)
|
mustInit(storage.Init)
|
||||||
mustInit(repository.NewContext)
|
mustInit(repo_service.NewContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncAppPathForGit(ctx context.Context) error {
|
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("AppPath changed from '%s' to '%s'", runtimeState.LastAppPath, setting.AppPath)
|
||||||
|
|
||||||
log.Info("re-sync repository hooks ...")
|
log.Info("re-sync repository hooks ...")
|
||||||
mustInitCtx(ctx, repo_module.SyncRepositoryHooks)
|
mustInitCtx(ctx, repo_service.SyncRepositoryHooks)
|
||||||
|
|
||||||
log.Info("re-write ssh public keys ...")
|
log.Info("re-write ssh public keys ...")
|
||||||
mustInit(models.RewriteAllPublicKeys)
|
mustInit(models.RewriteAllPublicKeys)
|
||||||
|
|
|
@ -171,7 +171,7 @@ func loadBranches(ctx *context.Context, skip, limit int) ([]*Branch, int) {
|
||||||
return nil, 0
|
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 {
|
if err != nil {
|
||||||
log.Error("GetBranches: %v", err)
|
log.Error("GetBranches: %v", err)
|
||||||
ctx.ServerError("GetBranches", 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, "")
|
err = release_service.CreateNewTag(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName, "")
|
||||||
}
|
}
|
||||||
} else if ctx.Repo.IsViewBranch {
|
} 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 {
|
} 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 {
|
} 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 err != nil {
|
||||||
if models.IsErrTagAlreadyExists(err) {
|
if models.IsErrTagAlreadyExists(err) {
|
||||||
|
|
|
@ -85,7 +85,7 @@ func registerRepositoryUpdateHook() {
|
||||||
RunAtStart: false,
|
RunAtStart: false,
|
||||||
Schedule: "@every 72h",
|
Schedule: "@every 72h",
|
||||||
}, func(ctx context.Context, _ *models.User, _ Config) error {
|
}, 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)
|
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 {
|
if err != nil {
|
||||||
log.Error("GetBranches: %v", err)
|
log.Error("GetBranches: %v", err)
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|
|
@ -6,6 +6,7 @@ package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -15,6 +16,95 @@ import (
|
||||||
pull_service "code.gitea.io/gitea/services/pull"
|
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
|
// RenameBranch rename a branch
|
||||||
func RenameBranch(repo *models.Repository, doer *models.User, gitRepo *git.Repository, from, to string) (string, error) {
|
func RenameBranch(repo *models.Repository, doer *models.User, gitRepo *git.Repository, from, to string) (string, error) {
|
||||||
if from == to {
|
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
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
@ -20,6 +22,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/repofiles"
|
"code.gitea.io/gitea/modules/repofiles"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
pull_service "code.gitea.io/gitea/services/pull"
|
pull_service "code.gitea.io/gitea/services/pull"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -210,7 +213,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache for big repository
|
// 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)
|
log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -229,7 +232,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||||
log.Trace("Non-tag and non-branch commits pushed.")
|
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)
|
return fmt.Errorf("PushUpdateAddDeleteTags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,3 +243,122 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||||
|
|
||||||
return nil
|
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 a new issue