mirror of
https://github.com/go-gitea/gitea
synced 2025-12-07 13:28:25 +00:00
Merge branch 'main' of github.com:go-gitea/gitea into api-repo-actions
This commit is contained in:
@@ -20,7 +20,7 @@ func TestCreateAuthorizationToken(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, "", token)
|
||||
claims := jwt.MapClaims{}
|
||||
_, err = jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (interface{}, error) {
|
||||
_, err = jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (any, error) {
|
||||
return setting.GetGeneralTokenSigningSecret(), nil
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
|
||||
|
||||
"github.com/nektos/act/pkg/jobparser"
|
||||
)
|
||||
@@ -122,18 +123,13 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
|
||||
if err != nil {
|
||||
return fmt.Errorf("HashTypeInterfaceFromHashString: %w", err)
|
||||
}
|
||||
if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{
|
||||
Repo: repo,
|
||||
SHA: commitID,
|
||||
Creator: creator,
|
||||
CommitStatus: &git_model.CommitStatus{
|
||||
SHA: sha,
|
||||
TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), index),
|
||||
Description: description,
|
||||
Context: ctxname,
|
||||
CreatorID: creator.ID,
|
||||
State: state,
|
||||
},
|
||||
if err := commitstatus_service.CreateCommitStatus(ctx, repo, creator, commitID.String(), &git_model.CommitStatus{
|
||||
SHA: sha,
|
||||
TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), index),
|
||||
Description: description,
|
||||
Context: ctxname,
|
||||
CreatorID: creator.ID,
|
||||
State: state,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("NewCommitStatus: %w", err)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func (n *actionsNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
|
||||
newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{
|
||||
Action: api.HookIssueOpened,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, issue.Poster, nil),
|
||||
}).Notify(withMethod(ctx, "NewIssue"))
|
||||
@@ -89,7 +89,7 @@ func (n *actionsNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
|
||||
WithPayload(&api.IssuePayload{
|
||||
Action: api.HookIssueEdited,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}).
|
||||
@@ -127,7 +127,7 @@ func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
|
||||
}
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues
|
||||
WithPayload(&api.IssuePayload{
|
||||
Action: action,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}).
|
||||
@@ -293,7 +293,7 @@ func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, commen
|
||||
|
||||
payload := &api.IssueCommentPayload{
|
||||
Action: action,
|
||||
Issue: convert.ToAPIIssue(ctx, comment.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
|
||||
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
|
||||
@@ -525,12 +525,9 @@ func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository)
|
||||
}
|
||||
|
||||
// We need a notifyInput to call handleSchedules
|
||||
// Here we use the commit author as the Doer of the notifyInput
|
||||
commitUser, err := user_model.GetUserByEmail(ctx, commit.Author.Email)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get user by email: %w", err)
|
||||
}
|
||||
notifyInput := newNotifyInput(repo, commitUser, webhook_module.HookEventSchedule)
|
||||
// if repo is a mirror, commit author maybe an external user,
|
||||
// so we use action user as the Doer of the notifyInput
|
||||
notifyInput := newNotifyInput(repo, user_model.NewActionsUser(), webhook_module.HookEventSchedule)
|
||||
|
||||
return handleSchedules(ctx, scheduleWorkflows, commit, notifyInput, repo.DefaultBranch)
|
||||
}
|
||||
|
||||
+17
-9
@@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
)
|
||||
@@ -145,10 +146,14 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
||||
log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID)
|
||||
|
||||
results = append(results, private.HookProcReceiveRefResult{
|
||||
Ref: pr.GetGitRefName(),
|
||||
OriginalRef: opts.RefFullNames[i],
|
||||
OldOID: objectFormat.EmptyObjectID().String(),
|
||||
NewOID: opts.NewCommitIDs[i],
|
||||
Ref: pr.GetGitRefName(),
|
||||
OriginalRef: opts.RefFullNames[i],
|
||||
OldOID: objectFormat.EmptyObjectID().String(),
|
||||
NewOID: opts.NewCommitIDs[i],
|
||||
IsCreatePR: true,
|
||||
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
|
||||
ShouldShowMessage: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx),
|
||||
HeadBranch: headBranch,
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -208,11 +213,14 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
||||
isForcePush := comment != nil && comment.IsForcePush
|
||||
|
||||
results = append(results, private.HookProcReceiveRefResult{
|
||||
OldOID: oldCommitID,
|
||||
NewOID: opts.NewCommitIDs[i],
|
||||
Ref: pr.GetGitRefName(),
|
||||
OriginalRef: opts.RefFullNames[i],
|
||||
IsForcePush: isForcePush,
|
||||
OldOID: oldCommitID,
|
||||
NewOID: opts.NewCommitIDs[i],
|
||||
Ref: pr.GetGitRefName(),
|
||||
OriginalRef: opts.RefFullNames[i],
|
||||
IsForcePush: isForcePush,
|
||||
IsCreatePR: false,
|
||||
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
|
||||
ShouldShowMessage: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
session_module "code.gitea.io/gitea/modules/session"
|
||||
|
||||
chiSession "gitea.com/go-chi/session"
|
||||
"github.com/gorilla/sessions"
|
||||
@@ -65,7 +66,7 @@ func (st *SessionsStore) Save(r *http.Request, w http.ResponseWriter, session *s
|
||||
chiStore := chiSession.GetSession(r)
|
||||
|
||||
if session.IsNew {
|
||||
_, _ = chiSession.RegenerateSession(w, r)
|
||||
_, _ = session_module.RegenerateSession(w, r)
|
||||
session.IsNew = false
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
mc "code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/httpcache"
|
||||
@@ -21,15 +21,13 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
web_types "code.gitea.io/gitea/modules/web/types"
|
||||
|
||||
"gitea.com/go-chi/cache"
|
||||
)
|
||||
|
||||
// APIContext is a specific context for API service
|
||||
type APIContext struct {
|
||||
*Base
|
||||
|
||||
Cache cache.Cache
|
||||
Cache cache.StringCache
|
||||
|
||||
Doer *user_model.User // current signed-in user
|
||||
IsSigned bool
|
||||
@@ -217,7 +215,7 @@ func APIContexter() func(http.Handler) http.Handler {
|
||||
base, baseCleanUp := NewBaseContext(w, req)
|
||||
ctx := &APIContext{
|
||||
Base: base,
|
||||
Cache: mc.GetCache(),
|
||||
Cache: cache.GetCache(),
|
||||
Repo: &Repository{PullRequest: &PullRequest{}},
|
||||
Org: &APIOrganization{},
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func GetImageCaptcha() *captcha.Captcha {
|
||||
cpt = captcha.NewCaptcha(captcha.Options{
|
||||
SubURL: setting.AppSubURL,
|
||||
})
|
||||
cpt.Store = cache.GetCache()
|
||||
cpt.Store = cache.GetCache().ChiCache()
|
||||
})
|
||||
return cpt
|
||||
}
|
||||
@@ -79,11 +79,11 @@ func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
|
||||
case setting.CfTurnstile:
|
||||
valid, err = turnstile.Verify(ctx, ctx.Req.Form.Get(cfTurnstileResponseField))
|
||||
default:
|
||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("unknown Captcha Type: %s", setting.Service.CaptchaType))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Debug("%v", err)
|
||||
log.Debug("Captcha Verify failed: %v", err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
mc "code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/httpcache"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
web_types "code.gitea.io/gitea/modules/web/types"
|
||||
|
||||
"gitea.com/go-chi/cache"
|
||||
"gitea.com/go-chi/session"
|
||||
)
|
||||
|
||||
@@ -46,7 +45,7 @@ type Context struct {
|
||||
Render Render
|
||||
PageData map[string]any // data used by JavaScript modules in one page, it's `window.config.pageData`
|
||||
|
||||
Cache cache.Cache
|
||||
Cache cache.StringCache
|
||||
Csrf CSRFProtector
|
||||
Flash *middleware.Flash
|
||||
Session session.Store
|
||||
@@ -102,6 +101,19 @@ func NewTemplateContextForWeb(ctx *Context) TemplateContext {
|
||||
tmplCtx := NewTemplateContext(ctx)
|
||||
tmplCtx["Locale"] = ctx.Base.Locale
|
||||
tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx)
|
||||
tmplCtx["RootData"] = ctx.Data
|
||||
tmplCtx["Consts"] = map[string]any{
|
||||
"RepoUnitTypeCode": unit.TypeCode,
|
||||
"RepoUnitTypeIssues": unit.TypeIssues,
|
||||
"RepoUnitTypePullRequests": unit.TypePullRequests,
|
||||
"RepoUnitTypeReleases": unit.TypeReleases,
|
||||
"RepoUnitTypeWiki": unit.TypeWiki,
|
||||
"RepoUnitTypeExternalWiki": unit.TypeExternalWiki,
|
||||
"RepoUnitTypeExternalTracker": unit.TypeExternalTracker,
|
||||
"RepoUnitTypeProjects": unit.TypeProjects,
|
||||
"RepoUnitTypePackages": unit.TypePackages,
|
||||
"RepoUnitTypeActions": unit.TypeActions,
|
||||
}
|
||||
return tmplCtx
|
||||
}
|
||||
|
||||
@@ -111,7 +123,7 @@ func NewWebContext(base *Base, render Render, session session.Store) *Context {
|
||||
Render: render,
|
||||
Session: session,
|
||||
|
||||
Cache: mc.GetCache(),
|
||||
Cache: cache.GetCache(),
|
||||
Link: setting.AppSubURL + strings.TrimSuffix(base.Req.URL.EscapedPath(), "/"),
|
||||
Repo: &Repository{PullRequest: &PullRequest{}},
|
||||
Org: &Organization{},
|
||||
|
||||
@@ -383,7 +383,6 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
||||
ctx.NotFound("no access right", nil)
|
||||
return
|
||||
}
|
||||
ctx.Data["HasAccess"] = true
|
||||
ctx.Data["Permission"] = &ctx.Repo.Permission
|
||||
|
||||
if repo.IsMirror {
|
||||
@@ -1052,19 +1051,3 @@ func GitHookService() func(ctx *Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UnitTypes returns a middleware to set unit types to context variables.
|
||||
func UnitTypes() func(ctx *Context) {
|
||||
return func(ctx *Context) {
|
||||
ctx.Data["UnitTypeCode"] = unit_model.TypeCode
|
||||
ctx.Data["UnitTypeIssues"] = unit_model.TypeIssues
|
||||
ctx.Data["UnitTypePullRequests"] = unit_model.TypePullRequests
|
||||
ctx.Data["UnitTypeReleases"] = unit_model.TypeReleases
|
||||
ctx.Data["UnitTypeWiki"] = unit_model.TypeWiki
|
||||
ctx.Data["UnitTypeExternalWiki"] = unit_model.TypeExternalWiki
|
||||
ctx.Data["UnitTypeExternalTracker"] = unit_model.TypeExternalTracker
|
||||
ctx.Data["UnitTypeProjects"] = unit_model.TypeProjects
|
||||
ctx.Data["UnitTypePackages"] = unit_model.TypePackages
|
||||
ctx.Data["UnitTypeActions"] = unit_model.TypeActions
|
||||
}
|
||||
}
|
||||
|
||||
+36
-22
@@ -22,6 +22,7 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
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/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@@ -106,33 +107,46 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
// getWhitelistEntities returns the names of the entities that are in the whitelist
|
||||
func getWhitelistEntities[T *user_model.User | *organization.Team](entities []T, whitelistIDs []int64) []string {
|
||||
whitelistUserIDsSet := container.SetOf(whitelistIDs...)
|
||||
whitelistNames := make([]string, 0)
|
||||
for _, entity := range entities {
|
||||
switch v := any(entity).(type) {
|
||||
case *user_model.User:
|
||||
if whitelistUserIDsSet.Contains(v.ID) {
|
||||
whitelistNames = append(whitelistNames, v.Name)
|
||||
}
|
||||
case *organization.Team:
|
||||
if whitelistUserIDsSet.Contains(v.ID) {
|
||||
whitelistNames = append(whitelistNames, v.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return whitelistNames
|
||||
}
|
||||
|
||||
// ToBranchProtection convert a ProtectedBranch to api.BranchProtection
|
||||
func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch) *api.BranchProtection {
|
||||
pushWhitelistUsernames, err := user_model.GetUserNamesByIDs(ctx, bp.WhitelistUserIDs)
|
||||
func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo *repo_model.Repository) *api.BranchProtection {
|
||||
readers, err := access_model.GetRepoReaders(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("GetUserNamesByIDs (WhitelistUserIDs): %v", err)
|
||||
log.Error("GetRepoReaders: %v", err)
|
||||
}
|
||||
mergeWhitelistUsernames, err := user_model.GetUserNamesByIDs(ctx, bp.MergeWhitelistUserIDs)
|
||||
|
||||
pushWhitelistUsernames := getWhitelistEntities(readers, bp.WhitelistUserIDs)
|
||||
mergeWhitelistUsernames := getWhitelistEntities(readers, bp.MergeWhitelistUserIDs)
|
||||
approvalsWhitelistUsernames := getWhitelistEntities(readers, bp.ApprovalsWhitelistUserIDs)
|
||||
|
||||
teamReaders, err := organization.OrgFromUser(repo.Owner).TeamsWithAccessToRepo(ctx, repo.ID, perm.AccessModeRead)
|
||||
if err != nil {
|
||||
log.Error("GetUserNamesByIDs (MergeWhitelistUserIDs): %v", err)
|
||||
}
|
||||
approvalsWhitelistUsernames, err := user_model.GetUserNamesByIDs(ctx, bp.ApprovalsWhitelistUserIDs)
|
||||
if err != nil {
|
||||
log.Error("GetUserNamesByIDs (ApprovalsWhitelistUserIDs): %v", err)
|
||||
}
|
||||
pushWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.WhitelistTeamIDs)
|
||||
if err != nil {
|
||||
log.Error("GetTeamNamesByID (WhitelistTeamIDs): %v", err)
|
||||
}
|
||||
mergeWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.MergeWhitelistTeamIDs)
|
||||
if err != nil {
|
||||
log.Error("GetTeamNamesByID (MergeWhitelistTeamIDs): %v", err)
|
||||
}
|
||||
approvalsWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.ApprovalsWhitelistTeamIDs)
|
||||
if err != nil {
|
||||
log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err)
|
||||
log.Error("Repo.Owner.TeamsWithAccessToRepo: %v", err)
|
||||
}
|
||||
|
||||
pushWhitelistTeams := getWhitelistEntities(teamReaders, bp.WhitelistTeamIDs)
|
||||
mergeWhitelistTeams := getWhitelistEntities(teamReaders, bp.MergeWhitelistTeamIDs)
|
||||
approvalsWhitelistTeams := getWhitelistEntities(teamReaders, bp.ApprovalsWhitelistTeamIDs)
|
||||
|
||||
branchName := ""
|
||||
if !git_model.IsRuleNameSpecial(bp.RuleName) {
|
||||
branchName = bp.RuleName
|
||||
@@ -346,7 +360,7 @@ func ToTeams(ctx context.Context, teams []*organization.Team, loadOrgs bool) ([]
|
||||
Description: t.Description,
|
||||
IncludesAllRepositories: t.IncludesAllRepositories,
|
||||
CanCreateOrgRepo: t.CanCreateOrgRepo,
|
||||
Permission: t.AccessMode.String(),
|
||||
Permission: t.AccessMode.ToString(),
|
||||
Units: t.GetUnitNames(),
|
||||
UnitsMap: t.GetUnitsMap(),
|
||||
}
|
||||
|
||||
+14
-14
@@ -18,19 +18,19 @@ import (
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
)
|
||||
|
||||
func ToIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, issue, WebAssetDownloadURL)
|
||||
func ToIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, doer, issue, WebAssetDownloadURL)
|
||||
}
|
||||
|
||||
// ToAPIIssue converts an Issue to API format
|
||||
// it assumes some fields assigned with values:
|
||||
// Required - Poster, Labels,
|
||||
// Optional - Milestone, Assignee, PullRequest
|
||||
func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, issue, APIAssetDownloadURL)
|
||||
func ToAPIIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
|
||||
return toIssue(ctx, doer, issue, APIAssetDownloadURL)
|
||||
}
|
||||
|
||||
func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
|
||||
func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
|
||||
if err := issue.LoadLabels(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
|
||||
apiIssue := &api.Issue{
|
||||
ID: issue.ID,
|
||||
Index: issue.Index,
|
||||
Poster: ToUser(ctx, issue.Poster, nil),
|
||||
Poster: ToUser(ctx, issue.Poster, doer),
|
||||
Title: issue.Title,
|
||||
Body: issue.Content,
|
||||
Attachments: toAttachments(issue.Repo, issue.Attachments, getDownloadURL),
|
||||
@@ -114,25 +114,25 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
|
||||
}
|
||||
|
||||
// ToIssueList converts an IssueList to API format
|
||||
func ToIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue {
|
||||
func ToIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
|
||||
result := make([]*api.Issue, len(il))
|
||||
for i := range il {
|
||||
result[i] = ToIssue(ctx, il[i])
|
||||
result[i] = ToIssue(ctx, doer, il[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ToAPIIssueList converts an IssueList to API format
|
||||
func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue {
|
||||
func ToAPIIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
|
||||
result := make([]*api.Issue, len(il))
|
||||
for i := range il {
|
||||
result[i] = ToAPIIssue(ctx, il[i])
|
||||
result[i] = ToAPIIssue(ctx, doer, il[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ToTrackedTime converts TrackedTime to API format
|
||||
func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.TrackedTime) {
|
||||
func ToTrackedTime(ctx context.Context, doer *user_model.User, t *issues_model.TrackedTime) (apiT *api.TrackedTime) {
|
||||
apiT = &api.TrackedTime{
|
||||
ID: t.ID,
|
||||
IssueID: t.IssueID,
|
||||
@@ -141,7 +141,7 @@ func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.
|
||||
Created: t.Created,
|
||||
}
|
||||
if t.Issue != nil {
|
||||
apiT.Issue = ToAPIIssue(ctx, t.Issue)
|
||||
apiT.Issue = ToAPIIssue(ctx, doer, t.Issue)
|
||||
}
|
||||
if t.User != nil {
|
||||
apiT.UserName = t.User.Name
|
||||
@@ -192,10 +192,10 @@ func ToStopWatches(ctx context.Context, sws []*issues_model.Stopwatch) (api.Stop
|
||||
}
|
||||
|
||||
// ToTrackedTimeList converts TrackedTimeList to API format
|
||||
func ToTrackedTimeList(ctx context.Context, tl issues_model.TrackedTimeList) api.TrackedTimeList {
|
||||
func ToTrackedTimeList(ctx context.Context, doer *user_model.User, tl issues_model.TrackedTimeList) api.TrackedTimeList {
|
||||
result := make([]*api.TrackedTime, 0, len(tl))
|
||||
for _, t := range tl {
|
||||
result = append(result, ToTrackedTime(ctx, t))
|
||||
result = append(result, ToTrackedTime(ctx, doer, t))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
||||
return nil
|
||||
}
|
||||
|
||||
comment.TrackedTime = ToTrackedTime(ctx, c.Time)
|
||||
comment.TrackedTime = ToTrackedTime(ctx, doer, c.Time)
|
||||
}
|
||||
|
||||
if c.RefIssueID != 0 {
|
||||
@@ -129,7 +129,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
||||
log.Error("GetIssueByID(%d): %v", c.RefIssueID, err)
|
||||
return nil
|
||||
}
|
||||
comment.RefIssue = ToAPIIssue(ctx, issue)
|
||||
comment.RefIssue = ToAPIIssue(ctx, doer, issue)
|
||||
}
|
||||
|
||||
if c.RefCommentID != 0 {
|
||||
@@ -180,7 +180,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
||||
}
|
||||
|
||||
if c.DependentIssue != nil {
|
||||
comment.DependentIssue = ToAPIIssue(ctx, c.DependentIssue)
|
||||
comment.DependentIssue = ToAPIIssue(ctx, doer, c.DependentIssue)
|
||||
}
|
||||
|
||||
return comment
|
||||
|
||||
@@ -33,7 +33,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
||||
return nil
|
||||
}
|
||||
|
||||
apiIssue := ToAPIIssue(ctx, pr.Issue)
|
||||
apiIssue := ToAPIIssue(ctx, doer, pr.Issue)
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
|
||||
@@ -25,12 +25,13 @@ func ToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo a
|
||||
func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission, isParent bool) *api.Repository {
|
||||
var parent *api.Repository
|
||||
|
||||
if permissionInRepo.Units == nil && permissionInRepo.UnitsMode == nil {
|
||||
// If Units and UnitsMode are both nil, it means that it's a hard coded permission,
|
||||
// like access_model.Permission{AccessMode: perm.AccessModeAdmin}.
|
||||
// So we need to load units for the repo, or UnitAccessMode will always return perm.AccessModeNone.
|
||||
if !permissionInRepo.HasUnits() && permissionInRepo.AccessMode > perm.AccessModeNone {
|
||||
// If units is empty, it means that it's a hard-coded permission, like access_model.Permission{AccessMode: perm.AccessModeAdmin}
|
||||
// So we need to load units for the repo, otherwise UnitAccessMode will just return perm.AccessModeNone.
|
||||
// TODO: this logic is still not right (because unit modes are not correctly prepared)
|
||||
// the caller should prepare a proper "permission" before calling this function.
|
||||
_ = repo.LoadUnits(ctx) // the error is not important, so ignore it
|
||||
permissionInRepo.Units = repo.Units
|
||||
permissionInRepo.SetUnitsWithDefaultAccessMode(repo.Units, permissionInRepo.AccessMode)
|
||||
}
|
||||
|
||||
cloneLink := repo.CloneLink()
|
||||
|
||||
@@ -75,6 +75,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap
|
||||
if authed {
|
||||
result.IsAdmin = user.IsAdmin
|
||||
result.LoginName = user.LoginName
|
||||
result.SourceID = user.LoginSource
|
||||
result.LastLogin = user.LastLoginUnix.AsTime()
|
||||
result.Language = user.Language
|
||||
result.IsActive = user.IsActive
|
||||
@@ -102,7 +103,7 @@ func User2UserSettings(user *user_model.User) api.UserSettings {
|
||||
func ToUserAndPermission(ctx context.Context, user, doer *user_model.User, accessMode perm.AccessMode) api.RepoCollaboratorPermission {
|
||||
return api.RepoCollaboratorPermission{
|
||||
User: ToUser(ctx, user, doer),
|
||||
Permission: accessMode.String(),
|
||||
RoleName: accessMode.String(),
|
||||
Permission: accessMode.ToString(),
|
||||
RoleName: accessMode.ToString(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,26 +61,20 @@ func asFixer(fn func(ctx context.Context) error) func(ctx context.Context) (int6
|
||||
}
|
||||
}
|
||||
|
||||
func genericOrphanCheck(name, subject, refobject, joincond string) consistencyCheck {
|
||||
func genericOrphanCheck(name, subject, refObject, joinCond string) consistencyCheck {
|
||||
return consistencyCheck{
|
||||
Name: name,
|
||||
Counter: func(ctx context.Context) (int64, error) {
|
||||
return db.CountOrphanedObjects(ctx, subject, refobject, joincond)
|
||||
return db.CountOrphanedObjects(ctx, subject, refObject, joinCond)
|
||||
},
|
||||
Fixer: func(ctx context.Context) (int64, error) {
|
||||
err := db.DeleteOrphanedObjects(ctx, subject, refobject, joincond)
|
||||
err := db.DeleteOrphanedObjects(ctx, subject, refObject, joinCond)
|
||||
return -1, err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
// make sure DB version is uptodate
|
||||
if err := db.InitEngineWithMigration(ctx, migrations.EnsureUpToDate); err != nil {
|
||||
logger.Critical("Model version on the database does not match the current Gitea version. Model consistency will not be checked until the database is upgraded")
|
||||
return err
|
||||
}
|
||||
|
||||
func prepareDBConsistencyChecks() []consistencyCheck {
|
||||
consistencyChecks := []consistencyCheck{
|
||||
{
|
||||
// find labels without existing repo or org
|
||||
@@ -210,7 +204,7 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
"oauth2_grant", "user", "oauth2_grant.user_id=`user`.id"),
|
||||
// find OAuth2Application without existing user
|
||||
genericOrphanCheck("Orphaned OAuth2Application without existing User",
|
||||
"oauth2_application", "user", "oauth2_application.uid=`user`.id"),
|
||||
"oauth2_application", "user", "oauth2_application.uid=0 OR oauth2_application.uid=`user`.id"),
|
||||
// find OAuth2AuthorizationCode without existing OAuth2Grant
|
||||
genericOrphanCheck("Orphaned OAuth2AuthorizationCode without existing OAuth2Grant",
|
||||
"oauth2_authorization_code", "oauth2_grant", "oauth2_authorization_code.grant_id=oauth2_grant.id"),
|
||||
@@ -224,7 +218,16 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
genericOrphanCheck("Orphaned Redirects without existing redirect user",
|
||||
"user_redirect", "user", "user_redirect.redirect_user_id=`user`.id"),
|
||||
)
|
||||
return consistencyChecks
|
||||
}
|
||||
|
||||
func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
// make sure DB version is uptodate
|
||||
if err := db.InitEngineWithMigration(ctx, migrations.EnsureUpToDate); err != nil {
|
||||
logger.Critical("Model version on the database does not match the current Gitea version. Model consistency will not be checked until the database is upgraded")
|
||||
return err
|
||||
}
|
||||
consistencyChecks := prepareDBConsistencyChecks()
|
||||
for _, c := range consistencyChecks {
|
||||
if err := c.Run(ctx, logger, autofix); err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package doctor
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConsistencyCheck(t *testing.T) {
|
||||
checks := prepareDBConsistencyChecks()
|
||||
idx := slices.IndexFunc(checks, func(check consistencyCheck) bool {
|
||||
return check.Name == "Orphaned OAuth2Application without existing User"
|
||||
})
|
||||
if !assert.NotEqual(t, -1, idx) {
|
||||
return
|
||||
}
|
||||
|
||||
_ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &user.User{})
|
||||
_ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &auth.OAuth2Application{})
|
||||
|
||||
err := db.Insert(db.DefaultContext, &user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-1", ClientID: "client-id-1"})
|
||||
assert.NoError(t, err)
|
||||
err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-2", ClientID: "client-id-2", UID: 1})
|
||||
assert.NoError(t, err)
|
||||
err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-3", ClientID: "client-id-3", UID: 99999999})
|
||||
assert.NoError(t, err)
|
||||
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-1"})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-2"})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-3"})
|
||||
|
||||
oauth2AppCheck := checks[idx]
|
||||
err = oauth2AppCheck.Run(db.DefaultContext, log.GetManager().GetLogger(log.DEFAULT), true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-1"})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-2"})
|
||||
unittest.AssertNotExistsBean(t, &auth.OAuth2Application{ClientID: "client-id-3"})
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
)
|
||||
|
||||
// Check represents a Doctor check
|
||||
@@ -25,6 +26,7 @@ type Check struct {
|
||||
AbortIfFailed bool
|
||||
SkipDatabaseInitialization bool
|
||||
Priority int
|
||||
InitStorage bool
|
||||
}
|
||||
|
||||
func initDBSkipLogger(ctx context.Context) error {
|
||||
@@ -84,6 +86,7 @@ func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) err
|
||||
logger := log.BaseLoggerToGeneralLogger(&doctorCheckLogger{colorize: colorize})
|
||||
loggerStep := log.BaseLoggerToGeneralLogger(&doctorCheckStepLogger{colorize: colorize})
|
||||
dbIsInit := false
|
||||
storageIsInit := false
|
||||
for i, check := range checks {
|
||||
if !dbIsInit && !check.SkipDatabaseInitialization {
|
||||
// Only open database after the most basic configuration check
|
||||
@@ -94,6 +97,14 @@ func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) err
|
||||
}
|
||||
dbIsInit = true
|
||||
}
|
||||
if !storageIsInit && check.InitStorage {
|
||||
if err := storage.Init(); err != nil {
|
||||
logger.Error("Error whilst initializing the storage: %v", err)
|
||||
logger.Error("Check if you are using the right config file. You can use a --config directive to specify one.")
|
||||
return nil
|
||||
}
|
||||
storageIsInit = true
|
||||
}
|
||||
logger.Info("\n[%d] %s", i+1, check.Title)
|
||||
if err := check.Run(ctx, loggerStep, autofix); err != nil {
|
||||
if check.AbortIfFailed {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package doctor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m)
|
||||
}
|
||||
@@ -134,6 +134,7 @@ type RepoSettingForm struct {
|
||||
EnableWiki bool
|
||||
EnableExternalWiki bool
|
||||
DefaultWikiBranch string
|
||||
DefaultWikiEveryoneAccess string
|
||||
ExternalWikiURL string
|
||||
EnableIssues bool
|
||||
EnableExternalTracker bool
|
||||
|
||||
@@ -51,14 +51,14 @@ func PullRequestCodeOwnersReview(ctx context.Context, issue *issues_model.Issue,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pr.HeadRepo.IsFork {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pr.BaseRepo.IsFork {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -36,10 +36,10 @@ func TestProcessorHelperCodePreview(t *testing.T) {
|
||||
<table class="file-view">
|
||||
<tbody><tr>
|
||||
<td class="lines-num"><span data-line-number="1"></span></td>
|
||||
<td class="lines-code chroma"><code class="code-inner"><span class="gh"># repo1</code></td>
|
||||
<td class="lines-code chroma"><div class="code-inner"><span class="gh"># repo1</div></td>
|
||||
</tr><tr>
|
||||
<td class="lines-num"><span data-line-number="2"></span></td>
|
||||
<td class="lines-code chroma"><code class="code-inner"></span><span class="gh"></span></code></td>
|
||||
<td class="lines-code chroma"><div class="code-inner"></span><span class="gh"></span></div></td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -63,7 +63,7 @@ func TestProcessorHelperCodePreview(t *testing.T) {
|
||||
<table class="file-view">
|
||||
<tbody><tr>
|
||||
<td class="lines-num"><span data-line-number="1"></span></td>
|
||||
<td class="lines-code chroma"><code class="code-inner"><span class="gh"># repo1</code></td>
|
||||
<td class="lines-code chroma"><div class="code-inner"><span class="gh"># repo1</div></td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -72,6 +72,11 @@ func (g *GitBucketDownloader) LogString() string {
|
||||
// NewGitBucketDownloader creates a GitBucket downloader
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
|
||||
githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
// Gitbucket 4.40 uses different internal hard-coded perPage values.
|
||||
// Issues, PRs, and other major parts use 25. Release page uses 10.
|
||||
// Some API doesn't support paging yet. Sounds difficult, but using
|
||||
// minimum number among them worked out very well.
|
||||
githubDownloader.maxPerPage = 10
|
||||
githubDownloader.SkipReactions = true
|
||||
githubDownloader.SkipReviews = true
|
||||
return &GitBucketDownloader{
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
system_model "code.gitea.io/gitea/models/system"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
giturl "code.gitea.io/gitea/modules/git/url"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -30,10 +31,15 @@ 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)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid addr: %v", err)
|
||||
}
|
||||
|
||||
remoteName := m.GetRemoteName()
|
||||
repoPath := m.GetRepository(ctx).RepoPath()
|
||||
// Remove old remote
|
||||
_, _, err := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
_, _, 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 ") {
|
||||
return err
|
||||
}
|
||||
@@ -70,7 +76,9 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
||||
}
|
||||
}
|
||||
|
||||
m.Repo.OriginalURL = addr
|
||||
// erase authentication before storing in database
|
||||
u.User = nil
|
||||
m.Repo.OriginalURL = u.String()
|
||||
return repo_model.UpdateRepositoryCols(ctx, m.Repo, "original_url")
|
||||
}
|
||||
|
||||
@@ -449,19 +457,17 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var gitRepo *git.Repository
|
||||
if len(results) == 0 {
|
||||
log.Trace("SyncMirrors [repo: %-v]: no branches updated", m.Repo)
|
||||
} else {
|
||||
log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results))
|
||||
gitRepo, err = gitrepo.OpenRepository(ctx, m.Repo)
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, m.Repo)
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
|
||||
log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results))
|
||||
if len(results) > 0 {
|
||||
if ok := checkAndUpdateEmptyRepository(ctx, m, gitRepo, results); !ok {
|
||||
log.Error("SyncMirrors [repo: %-v]: checkAndUpdateEmptyRepository: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -534,16 +540,24 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
||||
}
|
||||
log.Trace("SyncMirrors [repo: %-v]: done notifying updated branches/tags - now updating last commit time", m.Repo)
|
||||
|
||||
// Get latest commit date and update to current repository updated time
|
||||
commitDate, err := git.GetLatestCommitTime(ctx, m.Repo.RepoPath())
|
||||
isEmpty, err := gitRepo.IsEmpty()
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to GetLatestCommitDate: %v", m.Repo, err)
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to check empty git repo: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
if !isEmpty {
|
||||
// Get latest commit date and update to current repository updated time
|
||||
commitDate, err := git.GetLatestCommitTime(ctx, m.Repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to GetLatestCommitDate: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = repo_model.UpdateRepositoryUpdatedTime(ctx, m.RepoID, commitDate); err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to update repository 'updated_unix': %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err = repo_model.UpdateRepositoryUpdatedTime(ctx, m.RepoID, commitDate); err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to update repository 'updated_unix': %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
|
||||
log.Trace("SyncMirrors [repo: %-v]: Successfully updated", m.Repo)
|
||||
|
||||
@@ -91,7 +91,7 @@ func AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues
|
||||
// NewPullRequest notifies new pull request to notifiers
|
||||
func NewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User) {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("LoadIssue failed: %v", err)
|
||||
return
|
||||
}
|
||||
if err := pr.Issue.LoadPoster(ctx); err != nil {
|
||||
@@ -112,7 +112,7 @@ func PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *iss
|
||||
// PullRequestReview notifies new pull request review
|
||||
func PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) {
|
||||
if err := review.LoadReviewer(ctx); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("LoadReviewer failed: %v", err)
|
||||
return
|
||||
}
|
||||
for _, notifier := range notifiers {
|
||||
|
||||
@@ -989,12 +989,12 @@ func GetPullCommits(ctx *gitea_context.Context, issue *issues_model.Issue) ([]Co
|
||||
for _, commit := range prInfo.Commits {
|
||||
var committerOrAuthorName string
|
||||
var commitTime time.Time
|
||||
if commit.Committer != nil {
|
||||
committerOrAuthorName = commit.Committer.Name
|
||||
commitTime = commit.Committer.When
|
||||
} else {
|
||||
if commit.Author != nil {
|
||||
committerOrAuthorName = commit.Author.Name
|
||||
commitTime = commit.Author.When
|
||||
} else {
|
||||
committerOrAuthorName = commit.Committer.Name
|
||||
commitTime = commit.Committer.When
|
||||
}
|
||||
|
||||
commits = append(commits, CommitInfo{
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/queue"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
@@ -119,17 +120,15 @@ func getDivergenceCacheKey(repoID int64, branchName string) string {
|
||||
|
||||
// getDivergenceFromCache gets the divergence from cache
|
||||
func getDivergenceFromCache(repoID int64, branchName string) (*git.DivergeObject, bool) {
|
||||
data := cache.GetCache().Get(getDivergenceCacheKey(repoID, branchName))
|
||||
data, ok := cache.GetCache().Get(getDivergenceCacheKey(repoID, branchName))
|
||||
res := git.DivergeObject{
|
||||
Ahead: -1,
|
||||
Behind: -1,
|
||||
}
|
||||
s, ok := data.([]byte)
|
||||
if !ok || len(s) == 0 {
|
||||
if !ok || data == "" {
|
||||
return &res, false
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(s, &res); err != nil {
|
||||
if err := json.Unmarshal(util.UnsafeStringToBytes(data), &res); err != nil {
|
||||
log.Error("json.UnMarshal failed: %v", err)
|
||||
return &res, false
|
||||
}
|
||||
@@ -141,7 +140,7 @@ func putDivergenceFromCache(repoID int64, branchName string, divergence *git.Div
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cache.GetCache().Put(getDivergenceCacheKey(repoID, branchName), bs, 30*24*60*60)
|
||||
return cache.GetCache().Put(getDivergenceCacheKey(repoID, branchName), util.UnsafeBytesToString(bs), 30*24*60*60)
|
||||
}
|
||||
|
||||
func DelDivergenceFromCache(repoID int64, branchName string) error {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/services/automerge"
|
||||
@@ -25,12 +27,41 @@ func getCacheKey(repoID int64, brancheName string) string {
|
||||
return fmt.Sprintf("commit_status:%x", hashBytes)
|
||||
}
|
||||
|
||||
func updateCommitStatusCache(ctx context.Context, repoID int64, branchName string, status api.CommitStatusState) error {
|
||||
c := cache.GetCache()
|
||||
return c.Put(getCacheKey(repoID, branchName), string(status), 3*24*60)
|
||||
type commitStatusCacheValue struct {
|
||||
State string `json:"state"`
|
||||
TargetURL string `json:"target_url"`
|
||||
}
|
||||
|
||||
func deleteCommitStatusCache(ctx context.Context, repoID int64, branchName string) error {
|
||||
func getCommitStatusCache(repoID int64, branchName string) *commitStatusCacheValue {
|
||||
c := cache.GetCache()
|
||||
statusStr, ok := c.Get(getCacheKey(repoID, branchName))
|
||||
if ok && statusStr != "" {
|
||||
var cv commitStatusCacheValue
|
||||
err := json.Unmarshal([]byte(statusStr), &cv)
|
||||
if err == nil && cv.State != "" {
|
||||
return &cv
|
||||
}
|
||||
if err != nil {
|
||||
log.Warn("getCommitStatusCache: json.Unmarshal failed: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateCommitStatusCache(repoID int64, branchName string, state api.CommitStatusState, targetURL string) error {
|
||||
c := cache.GetCache()
|
||||
bs, err := json.Marshal(commitStatusCacheValue{
|
||||
State: state.String(),
|
||||
TargetURL: targetURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn("updateCommitStatusCache: json.Marshal failed: %v", err)
|
||||
return nil
|
||||
}
|
||||
return c.Put(getCacheKey(repoID, branchName), string(bs), 3*24*60)
|
||||
}
|
||||
|
||||
func deleteCommitStatusCache(repoID int64, branchName string) error {
|
||||
c := cache.GetCache()
|
||||
return c.Delete(getCacheKey(repoID, branchName))
|
||||
}
|
||||
@@ -59,13 +90,19 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
|
||||
sha = commit.ID.String()
|
||||
}
|
||||
|
||||
if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{
|
||||
Repo: repo,
|
||||
Creator: creator,
|
||||
SHA: commit.ID,
|
||||
CommitStatus: status,
|
||||
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{
|
||||
Repo: repo,
|
||||
Creator: creator,
|
||||
SHA: commit.ID,
|
||||
CommitStatus: status,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", repo.ID, creator.ID, sha, err)
|
||||
}
|
||||
|
||||
return git_model.UpdateCommitStatusSummary(ctx, repo.ID, commit.ID.String())
|
||||
}); err != nil {
|
||||
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", repo.ID, creator.ID, sha, err)
|
||||
return err
|
||||
}
|
||||
|
||||
defaultBranchCommit, err := gitRepo.GetBranchCommit(repo.DefaultBranch)
|
||||
@@ -74,7 +111,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
|
||||
}
|
||||
|
||||
if commit.ID.String() == defaultBranchCommit.ID.String() { // since one commit status updated, the combined commit status should be invalid
|
||||
if err := deleteCommitStatusCache(ctx, repo.ID, repo.DefaultBranch); err != nil {
|
||||
if err := deleteCommitStatusCache(repo.ID, repo.DefaultBranch); err != nil {
|
||||
log.Error("deleteCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err)
|
||||
}
|
||||
}
|
||||
@@ -91,12 +128,12 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
|
||||
// FindReposLastestCommitStatuses loading repository default branch latest combinded commit status with cache
|
||||
func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Repository) ([]*git_model.CommitStatus, error) {
|
||||
results := make([]*git_model.CommitStatus, len(repos))
|
||||
c := cache.GetCache()
|
||||
|
||||
for i, repo := range repos {
|
||||
status, ok := c.Get(getCacheKey(repo.ID, repo.DefaultBranch)).(string)
|
||||
if ok && status != "" {
|
||||
results[i] = &git_model.CommitStatus{State: api.CommitStatusState(status)}
|
||||
if cv := getCommitStatusCache(repo.ID, repo.DefaultBranch); cv != nil {
|
||||
results[i] = &git_model.CommitStatus{
|
||||
State: api.CommitStatusState(cv.State),
|
||||
TargetURL: cv.TargetURL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +151,35 @@ func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Rep
|
||||
return nil, fmt.Errorf("FindBranchesByRepoAndBranchName: %v", err)
|
||||
}
|
||||
|
||||
var repoSHAs []git_model.RepoSHA
|
||||
for id, sha := range repoIDsToLatestCommitSHAs {
|
||||
repoSHAs = append(repoSHAs, git_model.RepoSHA{RepoID: id, SHA: sha})
|
||||
}
|
||||
|
||||
summaryResults, err := git_model.GetLatestCommitStatusForRepoAndSHAs(ctx, repoSHAs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetLatestCommitStatusForRepoAndSHAs: %v", err)
|
||||
}
|
||||
|
||||
for _, summary := range summaryResults {
|
||||
for i, repo := range repos {
|
||||
if repo.ID == summary.RepoID {
|
||||
results[i] = summary
|
||||
_ = slices.DeleteFunc(repoSHAs, func(repoSHA git_model.RepoSHA) bool {
|
||||
return repoSHA.RepoID == repo.ID
|
||||
})
|
||||
if results[i].State != "" {
|
||||
if err := updateCommitStatusCache(repo.ID, repo.DefaultBranch, results[i].State, results[i].TargetURL); err != nil {
|
||||
log.Error("updateCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call the database O(1) times to get the commit statuses for all repos
|
||||
repoToItsLatestCommitStatuses, err := git_model.GetLatestCommitStatusForPairs(ctx, repoIDsToLatestCommitSHAs, db.ListOptionsAll)
|
||||
repoToItsLatestCommitStatuses, err := git_model.GetLatestCommitStatusForPairs(ctx, repoSHAs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetLatestCommitStatusForPairs: %v", err)
|
||||
}
|
||||
@@ -124,7 +188,7 @@ func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Rep
|
||||
if results[i] == nil {
|
||||
results[i] = git_model.CalcCommitStatus(repoToItsLatestCommitStatuses[repo.ID])
|
||||
if results[i].State != "" {
|
||||
if err := updateCommitStatusCache(ctx, repo.ID, repo.DefaultBranch, results[i].State); err != nil {
|
||||
if err := updateCommitStatusCache(repo.ID, repo.DefaultBranch, results[i].State, results[i].TargetURL); err != nil {
|
||||
log.Error("updateCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,12 @@ import (
|
||||
"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/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"gitea.com/go-chi/cache"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -79,13 +78,13 @@ func findLastSundayBeforeDate(dateStr string) (string, error) {
|
||||
}
|
||||
|
||||
// GetContributorStats returns contributors stats for git commits for given revision or default branch
|
||||
func GetContributorStats(ctx context.Context, cache cache.Cache, repo *repo_model.Repository, revision string) (map[string]*ContributorData, error) {
|
||||
func GetContributorStats(ctx context.Context, cache cache.StringCache, repo *repo_model.Repository, revision string) (map[string]*ContributorData, error) {
|
||||
// as GetContributorStats is resource intensive we cache the result
|
||||
cacheKey := fmt.Sprintf(contributorStatsCacheKey, repo.FullName(), revision)
|
||||
if !cache.IsExist(cacheKey) {
|
||||
genReady := make(chan struct{})
|
||||
|
||||
// dont start multible async generations
|
||||
// dont start multiple async generations
|
||||
_, run := generateLock.Load(cacheKey)
|
||||
if run {
|
||||
return nil, ErrAwaitGeneration
|
||||
@@ -104,15 +103,11 @@ func GetContributorStats(ctx context.Context, cache cache.Cache, repo *repo_mode
|
||||
}
|
||||
}
|
||||
// TODO: renew timeout of cache cache.UpdateTimeout(cacheKey, contributorStatsCacheTimeout)
|
||||
|
||||
switch v := cache.Get(cacheKey).(type) {
|
||||
case error:
|
||||
return nil, v
|
||||
case map[string]*ContributorData:
|
||||
return v, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected type in cache detected")
|
||||
var res map[string]*ContributorData
|
||||
if _, cacheErr := cache.GetJSON(cacheKey, &res); cacheErr != nil {
|
||||
return nil, fmt.Errorf("cached error: %w", cacheErr.ToError())
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// getExtendedCommitStats return the list of *ExtendedCommitStats for the given revision
|
||||
@@ -205,13 +200,12 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int
|
||||
return extendedCommitStats, nil
|
||||
}
|
||||
|
||||
func generateContributorStats(genDone chan struct{}, cache cache.Cache, cacheKey string, repo *repo_model.Repository, revision string) {
|
||||
func generateContributorStats(genDone chan struct{}, cache cache.StringCache, cacheKey string, repo *repo_model.Repository, revision string) {
|
||||
ctx := graceful.GetManager().HammerContext()
|
||||
|
||||
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("OpenRepository: %w", err)
|
||||
_ = cache.Put(cacheKey, err, contributorStatsCacheTimeout)
|
||||
_ = cache.PutJSON(cacheKey, fmt.Errorf("OpenRepository: %w", err), contributorStatsCacheTimeout)
|
||||
return
|
||||
}
|
||||
defer closer.Close()
|
||||
@@ -221,13 +215,11 @@ func generateContributorStats(genDone chan struct{}, cache cache.Cache, cacheKey
|
||||
}
|
||||
extendedCommitStats, err := getExtendedCommitStats(gitRepo, revision)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("ExtendedCommitStats: %w", err)
|
||||
_ = cache.Put(cacheKey, err, contributorStatsCacheTimeout)
|
||||
_ = cache.PutJSON(cacheKey, fmt.Errorf("ExtendedCommitStats: %w", err), contributorStatsCacheTimeout)
|
||||
return
|
||||
}
|
||||
if len(extendedCommitStats) == 0 {
|
||||
err := fmt.Errorf("no commit stats returned for revision '%s'", revision)
|
||||
_ = cache.Put(cacheKey, err, contributorStatsCacheTimeout)
|
||||
_ = cache.PutJSON(cacheKey, fmt.Errorf("no commit stats returned for revision '%s'", revision), contributorStatsCacheTimeout)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -309,7 +301,7 @@ func generateContributorStats(genDone chan struct{}, cache cache.Cache, cacheKey
|
||||
total.TotalCommits++
|
||||
}
|
||||
|
||||
_ = cache.Put(cacheKey, contributorsCommitStats, contributorStatsCacheTimeout)
|
||||
_ = cache.PutJSON(cacheKey, contributorsCommitStats, contributorStatsCacheTimeout)
|
||||
generateLock.Delete(cacheKey)
|
||||
if genDone != nil {
|
||||
genDone <- struct{}{}
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"gitea.com/go-chi/cache"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -20,20 +20,18 @@ func TestRepository_ContributorsGraph(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
assert.NoError(t, repo.LoadOwner(db.DefaultContext))
|
||||
mockCache, err := cache.NewCacher(cache.Options{
|
||||
Adapter: "memory",
|
||||
Interval: 24 * 60,
|
||||
})
|
||||
mockCache, err := cache.NewStringCache(setting.Cache{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
generateContributorStats(nil, mockCache, "key", repo, "404ref")
|
||||
err, isErr := mockCache.Get("key").(error)
|
||||
assert.True(t, isErr)
|
||||
assert.ErrorAs(t, err, &git.ErrNotExist{})
|
||||
var data map[string]*ContributorData
|
||||
_, getErr := mockCache.GetJSON("key", &data)
|
||||
assert.NotNil(t, getErr)
|
||||
assert.ErrorContains(t, getErr.ToError(), "object does not exist")
|
||||
|
||||
generateContributorStats(nil, mockCache, "key2", repo, "master")
|
||||
data, isData := mockCache.Get("key2").(map[string]*ContributorData)
|
||||
assert.True(t, isData)
|
||||
exist, _ := mockCache.GetJSON("key2", &data)
|
||||
assert.True(t, exist)
|
||||
var keys []string
|
||||
for k := range data {
|
||||
keys = append(keys, k)
|
||||
|
||||
@@ -163,6 +163,7 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
|
||||
&actions_model.ActionScheduleSpec{RepoID: repoID},
|
||||
&actions_model.ActionSchedule{RepoID: repoID},
|
||||
&actions_model.ActionArtifact{RepoID: repoID},
|
||||
&actions_model.ActionRunnerToken{RepoID: repoID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %w", err)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
|
||||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
if err := t.Clone(opts.OldBranch, false); err != nil {
|
||||
|
||||
@@ -111,7 +111,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
|
||||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
if err := t.Clone(opts.OldBranch, true); err != nil {
|
||||
|
||||
@@ -143,7 +143,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
||||
|
||||
t, err := NewTemporaryUploadRepository(ctx, repo)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("NewTemporaryUploadRepository failed: %v", err)
|
||||
}
|
||||
defer t.Close()
|
||||
hasOldBranch := true
|
||||
|
||||
@@ -94,6 +94,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
|
||||
&actions_model.ActionRunner{OwnerID: u.ID},
|
||||
&user_model.Blocking{BlockerID: u.ID},
|
||||
&user_model.Blocking{BlockeeID: u.ID},
|
||||
&actions_model.ActionRunnerToken{OwnerID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %w", err)
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func (m *webhookNotifier) IssueClearLabels(ctx context.Context, doer *user_model
|
||||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
|
||||
Action: api.HookIssueLabelCleared,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
@@ -168,7 +168,7 @@ func (m *webhookNotifier) IssueChangeAssignee(ctx context.Context, doer *user_mo
|
||||
permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func (m *webhookNotifier) IssueChangeTitle(ctx context.Context, doer *user_model
|
||||
From: oldTitle,
|
||||
},
|
||||
},
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
@@ -250,7 +250,7 @@ func (m *webhookNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
|
||||
} else {
|
||||
apiIssue := &api.IssuePayload{
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
CommitID: commitID,
|
||||
@@ -281,7 +281,7 @@ func (m *webhookNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
|
||||
Action: api.HookIssueOpened,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, issue.Poster, nil),
|
||||
}); err != nil {
|
||||
@@ -349,7 +349,7 @@ func (m *webhookNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
|
||||
From: oldContent,
|
||||
},
|
||||
},
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
@@ -384,7 +384,7 @@ func (m *webhookNotifier) UpdateComment(ctx context.Context, doer *user_model.Us
|
||||
permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentEdited,
|
||||
Issue: convert.ToAPIIssue(ctx, c.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
|
||||
Changes: &api.ChangesPayload{
|
||||
Body: &api.ChangesFromPayload{
|
||||
@@ -412,7 +412,7 @@ func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_mod
|
||||
permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentCreated,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Comment: convert.ToAPIComment(ctx, repo, comment),
|
||||
Repository: convert.ToRepo(ctx, repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
@@ -449,7 +449,7 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us
|
||||
permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||
Action: api.HookIssueCommentDeleted,
|
||||
Issue: convert.ToAPIIssue(ctx, comment.Issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
|
||||
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
|
||||
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
@@ -533,7 +533,7 @@ func (m *webhookNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
|
||||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
|
||||
Action: api.HookIssueLabelUpdated,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
@@ -575,7 +575,7 @@ func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m
|
||||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{
|
||||
Action: hookAction,
|
||||
Index: issue.Index,
|
||||
Issue: convert.ToAPIIssue(ctx, issue),
|
||||
Issue: convert.ToAPIIssue(ctx, doer, issue),
|
||||
Repository: convert.ToRepo(ctx, issue.Repo, permission),
|
||||
Sender: convert.ToUser(ctx, doer, nil),
|
||||
})
|
||||
|
||||
+11
-7
@@ -161,7 +161,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
if isOldWikiExist {
|
||||
err := gitRepo.RemoveFilesFromIndex(oldWikiPath)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("RemoveFilesFromIndex failed: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -171,18 +171,18 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
|
||||
objectHash, err := gitRepo.HashObject(strings.NewReader(content))
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("HashObject failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("AddObjectToIndex failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
tree, err := gitRepo.WriteTree()
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("WriteTree failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
|
||||
commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), committer, tree, commitTreeOpts)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("CommitTree failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -222,11 +222,11 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
0,
|
||||
),
|
||||
}); err != nil {
|
||||
log.Error("%v", err)
|
||||
log.Error("Push failed: %v", err)
|
||||
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Push: %w", err)
|
||||
return fmt.Errorf("failed to push: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -370,6 +370,10 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
|
||||
return fmt.Errorf("unable to update database: %w", err)
|
||||
}
|
||||
|
||||
if !repo.HasWiki() {
|
||||
return nil
|
||||
}
|
||||
|
||||
oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get default branch: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user