Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete related PullAutoMerge and ReviewState on User/Repo Deletion #19649

Merged
merged 12 commits into from
May 8, 2022
15 changes: 15 additions & 0 deletions models/db/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,18 @@ func IsErrSSHDisabled(err error) bool {
func (err ErrSSHDisabled) Error() string {
return "SSH is disabled"
}

// ErrNotExist represents a non-exist error.
type ErrNotExist struct {
ID int64
6543 marked this conversation as resolved.
Show resolved Hide resolved
}

// IsErrNotExist checks if an error is an ErrNotExist
func IsErrNotExist(err error) bool {
_, ok := err.(ErrNotExist)
return ok
}

func (err ErrNotExist) Error() string {
return fmt.Sprintf("record does not exist [id: %d]", err.ID)
6543 marked this conversation as resolved.
Show resolved Hide resolved
}
15 changes: 0 additions & 15 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ import (
"code.gitea.io/gitea/modules/git"
)

// ErrNotExist represents a non-exist error.
type ErrNotExist struct {
ID int64
}

// IsErrNotExist checks if an error is an ErrNotExist
func IsErrNotExist(err error) bool {
_, ok := err.(ErrNotExist)
return ok
}

func (err ErrNotExist) Error() string {
return fmt.Sprintf("record does not exist [id: %d]", err.ID)
}

// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
type ErrUserOwnRepos struct {
UID int64
Expand Down
19 changes: 19 additions & 0 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,25 @@ func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *Pul
return
}

// CreateAutoMergeComment is a internal function, only use it for CommentTypePRScheduledToAutoMerge and CommentTypePRUnScheduledToAutoMerge CommentTypes
func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullRequest, doer *user_model.User) (comment *Comment, err error) {
6543 marked this conversation as resolved.
Show resolved Hide resolved
if err = pr.LoadIssueCtx(ctx); err != nil {
6543 marked this conversation as resolved.
Show resolved Hide resolved
return
}

if err = pr.LoadBaseRepoCtx(ctx); err != nil {
return
}

comment, err = CreateCommentCtx(ctx, &CreateCommentOptions{
Type: typ,
Doer: doer,
Repo: pr.BaseRepo,
Issue: pr.Issue,
})
return
}

// getCommitsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
Expand Down
6 changes: 3 additions & 3 deletions models/issue_tracked_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
return err
}
if removedTime == 0 {
return ErrNotExist{}
return db.ErrNotExist{}
6543 marked this conversation as resolved.
Show resolved Hide resolved
}

