mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-02 22:01:44 +02:00
merge main
This commit is contained in:
commit
335375fd76
211 files changed
+3789
-3048
No files matched your search
@@ -54,7 +54,13 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
|
||||
return fmt.Errorf("head commit is missing in event payload")
|
||||
}
|
||||
sha = payload.HeadCommit.ID
|
||||
case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync:
|
||||
case // pull_request
|
||||
webhook_module.HookEventPullRequest,
|
||||
webhook_module.HookEventPullRequestSync,
|
||||
webhook_module.HookEventPullRequestAssign,
|
||||
webhook_module.HookEventPullRequestLabel,
|
||||
webhook_module.HookEventPullRequestReviewRequest,
|
||||
webhook_module.HookEventPullRequestMilestone:
|
||||
if run.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
||||
event = "pull_request_target"
|
||||
} else {
|
||||
|
||||
+10
-12
@@ -9,6 +9,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_isGitRawOrLFSPath(t *testing.T) {
|
||||
@@ -108,26 +110,22 @@ func Test_isGitRawOrLFSPath(t *testing.T) {
|
||||
t.Run(tt.path, func(t *testing.T) {
|
||||
req, _ := http.NewRequest("POST", "http://localhost"+tt.path, nil)
|
||||
setting.LFS.StartServer = false
|
||||
if got := isGitRawOrAttachOrLFSPath(req); got != tt.want {
|
||||
t.Errorf("isGitOrLFSPath() = %v, want %v", got, tt.want)
|
||||
}
|
||||
assert.Equal(t, tt.want, isGitRawOrAttachOrLFSPath(req))
|
||||
|
||||
setting.LFS.StartServer = true
|
||||
if got := isGitRawOrAttachOrLFSPath(req); got != tt.want {
|
||||
t.Errorf("isGitOrLFSPath() = %v, want %v", got, tt.want)
|
||||
}
|
||||
assert.Equal(t, tt.want, isGitRawOrAttachOrLFSPath(req))
|
||||
})
|
||||
}
|
||||
for _, tt := range lfsTests {
|
||||
t.Run(tt, func(t *testing.T) {
|
||||
req, _ := http.NewRequest("POST", tt, nil)
|
||||
setting.LFS.StartServer = false
|
||||
if got := isGitRawOrAttachOrLFSPath(req); got != setting.LFS.StartServer {
|
||||
t.Errorf("isGitOrLFSPath(%q) = %v, want %v, %v", tt, got, setting.LFS.StartServer, gitRawOrAttachPathRe.MatchString(tt))
|
||||
}
|
||||
got := isGitRawOrAttachOrLFSPath(req)
|
||||
assert.Equalf(t, setting.LFS.StartServer, got, "isGitOrLFSPath(%q) = %v, want %v, %v", tt, got, setting.LFS.StartServer, gitRawOrAttachPathRe.MatchString(tt))
|
||||
|
||||
setting.LFS.StartServer = true
|
||||
if got := isGitRawOrAttachOrLFSPath(req); got != setting.LFS.StartServer {
|
||||
t.Errorf("isGitOrLFSPath(%q) = %v, want %v", tt, got, setting.LFS.StartServer)
|
||||
}
|
||||
got = isGitRawOrAttachOrLFSPath(req)
|
||||
assert.Equalf(t, setting.LFS.StartServer, got, "isGitOrLFSPath(%q) = %v, want %v", tt, got, setting.LFS.StartServer)
|
||||
})
|
||||
}
|
||||
setting.LFS.StartServer = origLFSStartServer
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/queue"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
)
|
||||
|
||||
// prAutoMergeQueue represents a queue to handle update pull request tests
|
||||
@@ -63,9 +64,9 @@ func addToQueue(pr *issues_model.PullRequest, sha string) {
|
||||
}
|
||||
|
||||
// ScheduleAutoMerge if schedule is false and no error, pull can be merged directly
|
||||
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest, style repo_model.MergeStyle, message string) (scheduled bool, err error) {
|
||||
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest, style repo_model.MergeStyle, message string, deleteBranchAfterMerge bool) (scheduled bool, err error) {
|
||||
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if err := pull_model.ScheduleAutoMerge(ctx, doer, pull.ID, style, message); err != nil {
|
||||
if err := pull_model.ScheduleAutoMerge(ctx, doer, pull.ID, style, message, deleteBranchAfterMerge); err != nil {
|
||||
return err
|
||||
}
|
||||
scheduled = true
|
||||
@@ -303,4 +304,10 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
|
||||
// on the pull request page. But this should not be finished in a bug fix PR which will be backport to release branch.
|
||||
return
|
||||
}
|
||||
|
||||
if pr.Flow == issues_model.PullRequestFlowGithub && scheduledPRM.DeleteBranchAfterMerge {
|
||||
if err := repo_service.DeleteBranch(ctx, doer, pr.HeadRepo, headGitRepo, pr.HeadBranch, pr); err != nil {
|
||||
log.Error("DeletePullRequestHeadBranch: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,8 +293,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// NOTICE: the "ref" here for internal usage only (e.g. woodpecker)
|
||||
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.FormTrim("ref"))
|
||||
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.PathParam("*"), ctx.FormTrim("ref"))
|
||||
var err error
|
||||
|
||||
if ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
|
||||
+20
-27
@@ -325,9 +325,9 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||
|
||||
var cloneURL string
|
||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
||||
cloneURL = repo_model.ComposeSSHCloneURL(username, reponame)
|
||||
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, username, reponame)
|
||||
} else {
|
||||
cloneURL = repo_model.ComposeHTTPSCloneURL(username, reponame)
|
||||
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, username, reponame)
|
||||
}
|
||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
||||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
||||
@@ -564,7 +564,7 @@ func RepoAssignment(ctx *Context) {
|
||||
// If multiple forks are available or if the user can fork to another account, but there is already a fork: open selection dialog
|
||||
ctx.Data["ShowForkModal"] = len(userAndOrgForks) > 1 || (canSignedUserFork && len(userAndOrgForks) > 0)
|
||||
|
||||
ctx.Data["RepoCloneLink"] = repo.CloneLink()
|
||||
ctx.Data["RepoCloneLink"] = repo.CloneLink(ctx, ctx.Doer)
|
||||
|
||||
cloneButtonShowHTTPS := !setting.Repository.DisableHTTPGit
|
||||
cloneButtonShowSSH := !setting.SSH.Disabled && (ctx.IsSigned || setting.SSH.ExposeAnonymous)
|
||||
@@ -765,35 +765,30 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
|
||||
return ""
|
||||
}
|
||||
|
||||
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) {
|
||||
extraRef := util.OptionalArg(optionalExtraRef)
|
||||
reqPath := ctx.PathParam("*")
|
||||
reqPath = path.Join(extraRef, reqPath)
|
||||
|
||||
if refName := getRefName(ctx, repo, RepoRefBranch); refName != "" {
|
||||
func getRefNameLegacy(ctx *Base, repo *Repository, reqPath, extraRef string) (string, RepoRefType) {
|
||||
reqRefPath := path.Join(extraRef, reqPath)
|
||||
reqRefPathParts := strings.Split(reqRefPath, "/")
|
||||
if refName := getRefName(ctx, repo, reqRefPath, RepoRefBranch); refName != "" {
|
||||
return refName, RepoRefBranch
|
||||
}
|
||||
if refName := getRefName(ctx, repo, RepoRefTag); refName != "" {
|
||||
if refName := getRefName(ctx, repo, reqRefPath, RepoRefTag); refName != "" {
|
||||
return refName, RepoRefTag
|
||||
}
|
||||
|
||||
// For legacy support only full commit sha
|
||||
parts := strings.Split(reqPath, "/")
|
||||
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
|
||||
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), reqRefPathParts[0]) {
|
||||
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||
repo.TreePath = strings.Join(parts[1:], "/")
|
||||
return parts[0], RepoRefCommit
|
||||
repo.TreePath = strings.Join(reqRefPathParts[1:], "/")
|
||||
return reqRefPathParts[0], RepoRefCommit
|
||||
}
|
||||
|
||||
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
|
||||
if refName := getRefName(ctx, repo, reqPath, RepoRefBlob); refName != "" {
|
||||
return refName, RepoRefBlob
|
||||
}
|
||||
// FIXME: the old code falls back to default branch if "ref" doesn't exist, there could be an edge case:
|
||||
// "README?ref=no-such" would read the README file from the default branch, but the user might expect a 404
|
||||
repo.TreePath = reqPath
|
||||
return repo.Repository.DefaultBranch, RepoRefBranch
|
||||
}
|
||||
|
||||
func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||
path := ctx.PathParam("*")
|
||||
func getRefName(ctx *Base, repo *Repository, path string, pathType RepoRefType) string {
|
||||
switch pathType {
|
||||
case RepoRefBranch:
|
||||
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
|
||||
@@ -889,7 +884,8 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
}
|
||||
|
||||
// Get default branch.
|
||||
if len(ctx.PathParam("*")) == 0 {
|
||||
reqPath := ctx.PathParam("*")
|
||||
if reqPath == "" {
|
||||
refName = ctx.Repo.Repository.DefaultBranch
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1)
|
||||
@@ -897,10 +893,8 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
refName = brs[0].Name
|
||||
} else if len(brs) == 0 {
|
||||
log.Error("No branches in non-empty repository %s", ctx.Repo.GitRepo.Path)
|
||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||
} else {
|
||||
log.Error("GetBranches error: %v", err)
|
||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||
}
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
@@ -911,18 +905,17 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
} else if strings.Contains(err.Error(), "fatal: not a git repository") || strings.Contains(err.Error(), "object does not exist") {
|
||||
// if the repository is broken, we can continue to the handler code, to show "Settings -> Delete Repository" for end users
|
||||
log.Error("GetBranchCommit: %v", err)
|
||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||
} else {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.IsViewBranch = true
|
||||
} else {
|
||||
} else { // there is a path in request
|
||||
guessLegacyPath := refType == RepoRefUnknown
|
||||
if guessLegacyPath {
|
||||
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo)
|
||||
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
|
||||
} else {
|
||||
refName = getRefName(ctx.Base, ctx.Repo, refType)
|
||||
refName = getRefName(ctx.Base, ctx.Repo, reqPath, refType)
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
||||
|
||||
@@ -33,7 +33,9 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
permissionInRepo.SetUnitsWithDefaultAccessMode(repo.Units, permissionInRepo.AccessMode)
|
||||
}
|
||||
|
||||
cloneLink := repo.CloneLink()
|
||||
// TODO: ideally we should pass "doer" into "ToRepo" to to make CloneLink could generate user-related links
|
||||
// And passing "doer" in will also fix other FIXMEs in this file.
|
||||
cloneLink := repo.CloneLinkGeneral(ctx) // no doer at the moment
|
||||
permission := &api.Permission{
|
||||
Admin: permissionInRepo.AccessMode >= perm.AccessModeAdmin,
|
||||
Push: permissionInRepo.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeWrite,
|
||||
|
||||
@@ -36,6 +36,8 @@ func ToGitServiceType(value string) structs.GitServiceType {
|
||||
return structs.OneDevService
|
||||
case "gitbucket":
|
||||
return structs.GitBucketService
|
||||
case "codebase":
|
||||
return structs.CodebaseService
|
||||
case "codecommit":
|
||||
return structs.CodeCommitService
|
||||
default:
|
||||
|
||||
@@ -21,6 +21,8 @@ func TestToGitServiceType(t *testing.T) {
|
||||
typ string
|
||||
enum int
|
||||
}{{
|
||||
typ: "trash", enum: 1,
|
||||
}, {
|
||||
typ: "github", enum: 2,
|
||||
}, {
|
||||
typ: "gitea", enum: 3,
|
||||
@@ -29,7 +31,13 @@ func TestToGitServiceType(t *testing.T) {
|
||||
}, {
|
||||
typ: "gogs", enum: 5,
|
||||
}, {
|
||||
typ: "trash", enum: 1,
|
||||
typ: "onedev", enum: 6,
|
||||
}, {
|
||||
typ: "gitbucket", enum: 7,
|
||||
}, {
|
||||
typ: "codebase", enum: 8,
|
||||
}, {
|
||||
typ: "codecommit", enum: 9,
|
||||
}}
|
||||
for _, test := range tc {
|
||||
assert.EqualValues(t, test.enum, ToGitServiceType(test.typ))
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConsistencyCheck(t *testing.T) {
|
||||
@@ -21,9 +22,7 @@ func TestConsistencyCheck(t *testing.T) {
|
||||
idx := slices.IndexFunc(checks, func(check consistencyCheck) bool {
|
||||
return check.Name == "Orphaned OAuth2Application without existing User"
|
||||
})
|
||||
if !assert.NotEqual(t, -1, idx) {
|
||||
return
|
||||
}
|
||||
require.NotEqual(t, -1, idx)
|
||||
|
||||
_ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &user.User{})
|
||||
_ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &auth.OAuth2Application{})
|
||||
|
||||
@@ -192,23 +192,18 @@ c,d,e`,
|
||||
|
||||
for n, c := range cases {
|
||||
diff, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.diff), "")
|
||||
if err != nil {
|
||||
t.Errorf("ParsePatch failed: %s", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
var baseReader *csv.Reader
|
||||
if len(c.base) > 0 {
|
||||
baseReader, err = csv_module.CreateReaderAndDetermineDelimiter(nil, strings.NewReader(c.base))
|
||||
if err != nil {
|
||||
t.Errorf("CreateReaderAndDetermineDelimiter failed: %s", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
var headReader *csv.Reader
|
||||
if len(c.head) > 0 {
|
||||
headReader, err = csv_module.CreateReaderAndDetermineDelimiter(nil, strings.NewReader(c.head))
|
||||
if err != nil {
|
||||
t.Errorf("CreateReaderAndDetermineDelimiter failed: %s", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
result, err := CreateCsvDiff(diff.Files[0], baseReader, headReader)
|
||||
|
||||
@@ -360,7 +360,6 @@ type DiffFile struct {
|
||||
IsLFSFile bool
|
||||
IsRenamed bool
|
||||
IsAmbiguous bool
|
||||
IsSubmodule bool
|
||||
Sections []*DiffSection
|
||||
IsIncomplete bool
|
||||
IsIncompleteLineTooLong bool
|
||||
@@ -372,6 +371,9 @@ type DiffFile struct {
|
||||
Language string
|
||||
Mode string
|
||||
OldMode string
|
||||
|
||||
IsSubmodule bool // if IsSubmodule==true, then there must be a SubmoduleDiffInfo
|
||||
SubmoduleDiffInfo *SubmoduleDiffInfo
|
||||
}
|
||||
|
||||
// GetType returns type of diff file.
|
||||
@@ -609,9 +611,8 @@ parsingLoop:
|
||||
if strings.HasPrefix(line, "new mode ") {
|
||||
curFile.Mode = prepareValue(line, "new mode ")
|
||||
}
|
||||
|
||||
if strings.HasSuffix(line, " 160000\n") {
|
||||
curFile.IsSubmodule = true
|
||||
curFile.IsSubmodule, curFile.SubmoduleDiffInfo = true, &SubmoduleDiffInfo{}
|
||||
}
|
||||
case strings.HasPrefix(line, "rename from "):
|
||||
curFile.IsRenamed = true
|
||||
@@ -646,17 +647,17 @@ parsingLoop:
|
||||
curFile.Mode = prepareValue(line, "new file mode ")
|
||||
}
|
||||
if strings.HasSuffix(line, " 160000\n") {
|
||||
curFile.IsSubmodule = true
|
||||
curFile.IsSubmodule, curFile.SubmoduleDiffInfo = true, &SubmoduleDiffInfo{}
|
||||
}
|
||||
case strings.HasPrefix(line, "deleted"):
|
||||
curFile.Type = DiffFileDel
|
||||
curFile.IsDeleted = true
|
||||
if strings.HasSuffix(line, " 160000\n") {
|
||||
curFile.IsSubmodule = true
|
||||
curFile.IsSubmodule, curFile.SubmoduleDiffInfo = true, &SubmoduleDiffInfo{}
|
||||
}
|
||||
case strings.HasPrefix(line, "index"):
|
||||
if strings.HasSuffix(line, " 160000\n") {
|
||||
curFile.IsSubmodule = true
|
||||
curFile.IsSubmodule, curFile.SubmoduleDiffInfo = true, &SubmoduleDiffInfo{}
|
||||
}
|
||||
case strings.HasPrefix(line, "similarity index 100%"):
|
||||
curFile.Type = DiffFileRename
|
||||
@@ -915,6 +916,13 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
|
||||
}
|
||||
}
|
||||
curSection.Lines = append(curSection.Lines, diffLine)
|
||||
|
||||
// Parse submodule additions
|
||||
if curFile.SubmoduleDiffInfo != nil {
|
||||
if ref, found := bytes.CutPrefix(lineBytes, []byte("+Subproject commit ")); found {
|
||||
curFile.SubmoduleDiffInfo.NewRefID = string(bytes.TrimSpace(ref))
|
||||
}
|
||||
}
|
||||
case '-':
|
||||
curFileLinesCount++
|
||||
curFile.Deletion++
|
||||
@@ -936,6 +944,13 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
|
||||
lastLeftIdx = len(curSection.Lines)
|
||||
}
|
||||
curSection.Lines = append(curSection.Lines, diffLine)
|
||||
|
||||
// Parse submodule deletion
|
||||
if curFile.SubmoduleDiffInfo != nil {
|
||||
if ref, found := bytes.CutPrefix(lineBytes, []byte("-Subproject commit ")); found {
|
||||
curFile.SubmoduleDiffInfo.PreviousRefID = string(bytes.TrimSpace(ref))
|
||||
}
|
||||
}
|
||||
case ' ':
|
||||
curFileLinesCount++
|
||||
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||
@@ -1195,6 +1210,11 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
||||
}
|
||||
}
|
||||
|
||||
// Populate Submodule URLs
|
||||
if diffFile.SubmoduleDiffInfo != nil {
|
||||
diffFile.SubmoduleDiffInfo.PopulateURL(diffFile, beforeCommit, commit)
|
||||
}
|
||||
|
||||
if !isVendored.Has() {
|
||||
isVendored = optional.Some(analyze.IsVendor(diffFile.Name))
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
dmp "github.com/sergi/go-diff/diffmatchpatch"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDiffToHTML(t *testing.T) {
|
||||
@@ -628,9 +629,8 @@ func TestDiffLine_GetCommentSide(t *testing.T) {
|
||||
|
||||
func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
|
||||
gitRepo, err := git.OpenRepository(git.DefaultContext, "./testdata/academic-module")
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer gitRepo.Close()
|
||||
for _, behavior := range []git.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} {
|
||||
diffs, err := GetDiff(db.DefaultContext, gitRepo,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitdiff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
type SubmoduleDiffInfo struct {
|
||||
SubmoduleName string
|
||||
SubmoduleFile *git.CommitSubmoduleFile // it might be nil if the submodule is not found or unable to parse
|
||||
NewRefID string
|
||||
PreviousRefID string
|
||||
}
|
||||
|
||||
func (si *SubmoduleDiffInfo) PopulateURL(diffFile *DiffFile, leftCommit, rightCommit *git.Commit) {
|
||||
si.SubmoduleName = diffFile.Name
|
||||
submoduleCommit := rightCommit // If the submodule is added or updated, check at the right commit
|
||||
if diffFile.IsDeleted {
|
||||
submoduleCommit = leftCommit // If the submodule is deleted, check at the left commit
|
||||
}
|
||||
if submoduleCommit == nil {
|
||||
return
|
||||
}
|
||||
|
||||
submodule, err := submoduleCommit.GetSubModule(diffFile.GetDiffFileName())
|
||||
if err != nil {
|
||||
log.Error("Unable to PopulateURL for submodule %q: GetSubModule: %v", diffFile.GetDiffFileName(), err)
|
||||
return // ignore the error, do not cause 500 errors for end users
|
||||
}
|
||||
if submodule != nil {
|
||||
si.SubmoduleFile = git.NewCommitSubmoduleFile(submodule.URL, submoduleCommit.ID.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (si *SubmoduleDiffInfo) CommitRefIDLinkHTML(ctx context.Context, commitID string) template.HTML {
|
||||
webLink := si.SubmoduleFile.SubmoduleWebLink(ctx, commitID)
|
||||
if webLink == nil {
|
||||
return htmlutil.HTMLFormat("%s", base.ShortSha(commitID))
|
||||
}
|
||||
return htmlutil.HTMLFormat(`<a href="%s">%s</a>`, webLink.CommitWebLink, base.ShortSha(commitID))
|
||||
}
|
||||
|
||||
func (si *SubmoduleDiffInfo) CompareRefIDLinkHTML(ctx context.Context) template.HTML {
|
||||
webLink := si.SubmoduleFile.SubmoduleWebLink(ctx, si.PreviousRefID, si.NewRefID)
|
||||
if webLink == nil {
|
||||
return htmlutil.HTMLFormat("%s...%s", base.ShortSha(si.PreviousRefID), base.ShortSha(si.NewRefID))
|
||||
}
|
||||
return htmlutil.HTMLFormat(`<a href="%s">%s...%s</a>`, webLink.CommitWebLink, base.ShortSha(si.PreviousRefID), base.ShortSha(si.NewRefID))
|
||||
}
|
||||
|
||||
func (si *SubmoduleDiffInfo) SubmoduleRepoLinkHTML(ctx context.Context) template.HTML {
|
||||
webLink := si.SubmoduleFile.SubmoduleWebLink(ctx)
|
||||
if webLink == nil {
|
||||
return htmlutil.HTMLFormat("%s", si.SubmoduleName)
|
||||
}
|
||||
return htmlutil.HTMLFormat(`<a href="%s">%s</a>`, webLink.RepoWebLink, si.SubmoduleName)
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitdiff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseSubmoduleInfo(t *testing.T) {
|
||||
type testcase struct {
|
||||
name string
|
||||
gitdiff string
|
||||
infos map[int]SubmoduleDiffInfo
|
||||
}
|
||||
|
||||
tests := []testcase{
|
||||
{
|
||||
name: "added",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
new file mode 100644
|
||||
index 0000000..4ac13c1
|
||||
--- /dev/null
|
||||
+++ b/.gitmodules
|
||||
@@ -0,0 +1,3 @@
|
||||
+[submodule "gitea-mirror"]
|
||||
+ path = gitea-mirror
|
||||
+ url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea-mirror b/gitea-mirror
|
||||
new file mode 160000
|
||||
index 0000000..68972a9
|
||||
--- /dev/null
|
||||
+++ b/gitea-mirror
|
||||
@@ -0,0 +1 @@
|
||||
+Subproject commit 68972a994719ae5c74e28d8fa82fa27c23399bc8
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
1: {NewRefID: "68972a994719ae5c74e28d8fa82fa27c23399bc8"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "updated",
|
||||
gitdiff: `diff --git a/gitea-mirror b/gitea-mirror
|
||||
index 68972a9..c8ffe77 160000
|
||||
--- a/gitea-mirror
|
||||
+++ b/gitea-mirror
|
||||
@@ -1 +1 @@
|
||||
-Subproject commit 68972a994719ae5c74e28d8fa82fa27c23399bc8
|
||||
+Subproject commit c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
0: {
|
||||
PreviousRefID: "68972a994719ae5c74e28d8fa82fa27c23399bc8",
|
||||
NewRefID: "c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rename",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
index 4ac13c1..0510edd 100644
|
||||
--- a/.gitmodules
|
||||
+++ b/.gitmodules
|
||||
@@ -1,3 +1,3 @@
|
||||
[submodule "gitea-mirror"]
|
||||
- path = gitea-mirror
|
||||
+ path = gitea
|
||||
url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea-mirror b/gitea
|
||||
similarity index 100%
|
||||
rename from gitea-mirror
|
||||
rename to gitea
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "deleted",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
index 0510edd..e69de29 100644
|
||||
--- a/.gitmodules
|
||||
+++ b/.gitmodules
|
||||
@@ -1,3 +0,0 @@
|
||||
-[submodule "gitea-mirror"]
|
||||
- path = gitea
|
||||
- url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea b/gitea
|
||||
deleted file mode 160000
|
||||
index c8ffe77..0000000
|
||||
--- a/gitea
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-Subproject commit c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
1: {
|
||||
PreviousRefID: "c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "moved and updated",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
index 0510edd..bced3d8 100644
|
||||
--- a/.gitmodules
|
||||
+++ b/.gitmodules
|
||||
@@ -1,3 +1,3 @@
|
||||
[submodule "gitea-mirror"]
|
||||
- path = gitea
|
||||
+ path = gitea-1.22
|
||||
url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea b/gitea
|
||||
deleted file mode 160000
|
||||
index c8ffe77..0000000
|
||||
--- a/gitea
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-Subproject commit c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d
|
||||
diff --git a/gitea-1.22 b/gitea-1.22
|
||||
new file mode 160000
|
||||
index 0000000..8eefa1f
|
||||
--- /dev/null
|
||||
+++ b/gitea-1.22
|
||||
@@ -0,0 +1 @@
|
||||
+Subproject commit 8eefa1f6dedf2488db2c9e12c916e8e51f673160
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
1: {
|
||||
PreviousRefID: "c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d",
|
||||
},
|
||||
2: {
|
||||
NewRefID: "8eefa1f6dedf2488db2c9e12c916e8e51f673160",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "converted to file",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
index 0510edd..e69de29 100644
|
||||
--- a/.gitmodules
|
||||
+++ b/.gitmodules
|
||||
@@ -1,3 +0,0 @@
|
||||
-[submodule "gitea-mirror"]
|
||||
- path = gitea
|
||||
- url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea b/gitea
|
||||
deleted file mode 160000
|
||||
index c8ffe77..0000000
|
||||
--- a/gitea
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-Subproject commit c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d
|
||||
diff --git a/gitea b/gitea
|
||||
new file mode 100644
|
||||
index 0000000..33a9488
|
||||
--- /dev/null
|
||||
+++ b/gitea
|
||||
@@ -0,0 +1 @@
|
||||
+example
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
1: {
|
||||
PreviousRefID: "c8ffe777cf9c5bb47a38e3e0b3a3b5de6cd8813d",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "converted to submodule",
|
||||
gitdiff: `diff --git a/.gitmodules b/.gitmodules
|
||||
index e69de29..14ee267 100644
|
||||
--- a/.gitmodules
|
||||
+++ b/.gitmodules
|
||||
@@ -0,0 +1,3 @@
|
||||
+[submodule "gitea"]
|
||||
+ path = gitea
|
||||
+ url = https://gitea.com/gitea/gitea-mirror
|
||||
diff --git a/gitea b/gitea
|
||||
deleted file mode 100644
|
||||
index 33a9488..0000000
|
||||
--- a/gitea
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-example
|
||||
diff --git a/gitea b/gitea
|
||||
new file mode 160000
|
||||
index 0000000..68972a9
|
||||
--- /dev/null
|
||||
+++ b/gitea
|
||||
@@ -0,0 +1 @@
|
||||
+Subproject commit 68972a994719ae5c74e28d8fa82fa27c23399bc8
|
||||
`,
|
||||
infos: map[int]SubmoduleDiffInfo{
|
||||
2: {
|
||||
NewRefID: "68972a994719ae5c74e28d8fa82fa27c23399bc8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range tests {
|
||||
testcase := testcase
|
||||
t.Run(testcase.name, func(t *testing.T) {
|
||||
diff, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "")
|
||||
assert.NoError(t, err)
|
||||
|
||||
for i, expected := range testcase.infos {
|
||||
actual := diff.Files[i]
|
||||
assert.NotNil(t, actual)
|
||||
assert.Equal(t, expected, *actual.SubmoduleDiffInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmoduleInfo(t *testing.T) {
|
||||
sdi := &SubmoduleDiffInfo{
|
||||
SubmoduleName: "name",
|
||||
PreviousRefID: "aaaa",
|
||||
NewRefID: "bbbb",
|
||||
}
|
||||
ctx := context.Background()
|
||||
assert.EqualValues(t, "1111", sdi.CommitRefIDLinkHTML(ctx, "1111"))
|
||||
assert.EqualValues(t, "aaaa...bbbb", sdi.CompareRefIDLinkHTML(ctx))
|
||||
assert.EqualValues(t, "name", sdi.SubmoduleRepoLinkHTML(ctx))
|
||||
|
||||
sdi.SubmoduleFile = git.NewCommitSubmoduleFile("https://github.com/owner/repo", "1234")
|
||||
assert.EqualValues(t, `<a href="https://github.com/owner/repo/commit/1111">1111</a>`, sdi.CommitRefIDLinkHTML(ctx, "1111"))
|
||||
assert.EqualValues(t, `<a href="https://github.com/owner/repo/compare/aaaa...bbbb">aaaa...bbbb</a>`, sdi.CompareRefIDLinkHTML(ctx))
|
||||
assert.EqualValues(t, `<a href="https://github.com/owner/repo">name</a>`, sdi.SubmoduleRepoLinkHTML(ctx))
|
||||
}
|
||||
@@ -390,9 +390,7 @@ func TestGenerateMessageIDForIssue(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := generateMessageIDForIssue(tt.args.issue, tt.args.comment, tt.args.actionType)
|
||||
if !strings.HasPrefix(got, tt.prefix) {
|
||||
t.Errorf("generateMessageIDForIssue() = %v, want %v", got, tt.prefix)
|
||||
}
|
||||
assert.True(t, strings.HasPrefix(got, tt.prefix), "%v, want %v", got, tt.prefix)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
base "code.gitea.io/gitea/modules/migration"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGiteaDownloadRepo(t *testing.T) {
|
||||
@@ -29,12 +30,8 @@ func TestGiteaDownloadRepo(t *testing.T) {
|
||||
}
|
||||
|
||||
downloader, err := NewGiteaDownloader(context.Background(), "https://gitea.com", "gitea/test_repo", "", "", giteaToken)
|
||||
if downloader == nil {
|
||||
t.Fatal("NewGitlabDownloader is nil")
|
||||
}
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fatal("NewGitlabDownloader error occur")
|
||||
}
|
||||
require.NoError(t, err, "NewGiteaDownloader error occur")
|
||||
require.NotNil(t, downloader, "NewGiteaDownloader is nil")
|
||||
|
||||
repo, err := downloader.GetRepoInfo()
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
base "code.gitea.io/gitea/modules/migration"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/xanzy/go-gitlab"
|
||||
gitlab "gitlab.com/gitlab-org/api/client-go"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
base "code.gitea.io/gitea/modules/migration"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/xanzy/go-gitlab"
|
||||
gitlab "gitlab.com/gitlab-org/api/client-go"
|
||||
)
|
||||
|
||||
func TestGitlabDownloadRepo(t *testing.T) {
|
||||
|
||||
@@ -32,7 +32,7 @@ const gitShortEmptySha = "0000000"
|
||||
|
||||
// UpdateAddress writes new address to Git repository and database
|
||||
func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error {
|
||||
u, err := giturl.Parse(addr)
|
||||
u, err := giturl.ParseGitURL(addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid addr: %v", err)
|
||||
}
|
||||
@@ -41,13 +41,13 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
||||
repoPath := m.GetRepository(ctx).RepoPath()
|
||||
// Remove old remote
|
||||
_, _, err = git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(addr)
|
||||
_, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,13 +56,13 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
||||
wikiRemotePath := repo_module.WikiRemoteURL(ctx, addr)
|
||||
// Remove old remote of wiki
|
||||
_, _, err = git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: wikiPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd = git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(wikiRemotePath)
|
||||
_, _, err = cmd.RunStdString(&git.RunOpts{Dir: wikiPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,12 +132,11 @@ func createPackageAndVersion(ctx context.Context, pvci *PackageCreationInfo, all
|
||||
}
|
||||
var err error
|
||||
if p, err = packages_model.TryInsertPackage(ctx, p); err != nil {
|
||||
if err == packages_model.ErrDuplicatePackage {
|
||||
packageCreated = false
|
||||
} else {
|
||||
if !errors.Is(err, packages_model.ErrDuplicatePackage) {
|
||||
log.Error("Error inserting package: %v", err)
|
||||
return nil, false, err
|
||||
}
|
||||
packageCreated = false
|
||||
}
|
||||
|
||||
if packageCreated {
|
||||
@@ -163,11 +162,10 @@ func createPackageAndVersion(ctx context.Context, pvci *PackageCreationInfo, all
|
||||
MetadataJSON: string(metadataJSON),
|
||||
}
|
||||
if pv, err = packages_model.GetOrInsertVersion(ctx, pv); err != nil {
|
||||
if err == packages_model.ErrDuplicatePackageVersion {
|
||||
if errors.Is(err, packages_model.ErrDuplicatePackageVersion) && allowDuplicate {
|
||||
versionCreated = false
|
||||
}
|
||||
if err != packages_model.ErrDuplicatePackageVersion || !allowDuplicate {
|
||||
log.Error("Error inserting package: %v", err)
|
||||
} else {
|
||||
log.Error("Error inserting package: %v", err) // other error, or disallowing duplicates
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
@@ -433,7 +431,7 @@ func GetOrCreateInternalPackageVersion(ctx context.Context, ownerID int64, packa
|
||||
}
|
||||
var err error
|
||||
if p, err = packages_model.TryInsertPackage(ctx, p); err != nil {
|
||||
if err != packages_model.ErrDuplicatePackage {
|
||||
if !errors.Is(err, packages_model.ErrDuplicatePackage) {
|
||||
log.Error("Error inserting package: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -282,9 +282,6 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
pr.MergedCommitID = commit.ID.String()
|
||||
pr.MergedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
|
||||
pr.Status = issues_model.PullRequestStatusManuallyMerged
|
||||
merger, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
|
||||
|
||||
// When the commit author is unknown set the BaseRepo owner as merger
|
||||
@@ -297,10 +294,8 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool {
|
||||
}
|
||||
merger = pr.BaseRepo.Owner
|
||||
}
|
||||
pr.Merger = merger
|
||||
pr.MergerID = merger.ID
|
||||
|
||||
if merged, err := SetMerged(ctx, pr); err != nil {
|
||||
if merged, err := SetMerged(ctx, pr, commit.ID.String(), timeutil.TimeStamp(commit.Author.When.Unix()), merger, issues_model.PullRequestStatusManuallyMerged); err != nil {
|
||||
log.Error("%-v setMerged : %v", pr, err)
|
||||
return false
|
||||
} else if !merged {
|
||||
|
||||
+33
-32
@@ -17,6 +17,7 @@ import (
|
||||
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"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -632,14 +633,8 @@ func MergedManually(ctx context.Context, pr *issues_model.PullRequest, doer *use
|
||||
return fmt.Errorf("Wrong commit ID")
|
||||
}
|
||||
|
||||
pr.MergedCommitID = commitID
|
||||
pr.MergedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
|
||||
pr.Status = issues_model.PullRequestStatusManuallyMerged
|
||||
pr.Merger = doer
|
||||
pr.MergerID = doer.ID
|
||||
|
||||
var merged bool
|
||||
if merged, err = SetMerged(ctx, pr); err != nil {
|
||||
if merged, err = SetMerged(ctx, pr, commitID, timeutil.TimeStamp(commit.Author.When.Unix()), doer, issues_model.PullRequestStatusManuallyMerged); err != nil {
|
||||
return err
|
||||
} else if !merged {
|
||||
return fmt.Errorf("SetMerged failed")
|
||||
@@ -658,41 +653,35 @@ func MergedManually(ctx context.Context, pr *issues_model.PullRequest, doer *use
|
||||
}
|
||||
|
||||
// SetMerged sets a pull request to merged and closes the corresponding issue
|
||||
func SetMerged(ctx context.Context, pr *issues_model.PullRequest) (bool, error) {
|
||||
func SetMerged(ctx context.Context, pr *issues_model.PullRequest, mergedCommitID string, mergedTimeStamp timeutil.TimeStamp, merger *user_model.User, mergeStatus issues_model.PullRequestStatus) (bool, error) {
|
||||
if pr.HasMerged {
|
||||
return false, fmt.Errorf("PullRequest[%d] already merged", pr.Index)
|
||||
}
|
||||
|
||||
pr.HasMerged = true
|
||||
pr.MergedCommitID = mergedCommitID
|
||||
pr.MergedUnix = mergedTimeStamp
|
||||
pr.Merger = merger
|
||||
pr.MergerID = merger.ID
|
||||
pr.Status = mergeStatus
|
||||
// reset the conflicted files as there cannot be any if we're merged
|
||||
pr.ConflictedFiles = []string{}
|
||||
|
||||
if pr.MergedCommitID == "" || pr.MergedUnix == 0 || pr.Merger == nil {
|
||||
return false, fmt.Errorf("unable to merge PullRequest[%d], some required fields are empty", pr.Index)
|
||||
}
|
||||
|
||||
pr.HasMerged = true
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
if _, err := sess.Exec("UPDATE `issue` SET `repo_id` = `repo_id` WHERE `id` = ?", pr.IssueID); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if _, err := sess.Exec("UPDATE `pull_request` SET `issue_id` = `issue_id` WHERE `id` = ?", pr.ID); err != nil {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
pr.Issue = nil
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if tmpPr, err := issues_model.GetPullRequestByID(ctx, pr.ID); err != nil {
|
||||
return false, err
|
||||
} else if tmpPr.HasMerged {
|
||||
if pr.Issue.IsClosed {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("PullRequest[%d] already merged but it's associated issue [%d] is not closed", pr.Index, pr.IssueID)
|
||||
} else if pr.Issue.IsClosed {
|
||||
return false, fmt.Errorf("PullRequest[%d] already closed", pr.Index)
|
||||
}
|
||||
|
||||
if err := pr.Issue.LoadRepo(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -701,16 +690,28 @@ func SetMerged(ctx context.Context, pr *issues_model.PullRequest) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if _, err := issues_model.ChangeIssueStatus(ctx, pr.Issue, pr.Merger, true, true); err != nil {
|
||||
// Removing an auto merge pull and ignore if not exist
|
||||
if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) {
|
||||
return false, fmt.Errorf("DeleteScheduledAutoMerge[%d]: %v", pr.ID, err)
|
||||
}
|
||||
|
||||
// Set issue as closed
|
||||
if _, err := issues_model.SetIssueAsClosed(ctx, pr.Issue, pr.Merger, true); err != nil {
|
||||
return false, fmt.Errorf("ChangeIssueStatus: %w", err)
|
||||
}
|
||||
|
||||
// reset the conflicted files as there cannot be any if we're merged
|
||||
pr.ConflictedFiles = []string{}
|
||||
|
||||
// We need to save all of the data used to compute this merge as it may have already been changed by TestPatch. FIXME: need to set some state to prevent TestPatch from running whilst we are merging.
|
||||
if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merge_base, merged_commit_id, merger_id, merged_unix, conflicted_files").Update(pr); err != nil {
|
||||
if cnt, err := db.GetEngine(ctx).Where("id = ?", pr.ID).
|
||||
And("has_merged = ?", false).
|
||||
Cols("has_merged, status, merge_base, merged_commit_id, merger_id, merged_unix, conflicted_files").
|
||||
Update(pr); err != nil {
|
||||
return false, fmt.Errorf("failed to update pr[%d]: %w", pr.ID, err)
|
||||
} else if cnt != 1 {
|
||||
return false, issues_model.ErrIssueAlreadyChanged
|
||||
}
|
||||
|
||||
if err := committer.Commit(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
||||
+62
-52
@@ -6,6 +6,7 @@ package pull
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -265,6 +266,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
|
||||
ID: pr.Issue.ID,
|
||||
RepoID: pr.Issue.RepoID,
|
||||
Index: pr.Issue.Index,
|
||||
IsPull: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,33 +637,9 @@ func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
type errlist []error
|
||||
|
||||
func (errs errlist) Error() string {
|
||||
if len(errs) > 0 {
|
||||
var buf strings.Builder
|
||||
for i, err := range errs {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(err.Error())
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// RetargetChildrenOnMerge retarget children pull requests on merge if possible
|
||||
func RetargetChildrenOnMerge(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) error {
|
||||
if setting.Repository.PullRequest.RetargetChildrenOnMerge && pr.BaseRepoID == pr.HeadRepoID {
|
||||
return RetargetBranchPulls(ctx, doer, pr.HeadRepoID, pr.HeadBranch, pr.BaseBranch)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RetargetBranchPulls change target branch for all pull requests whose base branch is the branch
|
||||
// retargetBranchPulls change target branch for all pull requests whose base branch is the branch
|
||||
// Both branch and targetBranch must be in the same repo (for security reasons)
|
||||
func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch, targetBranch string) error {
|
||||
func retargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch, targetBranch string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -671,7 +649,7 @@ func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6
|
||||
return err
|
||||
}
|
||||
|
||||
var errs errlist
|
||||
var errs []error
|
||||
for _, pr := range prs {
|
||||
if err = pr.Issue.LoadRepo(ctx); err != nil {
|
||||
errs = append(errs, err)
|
||||
@@ -681,40 +659,75 @@ func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// CloseBranchPulls close all the pull requests who's head branch is the branch
|
||||
func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repoID, branch)
|
||||
// AdjustPullsCausedByBranchDeleted close all the pull requests who's head branch is the branch
|
||||
// Or Close all the plls who's base branch is the branch if setting.Repository.PullRequest.RetargetChildrenOnMerge is false.
|
||||
// If it's true, Retarget all these pulls to the default branch.
|
||||
func AdjustPullsCausedByBranchDeleted(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, branch string) error {
|
||||
// branch as head branch
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repo.ID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prs = append(prs, prs2...)
|
||||
if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
issues_model.PullRequestList(prs).SetHeadRepo(repo)
|
||||
if err := issues_model.PullRequestList(prs).LoadRepositories(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var errs errlist
|
||||
var errs []error
|
||||
for _, pr := range prs {
|
||||
if err = issue_service.CloseIssue(ctx, pr.Issue, doer, ""); err != nil && !issues_model.IsErrPullWasClosed(err) && !issues_model.IsErrDependenciesLeft(err) {
|
||||
if err = issue_service.CloseIssue(ctx, pr.Issue, doer, ""); err != nil && !issues_model.IsErrIssueIsClosed(err) && !issues_model.IsErrDependenciesLeft(err) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if err == nil {
|
||||
if err := issues_model.AddDeletePRBranchComment(ctx, doer, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
|
||||
log.Error("AddDeletePRBranchComment: %v", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
|
||||
if setting.Repository.PullRequest.RetargetChildrenOnMerge {
|
||||
if err := retargetBranchPulls(ctx, doer, repo.ID, branch, repo.DefaultBranch); err != nil {
|
||||
log.Error("retargetBranchPulls failed: %v", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
return nil
|
||||
|
||||
// branch as base branch
|
||||
prs, err = issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repo.ID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
issues_model.PullRequestList(prs).SetBaseRepo(repo)
|
||||
if err := issues_model.PullRequestList(prs).LoadRepositories(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errs = nil
|
||||
for _, pr := range prs {
|
||||
if err = issues_model.AddDeletePRBranchComment(ctx, doer, pr.BaseRepo, pr.Issue.ID, pr.BaseBranch); err != nil {
|
||||
log.Error("AddDeletePRBranchComment: %v", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if err == nil {
|
||||
if err = issue_service.CloseIssue(ctx, pr.Issue, doer, ""); err != nil && !issues_model.IsErrIssueIsClosed(err) && !issues_model.IsErrDependenciesLeft(err) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// CloseRepoBranchesPulls close all pull requests which head branches are in the given repository, but only whose base repo is not in the given repository
|
||||
@@ -724,7 +737,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
|
||||
return err
|
||||
}
|
||||
|
||||
var errs errlist
|
||||
var errs []error
|
||||
for _, branch := range branches {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repo.ID, branch.Name)
|
||||
if err != nil {
|
||||
@@ -741,16 +754,13 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
|
||||
if pr.BaseRepoID == repo.ID {
|
||||
continue
|
||||
}
|
||||
if err = issue_service.CloseIssue(ctx, pr.Issue, doer, ""); err != nil && !issues_model.IsErrPullWasClosed(err) {
|
||||
if err = issue_service.CloseIssue(ctx, pr.Issue, doer, ""); err != nil && !issues_model.IsErrIssueIsClosed(err) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
return nil
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
var commitMessageTrailersPattern = regexp.MustCompile(`(?:^|\n\n)(?:[\w-]+[ \t]*:[^\n]+\n*(?:[ \t]+[^\n]+\n*)*)+$`)
|
||||
|
||||
@@ -489,7 +489,7 @@ func CanDeleteBranch(ctx context.Context, repo *repo_model.Repository, branchNam
|
||||
}
|
||||
|
||||
// DeleteBranch delete branch
|
||||
func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error {
|
||||
func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string, pr *issues_model.PullRequest) error {
|
||||
err := repo.MustNotBeArchived()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -519,6 +519,12 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
|
||||
}
|
||||
}
|
||||
|
||||
if pr != nil {
|
||||
if err := issues_model.AddDeletePRBranchComment(ctx, doer, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("DeleteBranch: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
||||
Force: true,
|
||||
})
|
||||
|
||||
@@ -79,7 +79,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
|
||||
return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.Readme, err)
|
||||
}
|
||||
|
||||
cloneLink := repo.CloneLink()
|
||||
cloneLink := repo.CloneLink(ctx, nil /* no doer so do not generate user-related SSH link */)
|
||||
match := map[string]string{
|
||||
"Name": repo.Name,
|
||||
"Description": repo.Description,
|
||||
|
||||
@@ -51,7 +51,7 @@ var defaultTransformers = []transformer{
|
||||
{Name: "TITLE", Transform: util.ToTitleCase},
|
||||
}
|
||||
|
||||
func generateExpansion(src string, templateRepo, generateRepo *repo_model.Repository, sanitizeFileName bool) string {
|
||||
func generateExpansion(ctx context.Context, src string, templateRepo, generateRepo *repo_model.Repository, sanitizeFileName bool) string {
|
||||
year, month, day := time.Now().Date()
|
||||
expansions := []expansion{
|
||||
{Name: "YEAR", Value: strconv.Itoa(year), Transformers: nil},
|
||||
@@ -66,10 +66,10 @@ func generateExpansion(src string, templateRepo, generateRepo *repo_model.Reposi
|
||||
{Name: "TEMPLATE_OWNER", Value: templateRepo.OwnerName, Transformers: defaultTransformers},
|
||||
{Name: "REPO_LINK", Value: generateRepo.Link(), Transformers: nil},
|
||||
{Name: "TEMPLATE_LINK", Value: templateRepo.Link(), Transformers: nil},
|
||||
{Name: "REPO_HTTPS_URL", Value: generateRepo.CloneLink().HTTPS, Transformers: nil},
|
||||
{Name: "TEMPLATE_HTTPS_URL", Value: templateRepo.CloneLink().HTTPS, Transformers: nil},
|
||||
{Name: "REPO_SSH_URL", Value: generateRepo.CloneLink().SSH, Transformers: nil},
|
||||
{Name: "TEMPLATE_SSH_URL", Value: templateRepo.CloneLink().SSH, Transformers: nil},
|
||||
{Name: "REPO_HTTPS_URL", Value: generateRepo.CloneLinkGeneral(ctx).HTTPS, Transformers: nil},
|
||||
{Name: "TEMPLATE_HTTPS_URL", Value: templateRepo.CloneLinkGeneral(ctx).HTTPS, Transformers: nil},
|
||||
{Name: "REPO_SSH_URL", Value: generateRepo.CloneLinkGeneral(ctx).SSH, Transformers: nil},
|
||||
{Name: "TEMPLATE_SSH_URL", Value: templateRepo.CloneLinkGeneral(ctx).SSH, Transformers: nil},
|
||||
}
|
||||
|
||||
expansionMap := make(map[string]string)
|
||||
@@ -138,7 +138,7 @@ func readGiteaTemplateFile(tmpDir string) (*GiteaTemplate, error) {
|
||||
return &GiteaTemplate{Path: gtPath, Content: content}, nil
|
||||
}
|
||||
|
||||
func processGiteaTemplateFile(tmpDir string, templateRepo, generateRepo *repo_model.Repository, giteaTemplateFile *GiteaTemplate) error {
|
||||
func processGiteaTemplateFile(ctx context.Context, tmpDir string, templateRepo, generateRepo *repo_model.Repository, giteaTemplateFile *GiteaTemplate) error {
|
||||
if err := util.Remove(giteaTemplateFile.Path); err != nil {
|
||||
return fmt.Errorf("remove .giteatemplate: %w", err)
|
||||
}
|
||||
@@ -163,12 +163,12 @@ func processGiteaTemplateFile(tmpDir string, templateRepo, generateRepo *repo_mo
|
||||
return err
|
||||
}
|
||||
|
||||
generatedContent := []byte(generateExpansion(string(content), templateRepo, generateRepo, false))
|
||||
generatedContent := []byte(generateExpansion(ctx, string(content), templateRepo, generateRepo, false))
|
||||
if err := os.WriteFile(path, generatedContent, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
substPath := filepath.FromSlash(filepath.Join(tmpDirSlash, generateExpansion(base, templateRepo, generateRepo, true)))
|
||||
substPath := filepath.FromSlash(filepath.Join(tmpDirSlash, generateExpansion(ctx, base, templateRepo, generateRepo, true)))
|
||||
|
||||
// Create parent subdirectories if needed or continue silently if it exists
|
||||
if err = os.MkdirAll(filepath.Dir(substPath), 0o755); err != nil {
|
||||
@@ -226,7 +226,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
|
||||
}
|
||||
|
||||
if giteaTemplateFile != nil {
|
||||
err = processGiteaTemplateFile(tmpDir, templateRepo, generateRepo, giteaTemplateFile)
|
||||
err = processGiteaTemplateFile(ctx, tmpDir, templateRepo, generateRepo, giteaTemplateFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@@ -254,10 +253,10 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
||||
func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error {
|
||||
cmd := git.NewCommand(ctx, "remote", "rm", "origin")
|
||||
// if the origin does not exist
|
||||
_, stderr, err := cmd.RunStdString(&git.RunOpts{
|
||||
_, _, err := cmd.RunStdString(&git.RunOpts{
|
||||
Dir: repoPath,
|
||||
})
|
||||
if err != nil && !strings.HasPrefix(stderr, "fatal: No such remote") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -276,7 +275,7 @@ func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo
|
||||
}
|
||||
|
||||
_, _, err := git.NewCommand(ctx, "remote", "rm", "origin").RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
if err != nil && !git.IsRemoteNotExistError(err) {
|
||||
return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +275,8 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||
}
|
||||
} else {
|
||||
notify_service.DeleteRef(ctx, pusher, repo, opts.RefFullName)
|
||||
if err = pull_service.CloseBranchPulls(ctx, pusher, repo.ID, branch); err != nil {
|
||||
|
||||
if err := pull_service.AdjustPullsCausedByBranchDeleted(ctx, pusher, repo, branch); err != nil {
|
||||
// close all related pulls
|
||||
log.Error("close related pull request failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
_ "code.gitea.io/gitea/models/actions"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -166,9 +167,8 @@ func TestRepository_AddWikiPage(t *testing.T) {
|
||||
assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg))
|
||||
// Now need to show that the page has been added:
|
||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer gitRepo.Close()
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
@@ -238,9 +238,8 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
||||
|
||||
// Now need to show that the page has been added:
|
||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer gitRepo.Close()
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
@@ -253,9 +252,8 @@ func TestPrepareWikiFileName(t *testing.T) {
|
||||
unittest.PrepareTestEnv(t)
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer gitRepo.Close()
|
||||
|
||||
tests := []struct {
|
||||
@@ -307,9 +305,8 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
gitRepo, err := git.OpenRepository(git.DefaultContext, tmpDir)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer gitRepo.Close()
|
||||
|
||||
existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home")
|
||||
|
||||
Reference in new issue
Block a user