aboutsummaryrefslogtreecommitdiffstats
path: root/modules/repository
diff options
context:
space:
mode:
Diffstat (limited to 'modules/repository')
-rw-r--r--modules/repository/branch.go9
-rw-r--r--modules/repository/branch_test.go2
-rw-r--r--modules/repository/commits.go16
-rw-r--r--modules/repository/commits_test.go36
-rw-r--r--modules/repository/create.go103
-rw-r--r--modules/repository/create_test.go23
-rw-r--r--modules/repository/env.go8
-rw-r--r--modules/repository/hooks.go233
-rw-r--r--modules/repository/init.go38
-rw-r--r--modules/repository/init_test.go6
-rw-r--r--modules/repository/repo.go133
-rw-r--r--modules/repository/repo_test.go4
-rw-r--r--modules/repository/temp.go33
13 files changed, 62 insertions, 582 deletions
diff --git a/modules/repository/branch.go b/modules/repository/branch.go
index 2bf9930f19..30aa0a6e85 100644
--- a/modules/repository/branch.go
+++ b/modules/repository/branch.go
@@ -41,11 +41,12 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
if err != nil {
return 0, fmt.Errorf("GetObjectFormat: %w", err)
}
- _, err = db.GetEngine(ctx).ID(repo.ID).Update(&repo_model.Repository{ObjectFormatName: objFmt.Name()})
- if err != nil {
- return 0, fmt.Errorf("UpdateRepository: %w", err)
+ if objFmt.Name() != repo.ObjectFormatName {
+ repo.ObjectFormatName = objFmt.Name()
+ if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "object_format_name"); err != nil {
+ return 0, fmt.Errorf("UpdateRepositoryColsWithAutoTime: %w", err)
+ }
}
- repo.ObjectFormatName = objFmt.Name() // keep consistent with db
allBranches := container.Set[string]{}
{
diff --git a/modules/repository/branch_test.go b/modules/repository/branch_test.go
index acf75a1ac0..ead28aa141 100644
--- a/modules/repository/branch_test.go
+++ b/modules/repository/branch_test.go
@@ -27,5 +27,5 @@ func TestSyncRepoBranches(t *testing.T) {
assert.Equal(t, "sha1", repo.ObjectFormatName)
branch, err := git_model.GetBranch(db.DefaultContext, 1, "master")
assert.NoError(t, err)
- assert.EqualValues(t, "master", branch.Name)
+ assert.Equal(t, "master", branch.Name)
}
diff --git a/modules/repository/commits.go b/modules/repository/commits.go
index 6e4b75d5ca..878fdc1603 100644
--- a/modules/repository/commits.go
+++ b/modules/repository/commits.go
@@ -10,8 +10,10 @@ import (
"time"
"code.gitea.io/gitea/models/avatars"
+ repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
+ "code.gitea.io/gitea/modules/cachegroup"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -43,7 +45,7 @@ func NewPushCommits() *PushCommits {
}
// ToAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object.
-func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) {
+func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repo *repo_model.Repository, commit *PushCommit) (*api.PayloadCommit, error) {
var err error
authorUsername := ""
author, ok := emailUsers[commit.AuthorEmail]
@@ -70,7 +72,7 @@ func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.U
committerUsername = committer.Name
}
- fileStatus, err := git.GetCommitFileStatus(ctx, repoPath, commit.Sha1)
+ fileStatus, err := git.GetCommitFileStatus(ctx, repo.RepoPath(), commit.Sha1)
if err != nil {
return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %w", commit.Sha1, err)
}
@@ -78,7 +80,7 @@ func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.U
return &api.PayloadCommit{
ID: commit.Sha1,
Message: commit.Message,
- URL: fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(commit.Sha1)),
+ URL: fmt.Sprintf("%s/commit/%s", repo.HTMLURL(), url.PathEscape(commit.Sha1)),
Author: &api.PayloadUser{
Name: commit.AuthorName,
Email: commit.AuthorEmail,
@@ -98,14 +100,14 @@ func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.U
// ToAPIPayloadCommits converts a PushCommits object to api.PayloadCommit format.
// It returns all converted commits and, if provided, the head commit or an error otherwise.
-func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLink string) ([]*api.PayloadCommit, *api.PayloadCommit, error) {
+func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repo *repo_model.Repository) ([]*api.PayloadCommit, *api.PayloadCommit, error) {
commits := make([]*api.PayloadCommit, len(pc.Commits))
var headCommit *api.PayloadCommit
emailUsers := make(map[string]*user_model.User)
for i, commit := range pc.Commits {
- apiCommit, err := ToAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, commit)
+ apiCommit, err := ToAPIPayloadCommit(ctx, emailUsers, repo, commit)
if err != nil {
return nil, nil, err
}
@@ -117,7 +119,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
}
if pc.HeadCommit != nil && headCommit == nil {
var err error
- headCommit, err = ToAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit)
+ headCommit, err = ToAPIPayloadCommit(ctx, emailUsers, repo, pc.HeadCommit)
if err != nil {
return nil, nil, err
}
@@ -130,7 +132,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
func (pc *PushCommits) AvatarLink(ctx context.Context, email string) string {
size := avatars.DefaultAvatarPixelSize * setting.Avatar.RenderedSizeFactor
- v, _ := cache.GetWithContextCache(ctx, "push_commits", email, func() (string, error) {
+ v, _ := cache.GetWithContextCache(ctx, cachegroup.EmailAvatarLink, email, func(ctx context.Context, email string) (string, error) {
u, err := user_model.GetUserByEmail(ctx, email)
if err != nil {
if !user_model.IsErrUserNotExist(err) {
diff --git a/modules/repository/commits_test.go b/modules/repository/commits_test.go
index 3afc116e68..030cd7714d 100644
--- a/modules/repository/commits_test.go
+++ b/modules/repository/commits_test.go
@@ -50,54 +50,54 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) {
pushCommits.HeadCommit = &PushCommit{Sha1: "69554a6"}
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16})
- payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(git.DefaultContext, repo.RepoPath(), "/user2/repo16")
+ payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(git.DefaultContext, repo)
assert.NoError(t, err)
assert.Len(t, payloadCommits, 3)
assert.NotNil(t, headCommit)
assert.Equal(t, "69554a6", payloadCommits[0].ID)
assert.Equal(t, "not signed commit", payloadCommits[0].Message)
- assert.Equal(t, "/user2/repo16/commit/69554a6", payloadCommits[0].URL)
+ assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/69554a6", payloadCommits[0].URL)
assert.Equal(t, "User2", payloadCommits[0].Committer.Name)
assert.Equal(t, "user2", payloadCommits[0].Committer.UserName)
assert.Equal(t, "User2", payloadCommits[0].Author.Name)
assert.Equal(t, "user2", payloadCommits[0].Author.UserName)
- assert.EqualValues(t, []string{}, payloadCommits[0].Added)
- assert.EqualValues(t, []string{}, payloadCommits[0].Removed)
- assert.EqualValues(t, []string{"readme.md"}, payloadCommits[0].Modified)
+ assert.Equal(t, []string{}, payloadCommits[0].Added)
+ assert.Equal(t, []string{}, payloadCommits[0].Removed)
+ assert.Equal(t, []string{"readme.md"}, payloadCommits[0].Modified)
assert.Equal(t, "27566bd", payloadCommits[1].ID)
assert.Equal(t, "good signed commit (with not yet validated email)", payloadCommits[1].Message)
- assert.Equal(t, "/user2/repo16/commit/27566bd", payloadCommits[1].URL)
+ assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/27566bd", payloadCommits[1].URL)
assert.Equal(t, "User2", payloadCommits[1].Committer.Name)
assert.Equal(t, "user2", payloadCommits[1].Committer.UserName)
assert.Equal(t, "User2", payloadCommits[1].Author.Name)
assert.Equal(t, "user2", payloadCommits[1].Author.UserName)
- assert.EqualValues(t, []string{}, payloadCommits[1].Added)
- assert.EqualValues(t, []string{}, payloadCommits[1].Removed)
- assert.EqualValues(t, []string{"readme.md"}, payloadCommits[1].Modified)
+ assert.Equal(t, []string{}, payloadCommits[1].Added)
+ assert.Equal(t, []string{}, payloadCommits[1].Removed)
+ assert.Equal(t, []string{"readme.md"}, payloadCommits[1].Modified)
assert.Equal(t, "5099b81", payloadCommits[2].ID)
assert.Equal(t, "good signed commit", payloadCommits[2].Message)
- assert.Equal(t, "/user2/repo16/commit/5099b81", payloadCommits[2].URL)
+ assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/5099b81", payloadCommits[2].URL)
assert.Equal(t, "User2", payloadCommits[2].Committer.Name)
assert.Equal(t, "user2", payloadCommits[2].Committer.UserName)
assert.Equal(t, "User2", payloadCommits[2].Author.Name)
assert.Equal(t, "user2", payloadCommits[2].Author.UserName)
- assert.EqualValues(t, []string{"readme.md"}, payloadCommits[2].Added)
- assert.EqualValues(t, []string{}, payloadCommits[2].Removed)
- assert.EqualValues(t, []string{}, payloadCommits[2].Modified)
+ assert.Equal(t, []string{"readme.md"}, payloadCommits[2].Added)
+ assert.Equal(t, []string{}, payloadCommits[2].Removed)
+ assert.Equal(t, []string{}, payloadCommits[2].Modified)
assert.Equal(t, "69554a6", headCommit.ID)
assert.Equal(t, "not signed commit", headCommit.Message)
- assert.Equal(t, "/user2/repo16/commit/69554a6", headCommit.URL)
+ assert.Equal(t, "https://try.gitea.io/user2/repo16/commit/69554a6", headCommit.URL)
assert.Equal(t, "User2", headCommit.Committer.Name)
assert.Equal(t, "user2", headCommit.Committer.UserName)
assert.Equal(t, "User2", headCommit.Author.Name)
assert.Equal(t, "user2", headCommit.Author.UserName)
- assert.EqualValues(t, []string{}, headCommit.Added)
- assert.EqualValues(t, []string{}, headCommit.Removed)
- assert.EqualValues(t, []string{"readme.md"}, headCommit.Modified)
+ assert.Equal(t, []string{}, headCommit.Added)
+ assert.Equal(t, []string{}, headCommit.Removed)
+ assert.Equal(t, []string{"readme.md"}, headCommit.Modified)
}
func TestPushCommits_AvatarLink(t *testing.T) {
@@ -200,5 +200,3 @@ func TestListToPushCommits(t *testing.T) {
assert.Equal(t, now, pushCommits.Commits[1].Timestamp)
}
}
-
-// TODO TestPushUpdate
diff --git a/modules/repository/create.go b/modules/repository/create.go
index b4f7033bd7..a75598a84b 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -7,19 +7,10 @@ import (
"context"
"fmt"
"os"
- "path"
"path/filepath"
- "strings"
- activities_model "code.gitea.io/gitea/models/activities"
- "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
- access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
- issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
- "code.gitea.io/gitea/modules/log"
- api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
)
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
@@ -64,97 +55,3 @@ func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error {
return repo_model.UpdateRepoSize(ctx, repo.ID, size, lfsSize)
}
-
-// CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
-func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error {
- if err := repo.LoadOwner(ctx); err != nil {
- return err
- }
-
- // Create/Remove git-daemon-export-ok for git-daemon...
- daemonExportFile := path.Join(repo.RepoPath(), `git-daemon-export-ok`)
-
- isExist, err := util.IsExist(daemonExportFile)
- if err != nil {
- log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err)
- return err
- }
-
- isPublic := !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePublic
- if !isPublic && isExist {
- if err = util.Remove(daemonExportFile); err != nil {
- log.Error("Failed to remove %s: %v", daemonExportFile, err)
- }
- } else if isPublic && !isExist {
- if f, err := os.Create(daemonExportFile); err != nil {
- log.Error("Failed to create %s: %v", daemonExportFile, err)
- } else {
- f.Close()
- }
- }
-
- return nil
-}
-
-// UpdateRepository updates a repository with db context
-func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
- repo.LowerName = strings.ToLower(repo.Name)
-
- e := db.GetEngine(ctx)
-
- if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
- return fmt.Errorf("update: %w", err)
- }
-
- if err = UpdateRepoSize(ctx, repo); err != nil {
- log.Error("Failed to update size for repository: %v", err)
- }
-
- if visibilityChanged {
- if err = repo.LoadOwner(ctx); err != nil {
- return fmt.Errorf("LoadOwner: %w", err)
- }
- if repo.Owner.IsOrganization() {
- // Organization repository need to recalculate access table when visibility is changed.
- if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil {
- return fmt.Errorf("recalculateTeamAccesses: %w", err)
- }
- }
-
- // If repo has become private, we need to set its actions to private.
- if repo.IsPrivate {
- _, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{
- IsPrivate: true,
- })
- if err != nil {
- return err
- }
-
- if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {
- return err
- }
- }
-
- // Create/Remove git-daemon-export-ok for git-daemon...
- if err := CheckDaemonExportOK(ctx, repo); err != nil {
- return err
- }
-
- forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
- if err != nil {
- return fmt.Errorf("getRepositoriesByForkID: %w", err)
- }
- for i := range forkRepos {
- forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate
- if err = UpdateRepository(ctx, forkRepos[i], true); err != nil {
- return fmt.Errorf("updateRepository[%d]: %w", forkRepos[i].ID, err)
- }
- }
-
- // If visibility is changed, we need to update the issue indexer.
- // Since the data in the issue indexer have field to indicate if the repo is public or not.
- issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
- }
-
- return nil
-}
diff --git a/modules/repository/create_test.go b/modules/repository/create_test.go
index a9151482b4..b85a10adad 100644
--- a/modules/repository/create_test.go
+++ b/modules/repository/create_test.go
@@ -6,7 +6,6 @@ package repository
import (
"testing"
- activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
@@ -14,26 +13,6 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
-
- // Get sample repo and change visibility
- repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9)
- assert.NoError(t, err)
- repo.IsPrivate = true
-
- // Update it
- err = UpdateRepository(db.DefaultContext, repo, true)
- assert.NoError(t, err)
-
- // Check visibility of action has become private
- act := activities_model.Action{}
- _, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act)
-
- assert.NoError(t, err)
- assert.True(t, act.IsPrivate)
-}
-
func TestGetDirectorySize(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 1)
@@ -41,5 +20,5 @@ func TestGetDirectorySize(t *testing.T) {
size, err := getDirectorySize(repo.RepoPath())
assert.NoError(t, err)
repo.Size = 8165 // real size on the disk
- assert.EqualValues(t, repo.Size, size)
+ assert.Equal(t, repo.Size, size)
}
diff --git a/modules/repository/env.go b/modules/repository/env.go
index e4f32092fc..78e06f86fb 100644
--- a/modules/repository/env.go
+++ b/modules/repository/env.go
@@ -4,8 +4,8 @@
package repository
import (
- "fmt"
"os"
+ "strconv"
"strings"
repo_model "code.gitea.io/gitea/models/repo"
@@ -72,9 +72,9 @@ func FullPushingEnvironment(author, committer *user_model.User, repo *repo_model
EnvRepoUsername+"="+repo.OwnerName,
EnvRepoIsWiki+"="+isWiki,
EnvPusherName+"="+committer.Name,
- EnvPusherID+"="+fmt.Sprintf("%d", committer.ID),
- EnvRepoID+"="+fmt.Sprintf("%d", repo.ID),
- EnvPRID+"="+fmt.Sprintf("%d", prID),
+ EnvPusherID+"="+strconv.FormatInt(committer.ID, 10),
+ EnvRepoID+"="+strconv.FormatInt(repo.ID, 10),
+ EnvPRID+"="+strconv.FormatInt(prID, 10),
EnvAppURL+"="+setting.AppURL,
"SSH_ORIGINAL_COMMAND=gitea-internal",
)
diff --git a/modules/repository/hooks.go b/modules/repository/hooks.go
deleted file mode 100644
index 95849789ab..0000000000
--- a/modules/repository/hooks.go
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2020 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package repository
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "runtime"
-
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
-)
-
-func getHookTemplates() (hookNames, hookTpls, giteaHookTpls []string) {
- hookNames = []string{"pre-receive", "update", "post-receive"}
- hookTpls = []string{
- // for pre-receive
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-data=$(cat)
-exitcodes=""
-hookname=$(basename $0)
-GIT_DIR=${GIT_DIR:-$(dirname $0)/..}
-
-for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
- test -x "${hook}" && test -f "${hook}" || continue
- echo "${data}" | "${hook}"
- exitcodes="${exitcodes} $?"
-done
-
-for i in ${exitcodes}; do
- [ ${i} -eq 0 ] || exit ${i}
-done
-`, setting.ScriptType),
-
- // for update
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-exitcodes=""
-hookname=$(basename $0)
-GIT_DIR=${GIT_DIR:-$(dirname $0/..)}
-
-for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
- test -x "${hook}" && test -f "${hook}" || continue
- "${hook}" $1 $2 $3
- exitcodes="${exitcodes} $?"
-done
-
-for i in ${exitcodes}; do
- [ ${i} -eq 0 ] || exit ${i}
-done
-`, setting.ScriptType),
-
- // for post-receive
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-data=$(cat)
-exitcodes=""
-hookname=$(basename $0)
-GIT_DIR=${GIT_DIR:-$(dirname $0)/..}
-
-for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
- test -x "${hook}" && test -f "${hook}" || continue
- echo "${data}" | "${hook}"
- exitcodes="${exitcodes} $?"
-done
-
-for i in ${exitcodes}; do
- [ ${i} -eq 0 ] || exit ${i}
-done
-`, setting.ScriptType),
- }
-
- giteaHookTpls = []string{
- // for pre-receive
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-%s hook --config=%s pre-receive
-`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
-
- // for update
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-%s hook --config=%s update $1 $2 $3
-`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
-
- // for post-receive
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-%s hook --config=%s post-receive
-`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
- }
-
- // although only new git (>=2.29) supports proc-receive, it's still good to create its hook, in case the user upgrades git
- hookNames = append(hookNames, "proc-receive")
- hookTpls = append(hookTpls,
- fmt.Sprintf(`#!/usr/bin/env %s
-# AUTO GENERATED BY GITEA, DO NOT MODIFY
-%s hook --config=%s proc-receive
-`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)))
- giteaHookTpls = append(giteaHookTpls, "")
-
- return hookNames, hookTpls, giteaHookTpls
-}
-
-// CreateDelegateHooks creates all the hooks scripts for the repo
-func CreateDelegateHooks(repoPath string) (err error) {
- hookNames, hookTpls, giteaHookTpls := getHookTemplates()
- hookDir := filepath.Join(repoPath, "hooks")
-
- for i, hookName := range hookNames {
- oldHookPath := filepath.Join(hookDir, hookName)
- newHookPath := filepath.Join(hookDir, hookName+".d", "gitea")
-
- if err := os.MkdirAll(filepath.Join(hookDir, hookName+".d"), os.ModePerm); err != nil {
- return fmt.Errorf("create hooks dir '%s': %w", filepath.Join(hookDir, hookName+".d"), err)
- }
-
- // WARNING: This will override all old server-side hooks
- if err = util.Remove(oldHookPath); err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("unable to pre-remove old hook file '%s' prior to rewriting: %w ", oldHookPath, err)
- }
- if err = os.WriteFile(oldHookPath, []byte(hookTpls[i]), 0o777); err != nil {
- return fmt.Errorf("write old hook file '%s': %w", oldHookPath, err)
- }
-
- if err = ensureExecutable(oldHookPath); err != nil {
- return fmt.Errorf("Unable to set %s executable. Error %w", oldHookPath, err)
- }
-
- if err = util.Remove(newHookPath); err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("unable to pre-remove new hook file '%s' prior to rewriting: %w", newHookPath, err)
- }
- if err = os.WriteFile(newHookPath, []byte(giteaHookTpls[i]), 0o777); err != nil {
- return fmt.Errorf("write new hook file '%s': %w", newHookPath, err)
- }
-
- if err = ensureExecutable(newHookPath); err != nil {
- return fmt.Errorf("Unable to set %s executable. Error %w", oldHookPath, err)
- }
- }
-
- return nil
-}
-
-func checkExecutable(filename string) bool {
- // windows has no concept of a executable bit
- if runtime.GOOS == "windows" {
- return true
- }
- fileInfo, err := os.Stat(filename)
- if err != nil {
- return false
- }
- return (fileInfo.Mode() & 0o100) > 0
-}
-
-func ensureExecutable(filename string) error {
- fileInfo, err := os.Stat(filename)
- if err != nil {
- return err
- }
- if (fileInfo.Mode() & 0o100) > 0 {
- return nil
- }
- mode := fileInfo.Mode() | 0o100
- return os.Chmod(filename, mode)
-}
-
-// CheckDelegateHooks checks the hooks scripts for the repo
-func CheckDelegateHooks(repoPath string) ([]string, error) {
- hookNames, hookTpls, giteaHookTpls := getHookTemplates()
-
- hookDir := filepath.Join(repoPath, "hooks")
- results := make([]string, 0, 10)
-
- for i, hookName := range hookNames {
- oldHookPath := filepath.Join(hookDir, hookName)
- newHookPath := filepath.Join(hookDir, hookName+".d", "gitea")
-
- cont := false
- isExist, err := util.IsExist(oldHookPath)
- if err != nil {
- results = append(results, fmt.Sprintf("unable to check if %s exists. Error: %v", oldHookPath, err))
- }
- if err == nil && !isExist {
- results = append(results, fmt.Sprintf("old hook file %s does not exist", oldHookPath))
- cont = true
- }
- isExist, err = util.IsExist(oldHookPath + ".d")
- if err != nil {
- results = append(results, fmt.Sprintf("unable to check if %s exists. Error: %v", oldHookPath+".d", err))
- }
- if err == nil && !isExist {
- results = append(results, fmt.Sprintf("hooks directory %s does not exist", oldHookPath+".d"))
- cont = true
- }
- isExist, err = util.IsExist(newHookPath)
- if err != nil {
- results = append(results, fmt.Sprintf("unable to check if %s exists. Error: %v", newHookPath, err))
- }
- if err == nil && !isExist {
- results = append(results, fmt.Sprintf("new hook file %s does not exist", newHookPath))
- cont = true
- }
- if cont {
- continue
- }
- contents, err := os.ReadFile(oldHookPath)
- if err != nil {
- return results, err
- }
- if string(contents) != hookTpls[i] {
- results = append(results, fmt.Sprintf("old hook file %s is out of date", oldHookPath))
- }
- if !checkExecutable(oldHookPath) {
- results = append(results, fmt.Sprintf("old hook file %s is not executable", oldHookPath))
- }
- contents, err = os.ReadFile(newHookPath)
- if err != nil {
- return results, err
- }
- if string(contents) != giteaHookTpls[i] {
- results = append(results, fmt.Sprintf("new hook file %s is out of date", newHookPath))
- }
- if !checkExecutable(newHookPath) {
- results = append(results, fmt.Sprintf("new hook file %s is not executable", newHookPath))
- }
- }
- return results, nil
-}
diff --git a/modules/repository/init.go b/modules/repository/init.go
index 24602ae090..12e9606c74 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -11,10 +11,7 @@ import (
"strings"
issues_model "code.gitea.io/gitea/models/issues"
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/label"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/options"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -120,30 +117,6 @@ func LoadRepoConfig() error {
return nil
}
-func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) {
- // Somehow the directory could exist.
- repoPath := repo_model.RepoPath(owner, name)
- isExist, err := util.IsExist(repoPath)
- if err != nil {
- log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
- return err
- }
- if isExist {
- return repo_model.ErrRepoFilesAlreadyExist{
- Uname: owner,
- Name: name,
- }
- }
-
- // Init git bare new repository.
- if err = git.InitRepository(ctx, repoPath, true, objectFormatName); err != nil {
- return fmt.Errorf("git.InitRepository: %w", err)
- } else if err = CreateDelegateHooks(repoPath); err != nil {
- return fmt.Errorf("createDelegateHooks: %w", err)
- }
- return nil
-}
-
// InitializeLabels adds a label set to a repository using a template
func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg bool) error {
list, err := LoadTemplateLabelsByDisplayName(labelTemplate)
@@ -152,12 +125,13 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg
}
labels := make([]*issues_model.Label, len(list))
- for i := 0; i < len(list); i++ {
+ for i := range list {
labels[i] = &issues_model.Label{
- Name: list[i].Name,
- Exclusive: list[i].Exclusive,
- Description: list[i].Description,
- Color: list[i].Color,
+ Name: list[i].Name,
+ Exclusive: list[i].Exclusive,
+ ExclusiveOrder: list[i].ExclusiveOrder,
+ Description: list[i].Description,
+ Color: list[i].Color,
}
if isOrg {
labels[i].OrgID = id
diff --git a/modules/repository/init_test.go b/modules/repository/init_test.go
index 227efdc1db..1fa928105c 100644
--- a/modules/repository/init_test.go
+++ b/modules/repository/init_test.go
@@ -14,17 +14,17 @@ func TestMergeCustomLabels(t *testing.T) {
all: []string{"a", "a.yaml", "a.yml"},
custom: nil,
})
- assert.EqualValues(t, []string{"a.yaml"}, files, "yaml file should win")
+ assert.Equal(t, []string{"a.yaml"}, files, "yaml file should win")
files = mergeCustomLabelFiles(optionFileList{
all: []string{"a", "a.yaml"},
custom: []string{"a"},
})
- assert.EqualValues(t, []string{"a"}, files, "custom file should win")
+ assert.Equal(t, []string{"a"}, files, "custom file should win")
files = mergeCustomLabelFiles(optionFileList{
all: []string{"a", "a.yml", "a.yaml"},
custom: []string{"a", "a.yml"},
})
- assert.EqualValues(t, []string{"a.yml"}, files, "custom yml file should win if no yaml")
+ assert.Equal(t, []string{"a.yml"}, files, "custom yml file should win if no yaml")
}
diff --git a/modules/repository/repo.go b/modules/repository/repo.go
index 97b0343381..ad4a53b858 100644
--- a/modules/repository/repo.go
+++ b/modules/repository/repo.go
@@ -9,13 +9,10 @@ import (
"fmt"
"io"
"strings"
- "time"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
- user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/lfs"
@@ -59,118 +56,6 @@ func SyncRepoTags(ctx context.Context, repoID int64) error {
return SyncReleasesWithTags(ctx, repo, gitRepo)
}
-// SyncReleasesWithTags synchronizes release table with repository tags
-func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error {
- log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name)
-
- // optimized procedure for pull-mirrors which saves a lot of time (in
- // particular for repos with many tags).
- if repo.IsMirror {
- return pullMirrorReleaseSync(ctx, repo, gitRepo)
- }
-
- existingRelTags := make(container.Set[string])
- opts := repo_model.FindReleasesOptions{
- IncludeDrafts: true,
- IncludeTags: true,
- ListOptions: db.ListOptions{PageSize: 50},
- RepoID: repo.ID,
- }
- for page := 1; ; page++ {
- opts.Page = page
- rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts)
- if err != nil {
- return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err)
- }
- if len(rels) == 0 {
- break
- }
- for _, rel := range rels {
- if rel.IsDraft {
- continue
- }
- commitID, err := gitRepo.GetTagCommitID(rel.TagName)
- if err != nil && !git.IsErrNotExist(err) {
- return fmt.Errorf("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err)
- }
- if git.IsErrNotExist(err) || commitID != rel.Sha1 {
- if err := repo_model.PushUpdateDeleteTag(ctx, repo, rel.TagName); err != nil {
- return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err)
- }
- } else {
- existingRelTags.Add(strings.ToLower(rel.TagName))
- }
- }
- }
-
- _, err := gitRepo.WalkReferences(git.ObjectTag, 0, 0, func(sha1, refname string) error {
- tagName := strings.TrimPrefix(refname, git.TagPrefix)
- if existingRelTags.Contains(strings.ToLower(tagName)) {
- return nil
- }
-
- if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil {
- // sometimes, some tags will be sync failed. i.e. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tag/?h=v2.6.11
- // this is a tree object, not a tag object which created before git
- log.Error("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %v", tagName, repo.ID, repo.OwnerName, repo.Name, err)
- }
-
- return nil
- })
- return err
-}
-
-// PushUpdateAddTag must be called for any push actions to add tag
-func PushUpdateAddTag(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, tagName, sha1, refname string) error {
- tag, err := gitRepo.GetTagWithID(sha1, tagName)
- if err != nil {
- return fmt.Errorf("unable to GetTag: %w", err)
- }
- commit, err := tag.Commit(gitRepo)
- if err != nil {
- return fmt.Errorf("unable to get tag Commit: %w", err)
- }
-
- sig := tag.Tagger
- if sig == nil {
- sig = commit.Author
- }
- if sig == nil {
- sig = commit.Committer
- }
-
- var author *user_model.User
- createdAt := time.Unix(1, 0)
-
- if sig != nil {
- author, err = user_model.GetUserByEmail(ctx, sig.Email)
- if err != nil && !user_model.IsErrUserNotExist(err) {
- return fmt.Errorf("unable to GetUserByEmail for %q: %w", sig.Email, err)
- }
- createdAt = sig.When
- }
-
- commitsCount, err := commit.CommitsCount()
- if err != nil {
- return fmt.Errorf("unable to get CommitsCount: %w", err)
- }
-
- rel := repo_model.Release{
- RepoID: repo.ID,
- TagName: tagName,
- LowerTagName: strings.ToLower(tagName),
- Sha1: commit.ID.String(),
- NumCommits: commitsCount,
- CreatedUnix: timeutil.TimeStamp(createdAt.Unix()),
- IsTag: true,
- }
- if author != nil {
- rel.PublisherID = author.ID
- }
-
- return repo_model.SaveOrUpdateTag(ctx, repo, &rel)
-}
-
// StoreMissingLfsObjectsInRepository downloads missing LFS objects
func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, lfsClient lfs.Client) error {
contentStore := lfs.NewContentStore()
@@ -286,18 +171,19 @@ func (shortRelease) TableName() string {
return "release"
}
-// pullMirrorReleaseSync is a pull-mirror specific tag<->release table
+// SyncReleasesWithTags is a tag<->release table
// synchronization which overwrites all Releases from the repository tags. This
// can be relied on since a pull-mirror is always identical to its
-// upstream. Hence, after each sync we want the pull-mirror release set to be
+// upstream. Hence, after each sync we want the release set to be
// identical to the upstream tag set. This is much more efficient for
// repositories like https://github.com/vim/vim (with over 13000 tags).
-func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error {
- log.Trace("pullMirrorReleaseSync: rebuilding releases for pull-mirror Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name)
- tags, numTags, err := gitRepo.GetTagInfos(0, 0)
+func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error {
+ log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name)
+ tags, _, err := gitRepo.GetTagInfos(0, 0)
if err != nil {
return fmt.Errorf("unable to GetTagInfos in pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err)
}
+ var added, deleted, updated int
err = db.WithTx(ctx, func(ctx context.Context) error {
dbReleases, err := db.Find[shortRelease](ctx, repo_model.FindReleasesOptions{
RepoID: repo.ID,
@@ -318,9 +204,7 @@ func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, git
TagName: tag.Name,
LowerTagName: strings.ToLower(tag.Name),
Sha1: tag.Object.String(),
- // NOTE: ignored, since NumCommits are unused
- // for pull-mirrors (only relevant when
- // displaying releases, IsTag: false)
+ // NOTE: ignored, The NumCommits value is calculated and cached on demand when the UI requires it.
NumCommits: -1,
CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()),
IsTag: true,
@@ -349,13 +233,14 @@ func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, git
return fmt.Errorf("unable to update tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err)
}
}
+ added, deleted, updated = len(deletes), len(updates), len(inserts)
return nil
})
if err != nil {
return fmt.Errorf("unable to rebuild release table for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err)
}
- log.Trace("pullMirrorReleaseSync: done rebuilding %d releases", numTags)
+ log.Trace("SyncReleasesWithTags: %d tags added, %d tags deleted, %d tags updated", added, deleted, updated)
return nil
}
diff --git a/modules/repository/repo_test.go b/modules/repository/repo_test.go
index f3e7be6d7d..f79a79ccbd 100644
--- a/modules/repository/repo_test.go
+++ b/modules/repository/repo_test.go
@@ -63,7 +63,7 @@ func Test_calcSync(t *testing.T) {
inserts, deletes, updates := calcSync(gitTags, dbReleases)
if assert.Len(t, inserts, 1, "inserts") {
- assert.EqualValues(t, *gitTags[2], *inserts[0], "inserts equal")
+ assert.Equal(t, *gitTags[2], *inserts[0], "inserts equal")
}
if assert.Len(t, deletes, 1, "deletes") {
@@ -71,6 +71,6 @@ func Test_calcSync(t *testing.T) {
}
if assert.Len(t, updates, 1, "updates") {
- assert.EqualValues(t, *gitTags[1], *updates[0], "updates equal")
+ assert.Equal(t, *gitTags[1], *updates[0], "updates equal")
}
}
diff --git a/modules/repository/temp.go b/modules/repository/temp.go
index 04faa9db3d..d7253d9e02 100644
--- a/modules/repository/temp.go
+++ b/modules/repository/temp.go
@@ -4,42 +4,19 @@
package repository
import (
+ "context"
"fmt"
- "os"
- "path"
- "path/filepath"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
)
-// LocalCopyPath returns the local repository temporary copy path.
-func LocalCopyPath() string {
- if filepath.IsAbs(setting.Repository.Local.LocalCopyPath) {
- return setting.Repository.Local.LocalCopyPath
- }
- return path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath)
-}
-
// CreateTemporaryPath creates a temporary path
-func CreateTemporaryPath(prefix string) (string, error) {
- if err := os.MkdirAll(LocalCopyPath(), os.ModePerm); err != nil {
- log.Error("Unable to create localcopypath directory: %s (%v)", LocalCopyPath(), err)
- return "", fmt.Errorf("Failed to create localcopypath directory %s: %w", LocalCopyPath(), err)
- }
- basePath, err := os.MkdirTemp(LocalCopyPath(), prefix+".git")
+func CreateTemporaryPath(prefix string) (string, context.CancelFunc, error) {
+ basePath, cleanup, err := setting.AppDataTempDir("local-repo").MkdirTempRandom(prefix + ".git")
if err != nil {
log.Error("Unable to create temporary directory: %s-*.git (%v)", prefix, err)
- return "", fmt.Errorf("Failed to create dir %s-*.git: %w", prefix, err)
- }
- return basePath, nil
-}
-
-// RemoveTemporaryPath removes the temporary path
-func RemoveTemporaryPath(basePath string) error {
- if _, err := os.Stat(basePath); !os.IsNotExist(err) {
- return util.RemoveAll(basePath)
+ return "", nil, fmt.Errorf("failed to create dir %s-*.git: %w", prefix, err)
}
- return nil
+ return basePath, cleanup, nil
}