if err := issue.LoadRepo(ctx); err != nil {
Expand Down Expand Up @@ -311,7 +311,7 @@ func deleteTimes(e db.Engine, opts FindTrackedTimesOptions) (removedTime int64,

func deleteTime(e db.Engine, t *TrackedTime) error {
if t.Deleted {
return ErrNotExist{ID: t.ID}
return db.ErrNotExist{ID: t.ID}
6543 marked this conversation as resolved.
Show resolved Hide resolved
}
t.Deleted = true
_, err := e.ID(t.ID).Cols("deleted").Update(t)
Expand All @@ -325,7 +325,7 @@ func GetTrackedTimeByID(id int64) (*TrackedTime, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrNotExist{ID: id}
return nil, db.ErrNotExist{ID: id}
6543 marked this conversation as resolved.
Show resolved Hide resolved
}
return time, nil
}
2 changes: 1 addition & 1 deletion models/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ func getNotificationByID(e db.Engine, notificationID int64) (*Notification, erro
}

if !ok {
return nil, ErrNotExist{ID: notificationID}
return nil, db.ErrNotExist{ID: notificationID}
6543 marked this conversation as resolved.
Show resolved Hide resolved
}

return notification, nil
Expand Down
20 changes: 20 additions & 0 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"

"code.gitea.io/gitea/models/db"
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"
Expand Down Expand Up @@ -97,6 +98,25 @@ func init() {
db.RegisterModel(new(PullRequest))
}

func deletePullsByBaseRepoID(sess db.Engine, repoID int64) error {
deleteCond := builder.Select("id").From("pull_request").Where(builder.Eq{"pull_request.base_repo_id": repoID})

// Delete scheduled auto merges
if _, err := sess.In("pull_id", deleteCond).
Delete(&pull_model.AutoMerge{}); err != nil {
return err
}

// Delete review states
if _, err := sess.In("pull_id", deleteCond).
Delete(&pull_model.ReviewState{}); err != nil {
return err
}
6543 marked this conversation as resolved.
Show resolved Hide resolved

_, err := sess.Delete(&PullRequest{BaseRepoID: repoID})
return err
}

// MustHeadUserName returns the HeadRepo's username if failed return blank
func (pr *PullRequest) MustHeadUserName() string {
if err := pr.LoadHeadRepo(); err != nil {
Expand Down
65 changes: 10 additions & 55 deletions models/pull/automerge.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"context"
"fmt"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
Expand Down Expand Up @@ -59,21 +58,12 @@ func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pullID int64,
return ErrAlreadyScheduledToAutoMerge{PullID: pullID}
}

if _, err := db.GetEngine(ctx).Insert(&AutoMerge{
_, err := db.GetEngine(ctx).Insert(&AutoMerge{
DoerID: doer.ID,
PullID: pullID,
MergeStyle: style,
Message: message,
}); err != nil {
return err
}

pr, err := models.GetPullRequestByID(ctx, pullID)
if err != nil {
return err
}

_, err = createAutoMergeComment(ctx, models.CommentTypePRScheduledToAutoMerge, pr, doer)
})
return err
}

Expand All @@ -94,50 +84,15 @@ func GetScheduledMergeByPullID(ctx context.Context, pullID int64) (bool, *AutoMe
return true, scheduledPRM, nil
}

// RemoveScheduledAutoMerge cancels a previously scheduled pull request
func RemoveScheduledAutoMerge(ctx context.Context, doer *user_model.User, pullID int64, comment bool) error {
return db.WithTx(func(ctx context.Context) error {
exist, scheduledPRM, err := GetScheduledMergeByPullID(ctx, pullID)
if err != nil {
return err
} else if !exist {
return models.ErrNotExist{ID: pullID}
}

if _, err := db.GetEngine(ctx).ID(scheduledPRM.ID).Delete(&AutoMerge{}); err != nil {
return err
}

// if pull got merged we don't need to add "auto-merge canceled comment"
if !comment || doer == nil {
return nil
}

pr, err := models.GetPullRequestByID(ctx, pullID)
if err != nil {
return err
}

_, err = createAutoMergeComment(ctx, models.CommentTypePRUnScheduledToAutoMerge, pr, doer)
// DeleteScheduledAutoMerge delete a scheduled pull request
func DeleteScheduledAutoMerge(ctx context.Context, pullID int64) error {
exist, scheduledPRM, err := GetScheduledMergeByPullID(ctx, pullID)
if err != nil {
return err
}, ctx)
}

// createAutoMergeComment is a internal function, only use it for CommentTypePRScheduledToAutoMerge and CommentTypePRUnScheduledToAutoMerge CommentTypes
func createAutoMergeComment(ctx context.Context, typ models.CommentType, pr *models.PullRequest, doer *user_model.User) (comment *models.Comment, err error) {
if err = pr.LoadIssueCtx(ctx); err != nil {
return
} else if !exist {
return db.ErrNotExist{ID: pullID}
6543 marked this conversation as resolved.
Show resolved Hide resolved
}

if err = pr.LoadBaseRepoCtx(ctx); err != nil {
return
}

comment, err = models.CreateCommentCtx(ctx, &models.CreateCommentOptions{
Type: typ,
Doer: doer,
Repo: pr.BaseRepo,
Issue: pr.Issue,
})
return
_, err = db.GetEngine(ctx).ID(scheduledPRM.ID).Delete(&AutoMerge{})
return err
}
6 changes: 5 additions & 1 deletion models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,6 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
&Notification{RepoID: repoID},
&ProtectedBranch{RepoID: repoID},
&ProtectedTag{RepoID: repoID},
&PullRequest{BaseRepoID: repoID},
&repo_model.PushMirror{RepoID: repoID},
&Release{RepoID: repoID},
&repo_model.RepoIndexerStatus{RepoID: repoID},
Expand All @@ -723,6 +722,11 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
return err
}

// Delete Pulls and related objects
if err := deletePullsByBaseRepoID(sess, repoID); err != nil {
return err
}

// Delete Issues and related objects
var attachmentPaths []string
if attachmentPaths, err = deleteIssuesByRepoID(sess, repoID); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
pull_model "code.gitea.io/gitea/models/pull"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -82,6 +83,8 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
&Collaboration{UserID: u.ID},
&Stopwatch{UserID: u.ID},
&user_model.Setting{UserID: u.ID},
&pull_model.AutoMerge{DoerID: u.ID},
&pull_model.ReviewState{UserID: u.ID},
); err != nil {
return fmt.Errorf("deleteBeans: %v", err)
}
Expand Down
3 changes: 2 additions & 1 deletion routers/api/v1/notify/threads.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
)
Expand Down Expand Up @@ -102,7 +103,7 @@ func ReadThread(ctx *context.APIContext) {
func getThread(ctx *context.APIContext) *models.Notification {
n, err := models.GetNotificationByID(ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrNotExist(err) {
if db.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "GetNotificationByID", err)
} else {
ctx.InternalServerError(err)
Expand Down
5 changes: 3 additions & 2 deletions routers/api/v1/repo/issue_tracked_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
Expand Down Expand Up @@ -281,7 +282,7 @@ func ResetIssueTime(ctx *context.APIContext) {

err = models.DeleteIssueUserTimes(issue, ctx.Doer)
if err != nil {
if models.IsErrNotExist(err) {
if db.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "DeleteIssueUserTimes", err)
} else {
ctx.Error(http.StatusInternalServerError, "DeleteIssueUserTimes", err)
Expand Down Expand Up @@ -352,7 +353,7 @@ func DeleteTime(ctx *context.APIContext) {

time, err := models.GetTrackedTimeByID(ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrNotExist(err) {
if db.IsErrNotExist(err) {
ctx.NotFound(err)
return
}
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,7 @@ func CancelScheduledAutoMerge(ctx *context.APIContext) {
}
}

if err := pull_model.RemoveScheduledAutoMerge(ctx, ctx.Doer, pull.ID, true); err != nil {
if err := automerge.RemoveScheduledAutoMerge(ctx, ctx.Doer, pull); err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusNoContent)
Expand Down
3 changes: 2 additions & 1 deletion routers/web/repo/issue_timetrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
Expand Down Expand Up @@ -63,7 +64,7 @@ func DeleteTime(c *context.Context) {

t, err := models.GetTrackedTimeByID(c.ParamsInt64(":timeid"))
if err != nil {
if models.IsErrNotExist(err) {
if db.IsErrNotExist(err) {
c.NotFound("time not found", err)
return
}
Expand Down
40 changes: 31 additions & 9 deletions services/automerge/automerge.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
pull_model "code.gitea.io/gitea/models/pull"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
Expand Down Expand Up @@ -61,17 +62,38 @@ func addToQueue(pr *models.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 *models.PullRequest, style repo_model.MergeStyle, message string) (scheduled bool, err error) {
lastCommitStatus, err := pull_service.GetPullRequestCommitStatusState(ctx, pull)
if err != nil {
return false, err
}
err = db.WithTx(func(ctx context.Context) error {
lastCommitStatus, err := pull_service.GetPullRequestCommitStatusState(ctx, pull)
if err != nil {
return err
}

// we don't need to schedule
if lastCommitStatus.IsSuccess() {
return false, nil
}
// we don't need to schedule
if lastCommitStatus.IsSuccess() {
return nil
}

if err := pull_model.ScheduleAutoMerge(ctx, doer, pull.ID, style, message); err != nil {
return err
}
scheduled = true

_, err = models.CreateAutoMergeComment(ctx, models.CommentTypePRScheduledToAutoMerge, pull, doer)
return err
}, ctx)
return
}

return true, pull_model.ScheduleAutoMerge(ctx, doer, pull.ID, style, message)
// RemoveScheduledAutoMerge cancels a previously scheduled pull request
func RemoveScheduledAutoMerge(ctx context.Context, doer *user_model.User, pull *models.PullRequest) error {
return db.WithTx(func(ctx context.Context) error {
if err := pull_model.DeleteScheduledAutoMerge(ctx, pull.ID); err != nil {
return err
}

_, err := models.CreateAutoMergeComment(ctx, models.CommentTypePRUnScheduledToAutoMerge, pull, doer)
return err
}, ctx)
}

// MergeScheduledPullRequest merges a previously scheduled pull request when all checks succeeded
Expand Down
2 changes: 1 addition & 1 deletion services/pull/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func Merge(pr *models.PullRequest, doer *user_model.User, baseGitRepo *git.Repos
defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))

// Removing an auto merge pull and ignore if not exist
if err := pull_model.RemoveScheduledAutoMerge(db.DefaultContext, doer, pr.ID, false); err != nil && !models.IsErrNotExist(err) {
if err := pull_model.DeleteScheduledAutoMerge(db.DefaultContext, pr.ID); err != nil && !db.IsErrNotExist(err) {
return err
}

Expand Down