Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cd34ffe
Use git model to detect whether branch exist instead of gitrepo method
lunny Sep 11, 2025
9801db8
Merge branch 'main' into lunny/use_git_model
lunny Sep 17, 2025
ca586c3
Fix bug
lunny Sep 17, 2025
07d5b81
Merge branch 'main' into lunny/use_git_model
lunny Sep 27, 2025
32edd4d
Fix test
lunny Sep 30, 2025
6541b73
Merge branch 'main' into lunny/use_git_model
lunny Sep 30, 2025
b61ac43
improvements
lunny Sep 30, 2025
8ca9949
Merge branch 'main' into lunny/use_git_model
lunny Oct 6, 2025
cd1049a
fix test
lunny Oct 7, 2025
ffcddb0
Merge branch 'main' into lunny/use_git_model
lunny Oct 9, 2025
37d09a6
Merge branch 'main' into lunny/use_git_model
lunny Oct 9, 2025
ecc92ee
Fix bug
lunny Oct 9, 2025
635e7ae
Merge branch 'lunny/use_git_model' of github.com:lunny/gitea into lun…
lunny Oct 9, 2025
d91d63c
Merge branch 'main' into lunny/use_git_model
lunny Oct 10, 2025
12278a2
Merge branch 'main' into lunny/use_git_model
lunny Oct 18, 2025
1c11bd7
Merge branch 'main' into lunny/use_git_model
lunny Oct 19, 2025
6373e9b
Merge branch 'main' into lunny/use_git_model
lunny Oct 20, 2025
988811d
Merge branch 'main' into lunny/use_git_model
lunny Oct 20, 2025
808e879
Some improvements
lunny Oct 22, 2025
eb58cbf
Merge branch 'lunny/use_git_model' of github.com:lunny/gitea into lun…
lunny Oct 22, 2025
f1941bd
Merge branch 'main' into lunny/use_git_model
lunny Oct 22, 2025
e089923
more test
lunny Oct 22, 2025
d61c3d2
Merge branch 'main' into lunny/use_git_model
GiteaBot Oct 25, 2025
7798ade
Fix lint
lunny Oct 25, 2025
f7c3640
Merge branch 'main' into lunny/use_git_model
GiteaBot Oct 25, 2025
71b546e
Merge branch 'main' into lunny/use_git_model
lunny Oct 25, 2025
3904d46
Merge branch 'lunny/use_git_model' of github.com:lunny/gitea into lun…
lunny Oct 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions models/fixtures/branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,27 @@
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 27
repo_id: 1
name: 'DefaultBranch'
commit_id: '90c1019714259b24fb81711d4416ac0f18667dfa'
commit_message: 'add license'
commit_time: 1709345946
pusher_id: 1
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 28
repo_id: 1
name: 'sub-home-md-img-check'
commit_id: '4649299398e4d39a5c09eb4f534df6f1e1eb87cc'
commit_message: "Test how READMEs render images when found in a subfolder"
commit_time: 1678403550
pusher_id: 1
is_deleted: false
deleted_by_id: 0
deleted_unix: 0
8 changes: 6 additions & 2 deletions routers/api/v1/repo/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func CreateBranch(ctx *context.APIContext) {
return
}
} else if len(opt.OldBranchName) > 0 { //nolint:staticcheck // deprecated field
if gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, opt.OldBranchName) { //nolint:staticcheck // deprecated field
if exist, _ := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, opt.OldBranchName); exist { //nolint:staticcheck // deprecated field
oldCommit, err = ctx.Repo.GitRepo.GetBranchCommit(opt.OldBranchName) //nolint:staticcheck // deprecated field
if err != nil {
ctx.APIErrorInternal(err)
Expand Down Expand Up @@ -1011,7 +1011,11 @@ func EditBranchProtection(ctx *context.APIContext) {
isPlainRule := !git_model.IsRuleNameSpecial(bpName)
var isBranchExist bool
if isPlainRule {
isBranchExist = gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, bpName)
isBranchExist, err = git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, bpName)
if err != nil {
ctx.APIErrorInternal(err)
return
}
}

if isBranchExist {
Expand Down
7 changes: 6 additions & 1 deletion routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,12 @@

// change pull target branch
if !pr.HasMerged && len(form.Base) != 0 && form.Base != pr.BaseBranch {
if !gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, form.Base) {
branchExist, err := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, form.Base)

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / test-pgsql

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / test-unit

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / test-sqlite

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / test-mysql

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / test-mssql

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / lint-backend

undefined: git_model (typecheck)

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / lint-go-gogit

undefined: git_model (typecheck)

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / lint-go-windows

undefined: git_model (typecheck)

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / checks-backend

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / checks-backend

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / checks-backend

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / checks-backend

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / checks-backend

undefined: git_model

Check failure on line 758 in routers/api/v1/repo/pull.go

View workflow job for this annotation

GitHub Actions / backend

undefined: git_model
if err != nil {
ctx.APIErrorInternal(err)
return
}
if !branchExist {
ctx.APIError(http.StatusNotFound, fmt.Errorf("new base '%s' not exist", form.Base))
return
}
Expand Down
3 changes: 2 additions & 1 deletion routers/api/v1/utils/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package utils
import (
"errors"

git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
Expand All @@ -27,7 +28,7 @@ func ResolveRefCommit(ctx reqctx.RequestContext, repo *repo_model.Repository, in
return nil, err
}
refCommit := RefCommit{InputRef: inputRef}
if gitrepo.IsBranchExist(ctx, repo, inputRef) {
if exist, _ := git_model.IsBranchExist(ctx, repo.ID, inputRef); exist {
refCommit.RefName = git.RefNameFromBranch(inputRef)
} else if gitrepo.IsTagExist(ctx, repo, inputRef) {
refCommit.RefName = git.RefNameFromTag(inputRef)
Expand Down
29 changes: 12 additions & 17 deletions routers/private/hook_pre_receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/agit"
gitea_context "code.gitea.io/gitea/services/context"
pull_service "code.gitea.io/gitea/services/pull"
)
Expand Down Expand Up @@ -452,25 +454,18 @@ func preReceiveFor(ctx *preReceiveContext, refFullName git.RefName) {
return
}

baseBranchName := refFullName.ForBranchName()

baseBranchExist := gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, baseBranchName)

if !baseBranchExist {
for p, v := range baseBranchName {
if v == '/' && gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, baseBranchName[:p]) && p != len(baseBranchName)-1 {
baseBranchExist = true
break
}
_, _, err := agit.GetAgitBranchInfo(ctx, ctx.Repo.Repository.ID, refFullName.ForBranchName())
if err != nil {
if !errors.Is(err, util.ErrNotExist) {
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("Unexpected ref: %s", refFullName),
})
} else {
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: err.Error(),
})
}
}

