diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2022-12-10 10:46:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-10 10:46:31 +0800 |
commit | 68704532c28cf09db96c988291b2f82c5e615984 (patch) | |
tree | c6537092dc11054f96b202fdb957755ed116cd99 /models | |
parent | 097d4e30b180eef30600beef2c08095e2571319c (diff) | |
download | gitea-68704532c28cf09db96c988291b2f82c5e615984.tar.gz gitea-68704532c28cf09db96c988291b2f82c5e615984.zip |
Rename almost all Ctx functions (#22071)
Diffstat (limited to 'models')
-rw-r--r-- | models/issues/assignees.go | 2 | ||||
-rw-r--r-- | models/issues/comment.go | 208 | ||||
-rw-r--r-- | models/issues/comment_test.go | 2 | ||||
-rw-r--r-- | models/issues/issue.go | 24 | ||||
-rw-r--r-- | models/issues/issue_list.go | 2 | ||||
-rw-r--r-- | models/issues/issue_lock.go | 2 | ||||
-rw-r--r-- | models/issues/issue_project.go | 2 | ||||
-rw-r--r-- | models/issues/issue_xref.go | 2 | ||||
-rw-r--r-- | models/issues/label.go | 4 | ||||
-rw-r--r-- | models/issues/review.go | 16 | ||||
-rw-r--r-- | models/issues/stopwatch.go | 6 | ||||
-rw-r--r-- | models/issues/tracked_time.go | 6 | ||||
-rw-r--r-- | models/organization/org.go | 2 | ||||
-rw-r--r-- | models/organization/org_user.go | 4 | ||||
-rw-r--r-- | models/organization/team.go | 12 | ||||
-rw-r--r-- | models/perm/access/repo_permission.go | 2 | ||||
-rw-r--r-- | models/project/project.go | 54 | ||||
-rw-r--r-- | models/repo/collaboration.go | 69 | ||||
-rw-r--r-- | models/repo/collaboration_test.go | 6 | ||||
-rw-r--r-- | models/repo/issue.go | 23 | ||||
-rw-r--r-- | models/repo/release.go | 4 | ||||
-rw-r--r-- | models/repo/repo.go | 22 | ||||
-rw-r--r-- | models/repo_transfer.go | 94 | ||||
-rw-r--r-- | models/repo_transfer_test.go | 15 |
24 files changed, 162 insertions, 421 deletions
diff --git a/models/issues/assignees.go b/models/issues/assignees.go index d3a1f5ffe8..159086bd01 100644 --- a/models/issues/assignees.go +++ b/models/issues/assignees.go @@ -102,7 +102,7 @@ func toggleIssueAssignee(ctx context.Context, issue *Issue, doer *user_model.Use AssigneeID: assigneeID, } // Comment - comment, err = CreateCommentCtx(ctx, opts) + comment, err = CreateComment(ctx, opts) if err != nil { return false, nil, fmt.Errorf("createComment: %w", err) } diff --git a/models/issues/comment.go b/models/issues/comment.go index 2abe692a6f..612f17aa5a 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -779,8 +779,8 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) { return err } -// CreateCommentCtx creates comment with context -func CreateCommentCtx(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) { +// CreateComment creates comment with context +func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) { e := db.GetEngine(ctx) var LabelID int64 if opts.Label != nil { @@ -915,7 +915,7 @@ func createDeadlineComment(ctx context.Context, doer *user_model.User, issue *Is Issue: issue, Content: content, } - comment, err := CreateCommentCtx(ctx, opts) + comment, err := CreateComment(ctx, opts) if err != nil { return nil, err } @@ -940,7 +940,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is Issue: issue, DependentIssueID: dependentIssue.ID, } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return } @@ -951,7 +951,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is Issue: dependentIssue, DependentIssueID: issue.ID, } - _, err = CreateCommentCtx(ctx, opts) + _, err = CreateComment(ctx, opts) return err } @@ -993,55 +993,6 @@ type CreateCommentOptions struct { Invalidated bool } -// CreateComment creates comment of issue or commit. -func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return nil, err - } - defer committer.Close() - - comment, err = CreateCommentCtx(ctx, opts) - if err != nil { - return nil, err - } - - if err = committer.Commit(); err != nil { - return nil, err - } - - return comment, nil -} - -// CreateRefComment creates a commit reference comment to issue. -func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *Issue, content, commitSHA string) error { - if len(commitSHA) == 0 { - return fmt.Errorf("cannot create reference with empty commit SHA") - } - - // Check if same reference from same commit has already existed. - has, err := db.GetEngine(db.DefaultContext).Get(&Comment{ - Type: CommentTypeCommitRef, - IssueID: issue.ID, - CommitSHA: commitSHA, - }) - if err != nil { - return fmt.Errorf("check reference comment: %w", err) - } else if has { - return nil - } - - _, err = CreateComment(&CreateCommentOptions{ - Type: CommentTypeCommitRef, - Doer: doer, - Repo: repo, - Issue: issue, - CommitSHA: commitSHA, - Content: content, - }) - return err -} - // GetCommentByID returns the comment by given ID. func GetCommentByID(ctx context.Context, id int64) (*Comment, error) { c := new(Comment) @@ -1317,39 +1268,6 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID return err } -// CreatePushPullComment create push code to pull base comment -func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) { - if pr.HasMerged || oldCommitID == "" || newCommitID == "" { - return nil, nil - } - - ops := &CreateCommentOptions{ - Type: CommentTypePullRequestPush, - Doer: pusher, - Repo: pr.BaseRepo, - } - - var data PushActionContent - - data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) - if err != nil { - return nil, err - } - - ops.Issue = pr.Issue - - dataJSON, err := json.Marshal(data) - if err != nil { - return nil, err - } - - ops.Content = string(dataJSON) - - comment, err = CreateComment(ops) - - return comment, err -} - // 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) { if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge { @@ -1363,7 +1281,7 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques return } - comment, err = CreateCommentCtx(ctx, &CreateCommentOptions{ + comment, err = CreateComment(ctx, &CreateCommentOptions{ Type: typ, Doer: doer, Repo: pr.BaseRepo, @@ -1372,120 +1290,6 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques return comment, err } -// 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 -func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { - repoPath := repo.RepoPath() - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath) - if err != nil { - return nil, false, err - } - defer closer.Close() - - oldCommit, err := gitRepo.GetCommit(oldCommitID) - if err != nil { - return nil, false, err - } - - if err = oldCommit.LoadBranchName(); err != nil { - return nil, false, err - } - - if len(oldCommit.Branch) == 0 { - commitIDs = make([]string, 2) - commitIDs[0] = oldCommitID - commitIDs[1] = newCommitID - - return commitIDs, true, err - } - - newCommit, err := gitRepo.GetCommit(newCommitID) - if err != nil { - return nil, false, err - } - - commits, err := newCommit.CommitsBeforeUntil(oldCommitID) - if err != nil { - return nil, false, err - } - - commitIDs = make([]string, 0, len(commits)) - commitChecks := make(map[string]*commitBranchCheckItem) - - for _, commit := range commits { - commitChecks[commit.ID.String()] = &commitBranchCheckItem{ - Commit: commit, - Checked: false, - } - } - - if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil { - return - } - - for i := len(commits) - 1; i >= 0; i-- { - commitID := commits[i].ID.String() - if item, ok := commitChecks[commitID]; ok && item.Checked { - commitIDs = append(commitIDs, commitID) - } - } - - return commitIDs, isForcePush, err -} - -type commitBranchCheckItem struct { - Commit *git.Commit - Checked bool -} - -func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error { - if startCommit.ID.String() == endCommitID { - return nil - } - - checkStack := make([]string, 0, 10) - checkStack = append(checkStack, startCommit.ID.String()) - - for len(checkStack) > 0 { - commitID := checkStack[0] - checkStack = checkStack[1:] - - item, ok := commitList[commitID] - if !ok { - continue - } - - if item.Commit.ID.String() == endCommitID { - continue - } - - if err := item.Commit.LoadBranchName(); err != nil { - return err - } - - if item.Commit.Branch == baseBranch { - continue - } - - if item.Checked { - continue - } - - item.Checked = true - - parentNum := item.Commit.ParentCount() - for i := 0; i < parentNum; i++ { - parentCommit, err := item.Commit.Parent(i) - if err != nil { - return err - } - checkStack = append(checkStack, parentCommit.ID.String()) - } - } - return nil -} - // RemapExternalUser ExternalUserRemappable interface func (c *Comment) RemapExternalUser(externalName string, externalID, userID int64) error { c.OriginalAuthor = externalName diff --git a/models/issues/comment_test.go b/models/issues/comment_test.go index 6a647474dc..0d0570ae34 100644 --- a/models/issues/comment_test.go +++ b/models/issues/comment_test.go @@ -24,7 +24,7 @@ func TestCreateComment(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) now := time.Now().Unix() - comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{ + comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeComment, Doer: doer, Repo: repo, diff --git a/models/issues/issue.go b/models/issues/issue.go index 3ab6d204ba..fc93fcf454 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -202,16 +202,12 @@ func (issue *Issue) LoadRepo(ctx context.Context) (err error) { } // IsTimetrackerEnabled returns true if the repo enables timetracking -func (issue *Issue) IsTimetrackerEnabled() bool { - return issue.isTimetrackerEnabled(db.DefaultContext) -} - -func (issue *Issue) isTimetrackerEnabled(ctx context.Context) bool { +func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool { if err := issue.LoadRepo(ctx); err != nil { log.Error(fmt.Sprintf("loadRepo: %v", err)) return false } - return issue.Repo.IsTimetrackerEnabledCtx(ctx) + return issue.Repo.IsTimetrackerEnabled(ctx) } // GetPullRequest returns the issue pull request @@ -404,7 +400,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { if err = CommentList(issue.Comments).loadAttributes(ctx); err != nil { return err } - if issue.isTimetrackerEnabled(ctx) { + if issue.IsTimetrackerEnabled(ctx) { if err = issue.LoadTotalTimes(ctx); err != nil { return err } @@ -673,7 +669,7 @@ func changeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, isMergePull bool) (*Comment, error) { // Check for open dependencies - if issue.IsClosed && issue.Repo.IsDependenciesEnabledCtx(ctx) { + if issue.IsClosed && issue.Repo.IsDependenciesEnabled(ctx) { // only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies noDeps, err := IssueNoDependenciesLeft(ctx, issue) if err != nil { @@ -725,7 +721,7 @@ func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.Use cmtType = CommentTypeMergePull } - return CreateCommentCtx(ctx, &CreateCommentOptions{ + return CreateComment(ctx, &CreateCommentOptions{ Type: cmtType, Doer: doer, Repo: issue.Repo, @@ -769,7 +765,7 @@ func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err OldTitle: oldTitle, NewTitle: issue.Title, } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return fmt.Errorf("createComment: %w", err) } if err = issue.AddCrossReferences(ctx, doer, true); err != nil { @@ -805,7 +801,7 @@ func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err err OldRef: oldRefFriendly, NewRef: newRefFriendly, } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return fmt.Errorf("createComment: %w", err) } @@ -825,7 +821,7 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo * Issue: issue, OldRef: branchName, } - _, err = CreateCommentCtx(ctx, opts) + _, err = CreateComment(ctx, opts) return err } @@ -992,7 +988,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue OldMilestoneID: 0, MilestoneID: opts.Issue.MilestoneID, } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return err } } @@ -2000,7 +1996,7 @@ func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment OldTitle: currentIssue.Title, NewTitle: issue.Title, } - _, err := CreateCommentCtx(ctx, opts) + _, err := CreateComment(ctx, opts) if err != nil { return nil, false, fmt.Errorf("createComment: %w", err) } diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index 35a0c1f0e3..e22e48c0bb 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -461,7 +461,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) { ids := make([]int64, 0, len(issues)) for _, issue := range issues { - if issue.Repo.IsTimetrackerEnabled() { + if issue.Repo.IsTimetrackerEnabled(ctx) { ids = append(ids, issue.ID) } } diff --git a/models/issues/issue_lock.go b/models/issues/issue_lock.go index 1376ffcada..19cd6d3167 100644 --- a/models/issues/issue_lock.go +++ b/models/issues/issue_lock.go @@ -56,7 +56,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error { Type: commentType, Content: opts.Reason, } - if _, err := CreateCommentCtx(ctx, opt); err != nil { + if _, err := CreateComment(ctx, opt); err != nil { return err } diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index a366a92fad..8e559f13c9 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -145,7 +145,7 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U } if oldProjectID > 0 || newProjectID > 0 { - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeProject, Doer: doer, Repo: issue.Repo, diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go index 267ccc73a0..21ee24210f 100644 --- a/models/issues/issue_xref.go +++ b/models/issues/issue_xref.go @@ -121,7 +121,7 @@ func (issue *Issue) createCrossReferences(stdCtx context.Context, ctx *crossRefe RefAction: xref.Action, RefIsPull: ctx.OrigIssue.IsPull, } - _, err := CreateCommentCtx(stdCtx, opts) + _, err := CreateComment(stdCtx, opts) if err != nil { return err } diff --git a/models/issues/label.go b/models/issues/label.go index e5583ff00f..dbb7a139ef 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -613,7 +613,7 @@ func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m Label: label, Content: "1", } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return err } @@ -714,7 +714,7 @@ func deleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use Issue: issue, Label: label, } - if _, err = CreateCommentCtx(ctx, opts); err != nil { + if _, err = CreateComment(ctx, opts); err != nil { return err } diff --git a/models/issues/review.go b/models/issues/review.go index db2d2686cb..7dee28fe97 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -294,7 +294,7 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio } if !pr.ProtectedBranch.EnableApprovalsWhitelist { - return team.UnitAccessModeCtx(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil + return team.UnitAccessMode(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil } return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil @@ -436,7 +436,7 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co } } - comm, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + comm, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReview, Doer: doer, Content: review.Content, @@ -692,7 +692,7 @@ func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, return nil, err } - comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + comment, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, Repo: issue.Repo, @@ -746,7 +746,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Commen } } - comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + comment, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, Repo: issue.Repo, @@ -804,7 +804,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_ } } - comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + comment, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, Repo: issue.Repo, @@ -814,7 +814,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_ ReviewID: review.ID, }) if err != nil { - return nil, fmt.Errorf("CreateCommentCtx(): %w", err) + return nil, fmt.Errorf("CreateComment(): %w", err) } return comment, committer.Commit() @@ -864,7 +864,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us return nil, committer.Commit() } - comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + comment, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, Repo: issue.Repo, @@ -873,7 +873,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID }) if err != nil { - return nil, fmt.Errorf("CreateCommentCtx(): %w", err) + return nil, fmt.Errorf("CreateComment(): %w", err) } return comment, committer.Commit() diff --git a/models/issues/stopwatch.go b/models/issues/stopwatch.go index 8a8fdca339..6bf936c5d4 100644 --- a/models/issues/stopwatch.go +++ b/models/issues/stopwatch.go @@ -196,7 +196,7 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss return err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Doer: user, Issue: issue, Repo: issue.Repo, @@ -246,7 +246,7 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss return err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Doer: user, Issue: issue, Repo: issue.Repo, @@ -287,7 +287,7 @@ func cancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) e return err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Doer: user, Issue: issue, Repo: issue.Repo, diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go index 554b01bd40..ac65d654f2 100644 --- a/models/issues/tracked_time.go +++ b/models/issues/tracked_time.go @@ -172,7 +172,7 @@ func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Tim return nil, err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Issue: issue, Repo: issue.Repo, Doer: user, @@ -250,7 +250,7 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error { if err := issue.LoadRepo(ctx); err != nil { return err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Issue: issue, Repo: issue.Repo, Doer: user, @@ -279,7 +279,7 @@ func DeleteTime(t *TrackedTime) error { return err } - if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ + if _, err := CreateComment(ctx, &CreateCommentOptions{ Issue: t.Issue, Repo: t.Issue.Repo, Doer: t.User, diff --git a/models/organization/org.go b/models/organization/org.go index a5b07d5aae..b3d77b4ec6 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -106,7 +106,7 @@ func (org *Organization) IsOrgMember(uid int64) (bool, error) { // CanCreateOrgRepo returns true if given user can create repo in organization func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) { - return CanCreateOrgRepo(org.ID, uid) + return CanCreateOrgRepo(db.DefaultContext, org.ID, uid) } func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) { diff --git a/models/organization/org_user.go b/models/organization/org_user.go index d514e401ba..e5cbfe6c0f 100644 --- a/models/organization/org_user.go +++ b/models/organization/org_user.go @@ -73,8 +73,8 @@ func IsPublicMembership(orgID, uid int64) (bool, error) { } // CanCreateOrgRepo returns true if user can create repo in organization -func CanCreateOrgRepo(orgID, uid int64) (bool, error) { - return db.GetEngine(db.DefaultContext). +func CanCreateOrgRepo(ctx context.Context, orgID, uid int64) (bool, error) { + return db.GetEngine(ctx). Where(builder.Eq{"team.can_create_org_repo": true}). Join("INNER", "team_user", "team_user.team_id = team.id"). And("team_user.uid = ?", uid). diff --git a/models/organization/team.go b/models/organization/team.go index 86ea30c801..55d3f17276 100644 --- a/models/organization/team.go +++ b/models/organization/team.go @@ -242,18 +242,12 @@ func (t *Team) LoadMembers(ctx context.Context) (err error) { } // UnitEnabled returns if the team has the given unit type enabled -func (t *Team) UnitEnabled(tp unit.Type) bool { - return t.UnitAccessMode(tp) > perm.AccessModeNone +func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool { + return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone } // UnitAccessMode returns if the team has the given unit type enabled -// it is called in templates, should not be replaced by `UnitAccessModeCtx(ctx ...)` -func (t *Team) UnitAccessMode(tp unit.Type) perm.AccessMode { // Notice: It will be used in template, don't remove it directly - return t.UnitAccessModeCtx(db.DefaultContext, tp) -} - -// UnitAccessModeCtx returns if the team has the given unit type enabled -func (t *Team) UnitAccessModeCtx(ctx context.Context, tp unit.Type) perm.AccessMode { +func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode { if err := t.getUnits(ctx); err != nil { log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error()) } diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 88437dc4b2..a6bf9b6744 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -244,7 +244,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use for _, u := range repo.Units { var found bool for _, team := range teams { - teamMode := team.UnitAccessModeCtx(ctx, u.Type) + teamMode := team.UnitAccessMode(ctx, u.Type) if teamMode > perm_model.AccessModeNone { m := perm.UnitsMode[u.Type] if m < teamMode { diff --git a/models/project/project.go b/models/project/project.go index 384f51c5ac..bcf1166408 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -298,44 +298,32 @@ func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { return updateRepositoryProjectCount(ctx, p.RepoID) } -// DeleteProjectByID deletes a project from a repository. -func DeleteProjectByID(id int64) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - if err := DeleteProjectByIDCtx(ctx, id); err != nil { - return err - } - - return committer.Commit() -} - -// DeleteProjectByIDCtx deletes a project from a repository. -func DeleteProjectByIDCtx(ctx context.Context, id int64) error { - p, err := GetProjectByID(ctx, id) - if err != nil { - if IsErrProjectNotExist(err) { - return nil +// DeleteProjectByID deletes a project from a repository. if it's not in a database +// transaction, it will start a new database transaction +func DeleteProjectByID(ctx context.Context, id int64) error { + return db.AutoTx(ctx, func(ctx context.Context) error { + p, err := GetProjectByID(ctx, id) + if err != nil { + if IsErrProjectNotExist(err) { + return nil + } + return err } - return err - } - if err := deleteProjectIssuesByProjectID(ctx, id); err != nil { - return err - } + if err := deleteProjectIssuesByProjectID(ctx, id); err != nil { + return err + } - if err := deleteBoardByProjectID(ctx, id); err != nil { - return err - } + if err := deleteBoardByProjectID(ctx, id); err != nil { + return err + } - if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Project)); err != nil { - return err - } + if _, err = db.GetEngine(ctx).ID(p.ID).Delete(new(Project)); err != nil { + return err + } - return updateRepositoryProjectCount(ctx, p.RepoID) + return updateRepositoryProjectCount(ctx, p.RepoID) + }) } func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { diff --git a/models/repo/collaboration.go b/models/repo/collaboration.go index bd49b9aec9..29bcab70f3 100644 --- a/models/repo/collaboration.go +++ b/models/repo/collaboration.go @@ -99,55 +99,42 @@ func getCollaborations(ctx context.Context, repoID int64, listOptions db.ListOpt } // ChangeCollaborationAccessMode sets new access mode for the collaboration. -func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error { +func ChangeCollaborationAccessMode(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error { // Discard invalid input if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner { return nil } - e := db.GetEngine(ctx) - - collaboration := &Collaboration{ - RepoID: repo.ID, - UserID: uid, - } - has, err := e.Get(collaboration) - if err != nil { - return fmt.Errorf("get collaboration: %w", err) - } else if !has { - return nil - } - - if collaboration.Mode == mode { - return nil - } - collaboration.Mode = mode - - if _, err = e. - ID(collaboration.ID). - Cols("mode"). - Update(collaboration); err != nil { - return fmt.Errorf("update collaboration: %w", err) - } else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil { - return fmt.Errorf("update access table: %w", err) - } + return db.AutoTx(ctx, func(ctx context.Context) error { + e := db.GetEngine(ctx) - return nil -} - -// ChangeCollaborationAccessMode sets new access mode for the collaboration. -func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: uid, + } + has, err := e.Get(collaboration) + if err != nil { + return fmt.Errorf("get collaboration: %w", err) + } else if !has { + return nil + } - if err := ChangeCollaborationAccessModeCtx(ctx, repo, uid, mode); err != nil { - return err - } + if collaboration.Mode == mode { + return nil + } + collaboration.Mode = mode + + if _, err = e. + ID(collaboration.ID). + Cols("mode"). + Update(collaboration); err != nil { + return fmt.Errorf("update collaboration: %w", err) + } else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil { + return fmt.Errorf("update access table: %w", err) + } - return committer.Commit() + return nil + }) } // IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go index d240e9cbef..0a6444de85 100644 --- a/models/repo/collaboration_test.go +++ b/models/repo/collaboration_test.go @@ -54,7 +54,7 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin)) collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode) @@ -62,9 +62,9 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID}) assert.EqualValues(t, perm.AccessModeAdmin, access.Mode) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin)) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, unittest.NonexistentID, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin)) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } diff --git a/models/repo/issue.go b/models/repo/issue.go index e27179caf5..6f6b565a00 100644 --- a/models/repo/issue.go +++ b/models/repo/issue.go @@ -6,7 +6,6 @@ package repo import ( "context" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -26,44 +25,34 @@ func (repo *Repository) CanEnableTimetracker() bool { } // IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs. -func (repo *Repository) IsTimetrackerEnabled() bool { // Notice: It will be used in template so don't remove directly - return repo.IsTimetrackerEnabledCtx(db.DefaultContext) -} - -// IsTimetrackerEnabledCtx returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs. -func (repo *Repository) IsTimetrackerEnabledCtx(ctx context.Context) bool { +func (repo *Repository) IsTimetrackerEnabled(ctx context.Context) bool { if !setting.Service.EnableTimetracking { return false } var u *RepoUnit var err error - if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil { + if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { return setting.Service.DefaultEnableTimetracking } return u.IssuesConfig().EnableTimetracker } // AllowOnlyContributorsToTrackTime returns value of IssuesConfig or the default value -func (repo *Repository) AllowOnlyContributorsToTrackTime() bool { +func (repo *Repository) AllowOnlyContributorsToTrackTime(ctx context.Context) bool { var u *RepoUnit var err error - if u, err = repo.GetUnit(unit.TypeIssues); err != nil { + if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { return setting.Service.DefaultAllowOnlyContributorsToTrackTime } return u.IssuesConfig().AllowOnlyContributorsToTrackTime } // IsDependenciesEnabled returns if dependencies are enabled and returns the default setting if not set. -func (repo *Repository) IsDependenciesEnabled() bool { - return repo.IsDependenciesEnabledCtx(db.DefaultContext) -} - -// IsDependenciesEnabledCtx returns if dependencies are enabled and returns the default setting if not set. -func (repo *Repository) IsDependenciesEnabledCtx(ctx context.Context) bool { +func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool { var u *RepoUnit var err error - if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil { + if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { log.Trace("%s", err) return setting.Service.DefaultEnableDependencies } diff --git a/models/repo/release.go b/models/repo/release.go index c6cb755344..25eba10e05 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -286,8 +286,8 @@ func GetReleasesByRepoIDAndNames(ctx context.Context, repoID int64, tagNames []s } // GetReleaseCountByRepoID returns the count of releases of repository -func GetReleaseCountByRepoID(repoID int64, opts FindReleasesOptions) (int64, error) { - return db.GetEngine(db.DefaultContext).Where(opts.toConds(repoID)).Count(&Release{}) +func GetReleaseCountByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) { + return db.GetEngine(ctx).Where(opts.toConds(repoID)).Count(&Release{}) } type releaseMetaSearch struct { diff --git a/models/repo/repo.go b/models/repo/repo.go index 7cb7138523..e5e1ac43b4 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -315,12 +315,7 @@ func (repo *Repository) LoadUnits(ctx context.Context) (err error) { } // UnitEnabled if this repository has the given unit enabled -func (repo *Repository) UnitEnabled(tp unit.Type) (result bool) { // Notice: Don't remove this function directly, because it has been used in go template. - return repo.UnitEnabledCtx(db.DefaultContext, tp) -} - -// UnitEnabled if this repository has the given unit enabled -func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool { +func (repo *Repository) UnitEnabled(ctx context.Context, tp unit.Type) bool { if err := repo.LoadUnits(ctx); err != nil { log.Warn("Error loading repository (ID: %d) units: %s", repo.ID, err.Error()) } @@ -333,8 +328,8 @@ func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool { } // MustGetUnit always returns a RepoUnit object -func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit { - ru, err := repo.GetUnit(tp) +func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit { + ru, err := repo.GetUnit(ctx, tp) if err == nil { return ru } @@ -367,12 +362,7 @@ func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit { } // GetUnit returns a RepoUnit object -func (repo *Repository) GetUnit(tp unit.Type) (*RepoUnit, error) { - return repo.GetUnitCtx(db.DefaultContext, tp) -} - -// GetUnitCtx returns a RepoUnit object -func (repo *Repository) GetUnitCtx(ctx context.Context, tp unit.Type) (*RepoUnit, error) { +func (repo *Repository) GetUnit(ctx context.Context, tp unit.Type) (*RepoUnit, error) { if err := repo.LoadUnits(ctx); err != nil { return nil, err } @@ -419,7 +409,7 @@ func (repo *Repository) ComposeMetas() map[string]string { "mode": "comment", } - unit, err := repo.GetUnit(unit.TypeExternalTracker) + unit, err := repo.GetUnit(db.DefaultContext, unit.TypeExternalTracker) if err == nil { metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat switch unit.ExternalTrackerConfig().ExternalTrackerStyle { @@ -518,7 +508,7 @@ func (repo *Repository) CanEnablePulls() bool { // AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled. func (repo *Repository) AllowsPulls() bool { - return repo.CanEnablePulls() && repo.UnitEnabled(unit.TypePullRequests) + return repo.CanEnablePulls() && repo.UnitEnabled(db.DefaultContext, unit.TypePullRequests) } // CanEnableEditor returns true if repository meets the requirements of web editor. diff --git a/models/repo_transfer.go b/models/repo_transfer.go index 362253bdc8..19e6c06627 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -39,9 +39,9 @@ func init() { } // LoadAttributes fetches the transfer recipient from the database -func (r *RepoTransfer) LoadAttributes() error { +func (r *RepoTransfer) LoadAttributes(ctx context.Context) error { if r.Recipient == nil { - u, err := user_model.GetUserByID(db.DefaultContext, r.RecipientID) + u, err := user_model.GetUserByID(ctx, r.RecipientID) if err != nil { return err } @@ -51,7 +51,7 @@ func (r *RepoTransfer) LoadAttributes() error { if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) { for _, v := range r.TeamIDs { - team, err := organization.GetTeamByID(db.DefaultContext, v) + team, err := organization.GetTeamByID(ctx, v) if err != nil { return err } @@ -65,7 +65,7 @@ func (r *RepoTransfer) LoadAttributes() error { } if r.Doer == nil { - u, err := user_model.GetUserByID(db.DefaultContext, r.DoerID) + u, err := user_model.GetUserByID(ctx, r.DoerID) if err != nil { return err } @@ -80,7 +80,7 @@ func (r *RepoTransfer) LoadAttributes() error { // For user, it checks if it's himself // For organizations, it checks if the user is able to create repos func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool { - if err := r.LoadAttributes(); err != nil { + if err := r.LoadAttributes(db.DefaultContext); err != nil { log.Error("LoadAttributes: %v", err) return false } @@ -89,7 +89,7 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool { return r.RecipientID == u.ID } - allowed, err := organization.CanCreateOrgRepo(r.RecipientID, u.ID) + allowed, err := organization.CanCreateOrgRepo(db.DefaultContext, r.RecipientID, u.ID) if err != nil { log.Error("CanCreateOrgRepo: %v", err) return false @@ -100,10 +100,10 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool { // GetPendingRepositoryTransfer fetches the most recent and ongoing transfer // process for the repository -func GetPendingRepositoryTransfer(repo *repo_model.Repository) (*RepoTransfer, error) { +func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Repository) (*RepoTransfer, error) { transfer := new(RepoTransfer) - has, err := db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repo.ID).Get(transfer) + has, err := db.GetEngine(ctx).Where("repo_id = ? ", repo.ID).Get(transfer) if err != nil { return nil, err } @@ -154,56 +154,48 @@ func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error { // CreatePendingRepositoryTransfer transfer a repo from one owner to a new one. // it marks the repository transfer as "pending" -func CreatePendingRepositoryTransfer(doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error { - ctx, committer, err := db.TxContext(db.DefaultContext) - if err != nil { - return err - } - defer committer.Close() - - repo, err := repo_model.GetRepositoryByID(ctx, repoID) - if err != nil { - return err - } - - // Make sure repo is ready to transfer - if err := TestRepositoryReadyForTransfer(repo.Status); err != nil { - return err - } +func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error { + return db.AutoTx(ctx, func(ctx context.Context) error { + repo, err := repo_model.GetRepositoryByID(ctx, repoID) + if err != nil { + return err + } - repo.Status = repo_model.RepositoryPendingTransfer - if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { - return err - } + // Make sure repo is ready to transfer + if err := TestRepositoryReadyForTransfer(repo.Status); err != nil { + return err + } - // Check if new owner has repository with same name. - if has, err := repo_model.IsRepositoryExist(ctx, newOwner, repo.Name); err != nil { - return fmt.Errorf("IsRepositoryExist: %w", err) - } else if has { - return repo_model.ErrRepoAlreadyExist{ - Uname: newOwner.LowerName, - Name: repo.Name, + repo.Status = repo_model.RepositoryPendingTransfer + if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + return err } - } - transfer := &RepoTransfer{ - RepoID: repo.ID, - RecipientID: newOwner.ID, - CreatedUnix: timeutil.TimeStampNow(), - UpdatedUnix: timeutil.TimeStampNow(), - DoerID: doer.ID, - TeamIDs: make([]int64, 0, len(teams)), - } + // Check if new owner has repository with same name. + if has, err := repo_model.IsRepositoryExist(ctx, newOwner, repo.Name); err != nil { + return fmt.Errorf("IsRepositoryExist: %w", err) + } else if has { + return repo_model.ErrRepoAlreadyExist{ + Uname: newOwner.LowerName, + Name: repo.Name, + } + } - for k := range teams { - transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID) - } + transfer := &RepoTransfer{ + RepoID: repo.ID, + RecipientID: newOwner.ID, + CreatedUnix: timeutil.TimeStampNow(), + UpdatedUnix: timeutil.TimeStampNow(), + DoerID: doer.ID, + TeamIDs: make([]int64, 0, len(teams)), + } - if err := db.Insert(ctx, transfer); err != nil { - return err - } + for k := range teams { + transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID) + } - return committer.Commit() + return db.Insert(ctx, transfer) + }) } // TransferOwnership transfers all corresponding repository items from old user to new one. diff --git a/models/repo_transfer_test.go b/models/repo_transfer_test.go index 9720071a98..8352adc948 100644 --- a/models/repo_transfer_test.go +++ b/models/repo_transfer_test.go @@ -6,6 +6,7 @@ package models import ( "testing" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -19,36 +20,36 @@ func TestRepositoryTransfer(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - transfer, err := GetPendingRepositoryTransfer(repo) + transfer, err := GetPendingRepositoryTransfer(db.DefaultContext, repo) assert.NoError(t, err) assert.NotNil(t, transfer) // Cancel transfer assert.NoError(t, CancelRepositoryTransfer(repo)) - transfer, err = GetPendingRepositoryTransfer(repo) + transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo) assert.Error(t, err) assert.Nil(t, transfer) assert.True(t, IsErrNoPendingTransfer(err)) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, CreatePendingRepositoryTransfer(doer, user2, repo.ID, nil)) + assert.NoError(t, CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil)) - transfer, err = GetPendingRepositoryTransfer(repo) + transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo) assert.Nil(t, err) - assert.NoError(t, transfer.LoadAttributes()) + assert.NoError(t, transfer.LoadAttributes(db.DefaultContext)) assert.Equal(t, "user2", transfer.Recipient.Name) user6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // Only transfer can be started at any given time - err = CreatePendingRepositoryTransfer(doer, user6, repo.ID, nil) + err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, user6, repo.ID, nil) assert.Error(t, err) assert.True(t, IsErrRepoTransferInProgress(err)) // Unknown user - err = CreatePendingRepositoryTransfer(doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil) + err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil) assert.Error(t, err) // Cancel transfer |