if !baseBranchExist {
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("Unexpected ref: %s", refFullName),
})
return
}
}

func generateGitEnv(opts *private.HookOptions) (env []string) {
Expand Down
4 changes: 2 additions & 2 deletions routers/web/repo/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {

// Check if base branch is valid.
baseIsCommit := ctx.Repo.GitRepo.IsCommitExist(ci.BaseBranch)
baseIsBranch := gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, ci.BaseBranch)
baseIsBranch, _ := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, ci.BaseBranch)
baseIsTag := gitrepo.IsTagExist(ctx, ctx.Repo.Repository, ci.BaseBranch)

if !baseIsCommit && !baseIsBranch && !baseIsTag {
Expand Down Expand Up @@ -508,7 +508,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {

// Check if head branch is valid.
headIsCommit := ci.HeadGitRepo.IsCommitExist(ci.HeadBranch)
headIsBranch := gitrepo.IsBranchExist(ctx, ci.HeadRepo, ci.HeadBranch)
headIsBranch, _ := git_model.IsBranchExist(ctx, ci.HeadRepo.ID, ci.HeadBranch)
headIsTag := gitrepo.IsTagExist(ctx, ci.HeadRepo, ci.HeadBranch)
if !headIsCommit && !headIsBranch && !headIsTag {
// Check if headBranch is short sha commit hash
Expand Down
4 changes: 2 additions & 2 deletions routers/web/repo/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (
"strconv"
"strings"

git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/renderhelper"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/htmlutil"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
Expand Down Expand Up @@ -121,7 +121,7 @@ func NewComment(ctx *context.Context) {
ctx.ServerError("Unable to load head repo", err)
return
}
if ok := gitrepo.IsBranchExist(ctx, pull.HeadRepo, pull.BaseBranch); !ok {
if exist, _ := git_model.IsBranchExist(ctx, pull.HeadRepo.ID, pull.BaseBranch); !exist {
// todo localize
ctx.JSONError("The origin branch is delete, cannot reopen.")
return
Expand Down
5 changes: 3 additions & 2 deletions routers/web/repo/issue_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
Expand Down Expand Up @@ -566,8 +565,10 @@ func preparePullViewDeleteBranch(ctx *context.Context, issue *issues_model.Issue
pull := issue.PullRequest
isPullBranchDeletable := canDelete &&
pull.HeadRepo != nil &&
gitrepo.IsBranchExist(ctx, pull.HeadRepo, pull.HeadBranch) &&
(!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"])
if isPullBranchDeletable {
isPullBranchDeletable, _ = git_model.IsBranchExist(ctx, pull.HeadRepo.ID, pull.HeadBranch)
}

if isPullBranchDeletable && pull.HasMerged {
exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(ctx, pull.HeadRepoID, pull.HeadBranch)
Expand Down
4 changes: 2 additions & 2 deletions routers/web/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func prepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *pull_
defer baseGitRepo.Close()
}

if !gitrepo.IsBranchExist(ctx, pull.BaseRepo, pull.BaseBranch) {
if exist, _ := git_model.IsBranchExist(ctx, pull.BaseRepo.ID, pull.BaseBranch); !exist {
ctx.Data["BaseBranchNotExist"] = true
ctx.Data["IsPullRequestBroken"] = true
ctx.Data["BaseTarget"] = pull.BaseBranch
Expand Down Expand Up @@ -415,7 +415,7 @@ func prepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *pull_
defer closer.Close()

if pull.Flow == issues_model.PullRequestFlowGithub {
headBranchExist = gitrepo.IsBranchExist(ctx, pull.HeadRepo, pull.HeadBranch)
headBranchExist, _ = git_model.IsBranchExist(ctx, pull.HeadRepo.ID, pull.HeadBranch)
} else {
headBranchExist = gitrepo.IsReferenceExist(ctx, pull.BaseRepo, pull.GetGitHeadRefName())
}
Expand Down
3 changes: 1 addition & 2 deletions routers/web/repo/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -424,7 +423,7 @@ func NewReleasePost(ctx *context.Context) {
return
}

if !gitrepo.IsBranchExist(ctx, ctx.Repo.Repository, form.Target) {
if exist, _ := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, form.Target); !exist {
ctx.RenderWithErr(ctx.Tr("form.target_branch_not_exist"), tplReleaseNew, &form)
return
}
Expand Down
51 changes: 41 additions & 10 deletions services/agit/agit.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package agit
import (
"context"
"encoding/base64"
"errors"
"fmt"
"strings"

Expand All @@ -32,6 +33,34 @@ func parseAgitPushOptionValue(s string) string {
return s
}

func GetAgitBranchInfo(ctx context.Context, repoID int64, baseBranchName string) (string, string, error) {
baseBranchExist, err := git_model.IsBranchExist(ctx, repoID, baseBranchName)
if err != nil {
return "", "", err
}
if baseBranchExist {
return baseBranchName, "", nil
}

// try match <target-branch>/<topic-branch>
// refs/for have been trimmed to get baseBranchName
for p, v := range baseBranchName {
if v != '/' {
continue
}

baseBranchExist, err := git_model.IsBranchExist(ctx, repoID, baseBranchName[:p])
if err != nil {
return "", "", err
}
if baseBranchExist {
return baseBranchName[:p], baseBranchName[p+1:], nil
}
}

return "", "", util.NewNotExistErrorf("base branch does not exist")
}

// ProcReceive handle proc receive work
func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) {
results := make([]private.HookProcReceiveRefResult, 0, len(opts.OldCommitIDs))
Expand Down Expand Up @@ -70,17 +99,19 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
continue
}

baseBranchName := opts.RefFullNames[i].ForBranchName()
currentTopicBranch := ""
if !gitrepo.IsBranchExist(ctx, repo, baseBranchName) {
// try match refs/for/<target-branch>/<topic-branch>
for p, v := range baseBranchName {
if v == '/' && gitrepo.IsBranchExist(ctx, repo, baseBranchName[:p]) && p != len(baseBranchName)-1 {
currentTopicBranch = baseBranchName[p+1:]
baseBranchName = baseBranchName[:p]
break
}
baseBranchName, currentTopicBranch, err := GetAgitBranchInfo(ctx, repo.ID, opts.RefFullNames[i].ForBranchName())
if err != nil {
if !errors.Is(err, util.ErrNotExist) {
return nil, fmt.Errorf("failed to get branch information. Error: %w", err)
}
// If branch does not exist, we can continue
results = append(results, private.HookProcReceiveRefResult{
OriginalRef: opts.RefFullNames[i],
OldOID: opts.OldCommitIDs[i],
NewOID: opts.NewCommitIDs[i],
Err: "base-branch does not exist",
})
continue
}

if len(topicBranch) == 0 && len(currentTopicBranch) == 0 {
Expand Down
45 changes: 45 additions & 0 deletions services/agit/agit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,56 @@ package agit
import (
"testing"

"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/util"

"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
unittest.MainTest(m)
}

func TestParseAgitPushOptionValue(t *testing.T) {
assert.Equal(t, "a", parseAgitPushOptionValue("a"))
assert.Equal(t, "a", parseAgitPushOptionValue("{base64}YQ=="))
assert.Equal(t, "{base64}invalid value", parseAgitPushOptionValue("{base64}invalid value"))
}

func TestGetAgitBranchInfo(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

_, _, err := GetAgitBranchInfo(t.Context(), 1, "non-exist-basebranch")
assert.ErrorIs(t, err, util.ErrNotExist)

baseBranch, currentTopicBranch, err := GetAgitBranchInfo(t.Context(), 1, "master")
assert.NoError(t, err)
assert.Equal(t, "master", baseBranch)
assert.Empty(t, currentTopicBranch)

baseBranch, currentTopicBranch, err = GetAgitBranchInfo(t.Context(), 1, "master/topicbranch")
assert.NoError(t, err)
assert.Equal(t, "master", baseBranch)
assert.Equal(t, "topicbranch", currentTopicBranch)

baseBranch, currentTopicBranch, err = GetAgitBranchInfo(t.Context(), 1, "master/")
assert.NoError(t, err)
assert.Equal(t, "master", baseBranch)
assert.Empty(t, currentTopicBranch)

_, _, err = GetAgitBranchInfo(t.Context(), 1, "/")
assert.ErrorIs(t, err, util.ErrNotExist)

_, _, err = GetAgitBranchInfo(t.Context(), 1, "//")
assert.ErrorIs(t, err, util.ErrNotExist)

baseBranch, currentTopicBranch, err = GetAgitBranchInfo(t.Context(), 1, "master/topicbranch/")
assert.NoError(t, err)
assert.Equal(t, "master", baseBranch)
assert.Equal(t, "topicbranch/", currentTopicBranch)

baseBranch, currentTopicBranch, err = GetAgitBranchInfo(t.Context(), 1, "master/topicbranch/1")
assert.NoError(t, err)
assert.Equal(t, "master", baseBranch)
assert.Equal(t, "topicbranch/1", currentTopicBranch)
}
6 changes: 5 additions & 1 deletion services/automerge/automerge.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"

"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
pull_model "code.gitea.io/gitea/models/pull"
Expand Down Expand Up @@ -207,7 +208,10 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {

switch pr.Flow {
case issues_model.PullRequestFlowGithub:
headBranchExist := pr.HeadRepo != nil && gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch)
headBranchExist := pr.HeadRepo != nil
if headBranchExist {
headBranchExist, _ = git_model.IsBranchExist(ctx, pr.HeadRepo.ID, pr.HeadBranch)
}
if !headBranchExist {
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
return
Expand Down
8 changes: 6 additions & 2 deletions services/pull/commit_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,12 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR
}
defer closer.Close()

if pr.Flow == issues_model.PullRequestFlowGithub && !gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch) {
return "", errors.New("Head branch does not exist, can not merge")
if pr.Flow == issues_model.PullRequestFlowGithub {
if exist, err := git_model.IsBranchExist(ctx, pr.HeadRepo.ID, pr.HeadBranch); err != nil {
return "", errors.Wrap(err, "IsBranchExist")
} else if !exist {
return "", errors.New("Head branch does not exist, can not merge")
}
}
if pr.Flow == issues_model.PullRequestFlowAGit && !gitrepo.IsReferenceExist(ctx, pr.HeadRepo, pr.GetGitHeadRefName()) {
return "", errors.New("Head branch does not exist, can not merge")
Expand Down
Loading
Loading