diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/forms/repo_form.go | 23 | ||||
-rw-r--r-- | services/migrations/migrate.go | 18 | ||||
-rw-r--r-- | services/org/org.go | 5 | ||||
-rw-r--r-- | services/org/org_test.go | 4 | ||||
-rw-r--r-- | services/pull/check.go | 5 | ||||
-rw-r--r-- | services/pull/merge.go | 119 | ||||
-rw-r--r-- | services/pull/merge_prepare.go | 45 | ||||
-rw-r--r-- | services/pull/patch.go | 28 | ||||
-rw-r--r-- | services/pull/pull.go | 27 | ||||
-rw-r--r-- | services/release/release.go | 68 | ||||
-rw-r--r-- | services/repository/branch.go | 4 | ||||
-rw-r--r-- | services/repository/files/cherry_pick.go | 19 | ||||
-rw-r--r-- | services/repository/files/content.go | 5 | ||||
-rw-r--r-- | services/repository/files/file.go | 19 | ||||
-rw-r--r-- | services/repository/files/patch.go | 27 | ||||
-rw-r--r-- | services/repository/files/temp_repo.go | 3 | ||||
-rw-r--r-- | services/repository/files/tree.go | 23 | ||||
-rw-r--r-- | services/repository/files/update.go | 108 | ||||
-rw-r--r-- | services/user/update.go | 3 | ||||
-rw-r--r-- | services/user/user.go | 11 | ||||
-rw-r--r-- | services/user/user_test.go | 3 |
21 files changed, 457 insertions, 110 deletions
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 7647c74e46..b14171787e 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -6,10 +6,8 @@ package forms import ( "net/http" - "net/url" "strings" - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" project_model "code.gitea.io/gitea/models/project" "code.gitea.io/gitea/modules/setting" @@ -90,27 +88,6 @@ func (f *MigrateRepoForm) Validate(req *http.Request, errs binding.Errors) bindi return middleware.Validate(errs, ctx.Data, f, ctx.Locale) } -// ParseRemoteAddr checks if given remote address is valid, -// and returns composed URL with needed username and password. -func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) { - remoteAddr = strings.TrimSpace(remoteAddr) - // Remote address can be HTTP/HTTPS/Git URL or local path. - if strings.HasPrefix(remoteAddr, "http://") || - strings.HasPrefix(remoteAddr, "https://") || - strings.HasPrefix(remoteAddr, "git://") { - u, err := url.Parse(remoteAddr) - if err != nil { - return "", &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr} - } - if len(authUsername)+len(authPassword) > 0 { - u.User = url.UserPassword(authUsername, authPassword) - } - remoteAddr = u.String() - } - - return remoteAddr, nil -} - // RepoSettingForm form for changing repository settings type RepoSettingForm struct { RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` diff --git a/services/migrations/migrate.go b/services/migrations/migrate.go index d0ad6d0139..51b22d6111 100644 --- a/services/migrations/migrate.go +++ b/services/migrations/migrate.go @@ -12,10 +12,10 @@ import ( "path/filepath" "strings" - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" @@ -43,16 +43,16 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error { // Remote address can be HTTP/HTTPS/Git URL or local path. u, err := url.Parse(remoteURL) if err != nil { - return &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL} + return &git.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL} } if u.Scheme == "file" || u.Scheme == "" { if !doer.CanImportLocal() { - return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsPermissionDenied: true, LocalPath: true} + return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsPermissionDenied: true, LocalPath: true} } isAbs := filepath.IsAbs(u.Host + u.Path) if !isAbs { - return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} + return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} } isDir, err := util.IsDir(u.Host + u.Path) if err != nil { @@ -60,18 +60,18 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error { return err } if !isDir { - return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} + return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} } return nil } if u.Scheme == "git" && u.Port() != "" && (strings.Contains(remoteURL, "%0d") || strings.Contains(remoteURL, "%0a")) { - return &models.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true} + return &git.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true} } if u.Opaque != "" || u.Scheme != "" && u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "git" { - return &models.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true} + return &git.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true} } hostName, _, err := net.SplitHostPort(u.Host) @@ -95,12 +95,12 @@ func checkByAllowBlockList(hostName string, addrList []net.IP) error { } var blockedError error if blockList.MatchHostName(hostName) || ipBlocked { - blockedError = &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} + blockedError = &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} } // if we have an allow-list, check the allow-list before return to get the more accurate error if !allowList.IsEmpty() { if !allowList.MatchHostName(hostName) && !ipAllowed { - return &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} + return &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} } } // otherwise, we always follow the blocked list diff --git a/services/org/org.go b/services/org/org.go index 471e6fcaf1..3d30ae21a3 100644 --- a/services/org/org.go +++ b/services/org/org.go @@ -7,7 +7,6 @@ import ( "context" "fmt" - "code.gitea.io/gitea/models" actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" org_model "code.gitea.io/gitea/models/organization" @@ -67,14 +66,14 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge if err != nil { return fmt.Errorf("GetRepositoryCount: %w", err) } else if count > 0 { - return models.ErrUserOwnRepos{UID: org.ID} + return repo_model.ErrUserOwnRepos{UID: org.ID} } // Check ownership of packages. if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil { return fmt.Errorf("HasOwnerPackages: %w", err) } else if ownsPackages { - return models.ErrUserOwnPackages{UID: org.ID} + return packages_model.ErrUserOwnPackages{UID: org.ID} } if err := deleteOrganization(ctx, org); err != nil { diff --git a/services/org/org_test.go b/services/org/org_test.go index e7d2a18ea9..791404c5c8 100644 --- a/services/org/org_test.go +++ b/services/org/org_test.go @@ -6,9 +6,9 @@ package org import ( "testing" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" + repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -30,7 +30,7 @@ func TestDeleteOrganization(t *testing.T) { org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) err := DeleteOrganization(db.DefaultContext, org, false) assert.Error(t, err) - assert.True(t, models.IsErrUserOwnRepos(err)) + assert.True(t, repo_model.IsErrUserOwnRepos(err)) user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) assert.Error(t, DeleteOrganization(db.DefaultContext, user, false)) diff --git a/services/pull/check.go b/services/pull/check.go index 736be4611b..bffca394a8 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -11,7 +11,6 @@ import ( "strconv" "strings" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" @@ -36,7 +35,7 @@ var prPatchCheckerQueue *queue.WorkerPoolQueue[string] var ( ErrIsClosed = errors.New("pull is closed") - ErrUserNotAllowedToMerge = models.ErrDisallowedToMerge{} + ErrUserNotAllowedToMerge = ErrDisallowedToMerge{} ErrHasMerged = errors.New("has already been merged") ErrIsWorkInProgress = errors.New("work in progress PRs cannot be merged") ErrIsChecking = errors.New("cannot merge while conflict checking is in progress") @@ -106,7 +105,7 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc } if err := CheckPullBranchProtections(ctx, pr, false); err != nil { - if !models.IsErrDisallowedToMerge(err) { + if !IsErrDisallowedToMerge(err) { log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err) return err } diff --git a/services/pull/merge.go b/services/pull/merge.go index a3fbe4f627..fba85f1e51 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -13,7 +13,6 @@ import ( "strconv" "strings" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" @@ -30,6 +29,7 @@ import ( repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" issue_service "code.gitea.io/gitea/services/issue" notify_service "code.gitea.io/gitea/services/notify" ) @@ -159,6 +159,27 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr return getMergeMessage(ctx, baseGitRepo, pr, mergeStyle, nil) } +// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy +type ErrInvalidMergeStyle struct { + ID int64 + Style repo_model.MergeStyle +} + +// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle. +func IsErrInvalidMergeStyle(err error) bool { + _, ok := err.(ErrInvalidMergeStyle) + return ok +} + +func (err ErrInvalidMergeStyle) Error() string { + return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]", + err.ID, err.Style) +} + +func (err ErrInvalidMergeStyle) Unwrap() error { + return util.ErrInvalidArgument +} + // Merge merges pull request to base repository. // Caller should check PR is ready to be merged (review and status checks) func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error { @@ -179,7 +200,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U // Check if merge style is correct and allowed if !prConfig.IsMergeStyleAllowed(mergeStyle) { - return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} + return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} } releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID)) @@ -283,7 +304,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use return "", err } default: - return "", models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} + return "", ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} } // OK we should cache our current head and origin/headbranch @@ -374,13 +395,66 @@ func commitAndSignNoAuthor(ctx *mergeContext, message string) error { return nil } +// ErrMergeConflicts represents an error if merging fails with a conflict +type ErrMergeConflicts struct { + Style repo_model.MergeStyle + StdOut string + StdErr string + Err error +} + +// IsErrMergeConflicts checks if an error is a ErrMergeConflicts. +func IsErrMergeConflicts(err error) bool { + _, ok := err.(ErrMergeConflicts) + return ok +} + +func (err ErrMergeConflicts) Error() string { + return fmt.Sprintf("Merge Conflict Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut) +} + +// ErrMergeUnrelatedHistories represents an error if merging fails due to unrelated histories +type ErrMergeUnrelatedHistories struct { + Style repo_model.MergeStyle + StdOut string + StdErr string + Err error +} + +// IsErrMergeUnrelatedHistories checks if an error is a ErrMergeUnrelatedHistories. +func IsErrMergeUnrelatedHistories(err error) bool { + _, ok := err.(ErrMergeUnrelatedHistories) + return ok +} + +func (err ErrMergeUnrelatedHistories) Error() string { + return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut) +} + +// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge +type ErrMergeDivergingFastForwardOnly struct { + StdOut string + StdErr string + Err error +} + +// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly. +func IsErrMergeDivergingFastForwardOnly(err error) bool { + _, ok := err.(ErrMergeDivergingFastForwardOnly) + return ok +} + +func (err ErrMergeDivergingFastForwardOnly) Error() string { + return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut) +} + func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error { if err := cmd.Run(ctx.RunOpts()); err != nil { // Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil { // We have a merge conflict error log.Debug("MergeConflict %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) - return models.ErrMergeConflicts{ + return ErrMergeConflicts{ Style: mergeStyle, StdOut: ctx.outbuf.String(), StdErr: ctx.errbuf.String(), @@ -388,7 +462,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g } } else if strings.Contains(ctx.errbuf.String(), "refusing to merge unrelated histories") { log.Debug("MergeUnrelatedHistories %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) - return models.ErrMergeUnrelatedHistories{ + return ErrMergeUnrelatedHistories{ Style: mergeStyle, StdOut: ctx.outbuf.String(), StdErr: ctx.errbuf.String(), @@ -396,7 +470,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g } } else if mergeStyle == repo_model.MergeStyleFastForwardOnly && strings.Contains(ctx.errbuf.String(), "Not possible to fast-forward, aborting") { log.Debug("MergeDivergingFastForwardOnly %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) - return models.ErrMergeDivergingFastForwardOnly{ + return ErrMergeDivergingFastForwardOnly{ StdOut: ctx.outbuf.String(), StdErr: ctx.errbuf.String(), Err: err, @@ -431,6 +505,25 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a return false, nil } +// ErrDisallowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it. +type ErrDisallowedToMerge struct { + Reason string +} + +// IsErrDisallowedToMerge checks if an error is an ErrDisallowedToMerge. +func IsErrDisallowedToMerge(err error) bool { + _, ok := err.(ErrDisallowedToMerge) + return ok +} + +func (err ErrDisallowedToMerge) Error() string { + return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason) +} + +func (err ErrDisallowedToMerge) Unwrap() error { + return util.ErrPermissionDenied +} + // CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks) func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) { if err = pr.LoadBaseRepo(ctx); err != nil { @@ -450,29 +543,29 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques return err } if !isPass { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "Not all required status checks successful", } } if !issues_model.HasEnoughApprovals(ctx, pb, pr) { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "Does not have enough approvals", } } if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "There are requested changes", } } if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "There are official review requests", } } if issues_model.MergeBlockedByOutdatedBranch(pb, pr) { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "The head branch is behind the base branch", } } @@ -482,7 +575,7 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques } if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) { - return models.ErrDisallowedToMerge{ + return ErrDisallowedToMerge{ Reason: "Changed protected files", } } @@ -511,7 +604,7 @@ func MergedManually(ctx context.Context, pr *issues_model.PullRequest, doer *use // Check if merge style is correct and allowed if !prConfig.IsMergeStyleAllowed(repo_model.MergeStyleManuallyMerged) { - return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged} + return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged} } objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName) diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 88f6c037eb..2e1cc8cf85 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -14,7 +14,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -43,6 +42,23 @@ func (ctx *mergeContext) RunOpts() *git.RunOpts { } } +// ErrSHADoesNotMatch represents a "SHADoesNotMatch" kind of error. +type ErrSHADoesNotMatch struct { + Path string + GivenSHA string + CurrentSHA string +} + +// IsErrSHADoesNotMatch checks if an error is a ErrSHADoesNotMatch. +func IsErrSHADoesNotMatch(err error) bool { + _, ok := err.(ErrSHADoesNotMatch) + return ok +} + +func (err ErrSHADoesNotMatch) Error() string { + return fmt.Sprintf("sha does not match [given: %s, expected: %s]", err.GivenSHA, err.CurrentSHA) +} + func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, expectedHeadCommitID string) (mergeCtx *mergeContext, cancel context.CancelFunc, err error) { // Clone base repo. prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr) @@ -65,7 +81,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque } if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID { defer cancel() - return nil, nil, models.ErrSHADoesNotMatch{ + return nil, nil, ErrSHADoesNotMatch{ GivenSHA: expectedHeadCommitID, CurrentSHA: trackingCommitID, } @@ -233,8 +249,27 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, o return err } +// ErrRebaseConflicts represents an error if rebase fails with a conflict +type ErrRebaseConflicts struct { + Style repo_model.MergeStyle + CommitSHA string + StdOut string + StdErr string + Err error +} + +// IsErrRebaseConflicts checks if an error is a ErrRebaseConflicts. +func IsErrRebaseConflicts(err error) bool { + _, ok := err.(ErrRebaseConflicts) + return ok +} + +func (err ErrRebaseConflicts) Error() string { + return fmt.Sprintf("Rebase Error: %v: Whilst Rebasing: %s\n%s\n%s", err.Err, err.CommitSHA, err.StdErr, err.StdOut) +} + // rebaseTrackingOnToBase checks out the tracking branch as staging and rebases it on to the base branch -// if there is a conflict it will return a models.ErrRebaseConflicts +// if there is a conflict it will return an ErrRebaseConflicts func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error { // Checkout head branch if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). @@ -268,11 +303,11 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) } } if !ok { - log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as models.ErrRebaseConflicts.", ctx.pr) + log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as ErrRebaseConflicts.", ctx.pr) return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) } log.Debug("Conflict when rebasing staging on to base in %-v at %s: %v\n%s\n%s", ctx.pr, commitSha, err, ctx.outbuf.String(), ctx.errbuf.String()) - return models.ErrRebaseConflicts{ + return ErrRebaseConflicts{ CommitSHA: commitSha, Style: mergeStyle, StdOut: ctx.outbuf.String(), diff --git a/services/pull/patch.go b/services/pull/patch.go index 0934a86c89..36ca9dbdb6 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -13,7 +13,6 @@ import ( "path/filepath" "strings" - "code.gitea.io/gitea/models" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unit" @@ -502,6 +501,29 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * return false, nil } +// ErrFilePathProtected represents a "FilePathProtected" kind of error. +type ErrFilePathProtected struct { + Message string + Path string +} + +// IsErrFilePathProtected checks if an error is an ErrFilePathProtected. +func IsErrFilePathProtected(err error) bool { + _, ok := err.(ErrFilePathProtected) + return ok +} + +func (err ErrFilePathProtected) Error() string { + if err.Message != "" { + return err.Message + } + return fmt.Sprintf("path is protected and can not be changed [path: %s]", err.Path) +} + +func (err ErrFilePathProtected) Unwrap() error { + return util.ErrPermissionDenied +} + // CheckFileProtection check file Protection func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) { if len(patterns) == 0 { @@ -525,7 +547,7 @@ func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommi } } if len(changedProtectedFiles) > 0 { - err = models.ErrFilePathProtected{ + err = ErrFilePathProtected{ Path: changedProtectedFiles[0], } } @@ -575,7 +597,7 @@ func checkPullFilesProtection(ctx context.Context, pr *issues_model.PullRequest, } pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.HeadBranch, pr.MergeBase, "tracking", pb.GetProtectedFilePatterns(), 10, os.Environ()) - if err != nil && !models.IsErrFilePathProtected(err) { + if err != nil && !IsErrFilePathProtected(err) { return err } return nil diff --git a/services/pull/pull.go b/services/pull/pull.go index 3362cb97ff..0256c2c3f6 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -13,7 +13,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" @@ -224,6 +223,28 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error { return nil } +// ErrPullRequestHasMerged represents a "PullRequestHasMerged"-error +type ErrPullRequestHasMerged struct { + ID int64 + IssueID int64 + HeadRepoID int64 + BaseRepoID int64 + HeadBranch string + BaseBranch string +} + +// IsErrPullRequestHasMerged checks if an error is a ErrPullRequestHasMerged. +func IsErrPullRequestHasMerged(err error) bool { + _, ok := err.(ErrPullRequestHasMerged) + return ok +} + +// Error does pretty-printing :D +func (err ErrPullRequestHasMerged) Error() string { + return fmt.Sprintf("pull request has merged [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]", + err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch) +} + // ChangeTargetBranch changes the target branch of this pull request, as the given user. func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, targetBranch string) (err error) { releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID)) @@ -247,7 +268,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } if pr.HasMerged { - return models.ErrPullRequestHasMerged{ + return ErrPullRequestHasMerged{ ID: pr.ID, IssueID: pr.Index, HeadRepoID: pr.HeadRepoID, @@ -654,7 +675,7 @@ func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6 if err = pr.Issue.LoadRepo(ctx); err != nil { errs = append(errs, err) } else if err = ChangeTargetBranch(ctx, pr, doer, targetBranch); err != nil && - !issues_model.IsErrIssueIsClosed(err) && !models.IsErrPullRequestHasMerged(err) && + !issues_model.IsErrIssueIsClosed(err) && !IsErrPullRequestHasMerged(err) && !issues_model.IsErrPullRequestAlreadyExists(err) { errs = append(errs, err) } diff --git a/services/release/release.go b/services/release/release.go index 123e9ab7c7..84c60a105a 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -9,7 +9,6 @@ import ( "fmt" "strings" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" @@ -26,6 +25,44 @@ import ( notify_service "code.gitea.io/gitea/services/notify" ) +// ErrInvalidTagName represents a "InvalidTagName" kind of error. +type ErrInvalidTagName struct { + TagName string +} + +// IsErrInvalidTagName checks if an error is a ErrInvalidTagName. +func IsErrInvalidTagName(err error) bool { + _, ok := err.(ErrInvalidTagName) + return ok +} + +func (err ErrInvalidTagName) Error() string { + return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName) +} + +func (err ErrInvalidTagName) Unwrap() error { + return util.ErrInvalidArgument +} + +// ErrProtectedTagName represents a "ProtectedTagName" kind of error. +type ErrProtectedTagName struct { + TagName string +} + +// IsErrProtectedTagName checks if an error is a ErrProtectedTagName. +func IsErrProtectedTagName(err error) bool { + _, ok := err.(ErrProtectedTagName) + return ok +} + +func (err ErrProtectedTagName) Error() string { + return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName) +} + +func (err ErrProtectedTagName) Unwrap() error { + return util.ErrPermissionDenied +} + func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { err := rel.LoadAttributes(ctx) if err != nil { @@ -58,7 +95,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel return false, err } if !isAllowed { - return false, models.ErrProtectedTagName{ + return false, ErrProtectedTagName{ TagName: rel.TagName, } } @@ -71,7 +108,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel if len(msg) > 0 { if err = gitRepo.CreateAnnotatedTag(rel.TagName, msg, commit.ID.String()); err != nil { if strings.Contains(err.Error(), "is not a valid tag name") { - return false, models.ErrInvalidTagName{ + return false, ErrInvalidTagName{ TagName: rel.TagName, } } @@ -79,7 +116,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel } } else if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { if strings.Contains(err.Error(), "is not a valid tag name") { - return false, models.ErrInvalidTagName{ + return false, ErrInvalidTagName{ TagName: rel.TagName, } } @@ -159,13 +196,32 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU return nil } +// ErrTagAlreadyExists represents an error that tag with such name already exists. +type ErrTagAlreadyExists struct { + TagName string +} + +// IsErrTagAlreadyExists checks if an error is an ErrTagAlreadyExists. +func IsErrTagAlreadyExists(err error) bool { + _, ok := err.(ErrTagAlreadyExists) + return ok +} + +func (err ErrTagAlreadyExists) Error() string { + return fmt.Sprintf("tag already exists [name: %s]", err.TagName) +} + +func (err ErrTagAlreadyExists) Unwrap() error { + return util.ErrAlreadyExist +} + // CreateNewTag creates a new repository tag func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commit, tagName, msg string) error { has, err := repo_model.IsReleaseExist(ctx, repo.ID, tagName) if err != nil { return err } else if has { - return models.ErrTagAlreadyExists{ + return ErrTagAlreadyExists{ TagName: tagName, } } @@ -320,7 +376,7 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re return err } if !isAllowed { - return models.ErrProtectedTagName{ + return ErrProtectedTagName{ TagName: rel.TagName, } } diff --git a/services/repository/branch.go b/services/repository/branch.go index 3a95aab264..fc476298ca 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -9,7 +9,6 @@ import ( "fmt" "strings" - "code.gitea.io/gitea/models" actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" @@ -31,6 +30,7 @@ import ( "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" notify_service "code.gitea.io/gitea/services/notify" + release_service "code.gitea.io/gitea/services/release" files_service "code.gitea.io/gitea/services/repository/files" "xorm.io/builder" @@ -274,7 +274,7 @@ func checkBranchName(ctx context.Context, repo *repo_model.Repository, name stri BranchName: branchRefName, } case refName == git.TagPrefix+name: - return models.ErrTagAlreadyExists{ + return release_service.ErrTagAlreadyExists{ TagName: name, } } diff --git a/services/repository/files/cherry_pick.go b/services/repository/files/cherry_pick.go index 451a182155..10545e9e03 100644 --- a/services/repository/files/cherry_pick.go +++ b/services/repository/files/cherry_pick.go @@ -8,7 +8,6 @@ import ( "fmt" "strings" - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -17,6 +16,22 @@ import ( "code.gitea.io/gitea/services/pull" ) +// ErrCommitIDDoesNotMatch represents a "CommitIDDoesNotMatch" kind of error. +type ErrCommitIDDoesNotMatch struct { + GivenCommitID string + CurrentCommitID string +} + +// IsErrCommitIDDoesNotMatch checks if an error is a ErrCommitIDDoesNotMatch. +func IsErrCommitIDDoesNotMatch(err error) bool { + _, ok := err.(ErrCommitIDDoesNotMatch) + return ok +} + +func (err ErrCommitIDDoesNotMatch) Error() string { + return fmt.Sprintf("file CommitID does not match [given: %s, expected: %s]", err.GivenCommitID, err.CurrentCommitID) +} + // CherryPick cherrypicks or reverts a commit to the given repository func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, revert bool, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) { if err := opts.Validate(ctx, repo, doer); err != nil { @@ -57,7 +72,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod } opts.LastCommitID = lastCommitID.String() if commit.ID.String() != opts.LastCommitID { - return nil, models.ErrCommitIDDoesNotMatch{ + return nil, ErrCommitIDDoesNotMatch{ GivenCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID, } diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 95e7c7087c..0ab7422ce2 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -10,7 +10,6 @@ import ( "path" "strings" - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" @@ -53,7 +52,7 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, treePat // Check that the path given in opts.treePath is valid (not a git path) cleanTreePath := CleanUploadFileName(treePath) if cleanTreePath == "" && treePath != "" { - return nil, models.ErrFilenameInvalid{ + return nil, ErrFilenameInvalid{ Path: treePath, } } @@ -128,7 +127,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref // Check that the path given in opts.treePath is valid (not a git path) cleanTreePath := CleanUploadFileName(treePath) if cleanTreePath == "" && treePath != "" { - return nil, models.ErrFilenameInvalid{ + return nil, ErrFilenameInvalid{ Path: treePath, } } diff --git a/services/repository/files/file.go b/services/repository/files/file.go index 16783f5b5f..d7ca8e79e5 100644 --- a/services/repository/files/file.go +++ b/services/repository/files/file.go @@ -156,6 +156,25 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m return authorUser, committerUser } +// ErrFilenameInvalid represents a "FilenameInvalid" kind of error. +type ErrFilenameInvalid struct { + Path string +} + +// IsErrFilenameInvalid checks if an error is an ErrFilenameInvalid. +func IsErrFilenameInvalid(err error) bool { + _, ok := err.(ErrFilenameInvalid) + return ok +} + +func (err ErrFilenameInvalid) Error() string { + return fmt.Sprintf("path contains a malformed path component [path: %s]", err.Path) +} + +func (err ErrFilenameInvalid) Unwrap() error { + return util.ErrInvalidArgument +} + // CleanUploadFileName Trims a filename and returns empty string if it is a .git directory func CleanUploadFileName(name string) string { // Rebase the filename diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index ab0e7ffd36..38c17b4073 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -8,7 +8,6 @@ import ( "fmt" "strings" - "code.gitea.io/gitea/models" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -16,9 +15,29 @@ import ( "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" asymkey_service "code.gitea.io/gitea/services/asymkey" ) +// ErrUserCannotCommit represents "UserCannotCommit" kind of error. +type ErrUserCannotCommit struct { + UserName string +} + +// IsErrUserCannotCommit checks if an error is an ErrUserCannotCommit. +func IsErrUserCannotCommit(err error) bool { + _, ok := err.(ErrUserCannotCommit) + return ok +} + +func (err ErrUserCannotCommit) Error() string { + return fmt.Sprintf("user cannot commit to repo [user: %s]", err.UserName) +} + +func (err ErrUserCannotCommit) Unwrap() error { + return util.ErrPermissionDenied +} + // ApplyDiffPatchOptions holds the repository diff patch update options type ApplyDiffPatchOptions struct { LastCommitID string @@ -74,7 +93,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode if protectedBranch != nil { protectedBranch.Repo = repo if !protectedBranch.CanUserPush(ctx, doer) { - return models.ErrUserCannotCommit{ + return ErrUserCannotCommit{ UserName: doer.LowerName, } } @@ -85,7 +104,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode if !asymkey_service.IsErrWontSign(err) { return err } - return models.ErrUserCannotCommit{ + return ErrUserCannotCommit{ UserName: doer.LowerName, } } @@ -137,7 +156,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user } opts.LastCommitID = lastCommitID.String() if commit.ID.String() != opts.LastCommitID { - return nil, models.ErrCommitIDDoesNotMatch{ + return nil, ErrCommitIDDoesNotMatch{ GivenCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID, } diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 30ab22db1e..138af991f9 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -13,7 +13,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -187,7 +186,7 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(mode, objectHash, objectPat if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil { stderr := err.Error() if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched { - return models.ErrFilePathInvalid{ + return ErrFilePathInvalid{ Message: objectPath, Path: objectPath, } diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go index e3a7f3b8b0..6775186afd 100644 --- a/services/repository/files/tree.go +++ b/services/repository/files/tree.go @@ -8,18 +8,37 @@ import ( "fmt" "net/url" - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" ) +// ErrSHANotFound represents a "SHADoesNotMatch" kind of error. +type ErrSHANotFound struct { + SHA string +} + +// IsErrSHANotFound checks if an error is a ErrSHANotFound. +func IsErrSHANotFound(err error) bool { + _, ok := err.(ErrSHANotFound) + return ok +} + +func (err ErrSHANotFound) Error() string { + return fmt.Sprintf("sha not found [%s]", err.SHA) +} + +func (err ErrSHANotFound) Unwrap() error { + return util.ErrNotExist +} + // GetTreeBySHA get the GitTreeResponse of a repository using a sha hash. func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) { gitTree, err := gitRepo.GetTree(sha) if err != nil || gitTree == nil { - return nil, models.ErrSHANotFound{ + return nil, ErrSHANotFound{ // TODO: this error has never been catch outside of this function SHA: sha, } } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index b1b64bacd9..a2763105b0 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -11,7 +11,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -21,7 +20,9 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" asymkey_service "code.gitea.io/gitea/services/asymkey" + pull_service "code.gitea.io/gitea/services/pull" ) // IdentityOptions for a person's identity like an author or committer @@ -64,6 +65,26 @@ type RepoFileOptions struct { executable bool } +// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error. +type ErrRepoFileDoesNotExist struct { + Path string + Name string +} + +// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist. +func IsErrRepoFileDoesNotExist(err error) bool { + _, ok := err.(ErrRepoFileDoesNotExist) + return ok +} + +func (err ErrRepoFileDoesNotExist) Error() string { + return fmt.Sprintf("repository file does not exist [path: %s]", err.Path) +} + +func (err ErrRepoFileDoesNotExist) Unwrap() error { + return util.ErrNotExist +} + // ChangeRepoFiles adds, updates or removes multiple files in the given repository func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ChangeRepoFilesOptions) (*structs.FilesResponse, error) { err := repo.MustNotBeArchived() @@ -100,14 +121,14 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use // Check that the path given in opts.treePath is valid (not a git path) treePath := CleanUploadFileName(file.TreePath) if treePath == "" { - return nil, models.ErrFilenameInvalid{ + return nil, ErrFilenameInvalid{ Path: file.TreePath, } } // If there is a fromTreePath (we are copying it), also clean it up fromTreePath := CleanUploadFileName(file.FromTreePath) if fromTreePath == "" && file.FromTreePath != "" { - return nil, models.ErrFilenameInvalid{ + return nil, ErrFilenameInvalid{ Path: file.FromTreePath, } } @@ -185,7 +206,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } } if !inFilelist { - return nil, models.ErrRepoFileDoesNotExist{ + return nil, ErrRepoFileDoesNotExist{ Path: file.TreePath, } } @@ -276,6 +297,63 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use return filesResponse, nil } +// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error. +type ErrRepoFileAlreadyExists struct { + Path string +} + +// IsErrRepoFileAlreadyExists checks if an error is a ErrRepoFileAlreadyExists. +func IsErrRepoFileAlreadyExists(err error) bool { + _, ok := err.(ErrRepoFileAlreadyExists) + return ok +} + +func (err ErrRepoFileAlreadyExists) Error() string { + return fmt.Sprintf("repository file already exists [path: %s]", err.Path) +} + +func (err ErrRepoFileAlreadyExists) Unwrap() error { + return util.ErrAlreadyExist +} + +// ErrFilePathInvalid represents a "FilePathInvalid" kind of error. +type ErrFilePathInvalid struct { + Message string + Path string + Name string + Type git.EntryMode +} + +// IsErrFilePathInvalid checks if an error is an ErrFilePathInvalid. +func IsErrFilePathInvalid(err error) bool { + _, ok := err.(ErrFilePathInvalid) + return ok +} + +func (err ErrFilePathInvalid) Error() string { + if err.Message != "" { + return err.Message + } + return fmt.Sprintf("path is invalid [path: %s]", err.Path) +} + +func (err ErrFilePathInvalid) Unwrap() error { + return util.ErrInvalidArgument +} + +// ErrSHAOrCommitIDNotProvided represents a "SHAOrCommitIDNotProvided" kind of error. +type ErrSHAOrCommitIDNotProvided struct{} + +// IsErrSHAOrCommitIDNotProvided checks if an error is a ErrSHAOrCommitIDNotProvided. +func IsErrSHAOrCommitIDNotProvided(err error) bool { + _, ok := err.(ErrSHAOrCommitIDNotProvided) + return ok +} + +func (err ErrSHAOrCommitIDNotProvided) Error() string { + return "a SHA or commit ID must be proved when updating a file" +} + // handles the check for various issues for ChangeRepoFiles func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error { if file.Operation == "update" || file.Operation == "delete" { @@ -286,7 +364,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep if file.SHA != "" { // If a SHA was given and the SHA given doesn't match the SHA of the fromTreePath, throw error if file.SHA != fromEntry.ID.String() { - return models.ErrSHADoesNotMatch{ + return pull_service.ErrSHADoesNotMatch{ Path: file.Options.treePath, GivenSHA: file.SHA, CurrentSHA: fromEntry.ID.String(), @@ -299,7 +377,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep if changed, err := commit.FileChangedSinceCommit(file.Options.treePath, opts.LastCommitID); err != nil { return err } else if changed { - return models.ErrCommitIDDoesNotMatch{ + return ErrCommitIDDoesNotMatch{ GivenCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID, } @@ -309,7 +387,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep } else { // When updating a file, a lastCommitID or SHA needs to be given to make sure other commits // haven't been made. We throw an error if one wasn't provided. - return models.ErrSHAOrCommitIDNotProvided{} + return ErrSHAOrCommitIDNotProvided{} } file.Options.executable = fromEntry.IsExecutable() } @@ -332,7 +410,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep } if index < len(treePathParts)-1 { if !entry.IsDir() { - return models.ErrFilePathInvalid{ + return ErrFilePathInvalid{ Message: fmt.Sprintf("a file exists where you’re trying to create a subdirectory [path: %s]", subTreePath), Path: subTreePath, Name: part, @@ -340,14 +418,14 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep } } } else if entry.IsLink() { - return models.ErrFilePathInvalid{ + return ErrFilePathInvalid{ Message: fmt.Sprintf("a symbolic link exists where you’re trying to create a subdirectory [path: %s]", subTreePath), Path: subTreePath, Name: part, Type: git.EntryModeSymlink, } } else if entry.IsDir() { - return models.ErrFilePathInvalid{ + return ErrFilePathInvalid{ Message: fmt.Sprintf("a directory exists where you’re trying to create a file [path: %s]", subTreePath), Path: subTreePath, Name: part, @@ -355,7 +433,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep } } else if file.Options.fromTreePath != file.Options.treePath || file.Operation == "create" { // The entry shouldn't exist if we are creating new file or moving to a new path - return models.ErrRepoFileAlreadyExists{ + return ErrRepoFileAlreadyExists{ Path: file.Options.treePath, } } @@ -376,7 +454,7 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file if file.Operation == "create" { for _, indexFile := range filesInIndex { if indexFile == file.TreePath { - return models.ErrRepoFileAlreadyExists{ + return ErrRepoFileAlreadyExists{ Path: file.TreePath, } } @@ -479,12 +557,12 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do isUnprotectedFile = protectedBranch.IsUnprotectedFile(globUnprotected, treePath) } if !canUserPush && !isUnprotectedFile { - return models.ErrUserCannotCommit{ + return ErrUserCannotCommit{ UserName: doer.LowerName, } } if protectedBranch.IsProtectedFile(globProtected, treePath) { - return models.ErrFilePathProtected{ + return pull_service.ErrFilePathProtected{ Path: treePath, } } @@ -495,7 +573,7 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do if !asymkey_service.IsErrWontSign(err) { return err } - return models.ErrUserCannotCommit{ + return ErrUserCannotCommit{ UserName: doer.LowerName, } } diff --git a/services/user/update.go b/services/user/update.go index cbaf90053a..4a39f4f783 100644 --- a/services/user/update.go +++ b/services/user/update.go @@ -7,7 +7,6 @@ import ( "context" "fmt" - "code.gitea.io/gitea/models" auth_model "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" password_module "code.gitea.io/gitea/modules/auth/password" @@ -113,7 +112,7 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er } if opts.IsAdmin.Has() { if !opts.IsAdmin.Value() && user_model.IsLastAdminUser(ctx, u) { - return models.ErrDeleteLastAdminUser{UID: u.ID} + return user_model.ErrDeleteLastAdminUser{UID: u.ID} } u.IsAdmin = opts.IsAdmin.Value() diff --git a/services/user/user.go b/services/user/user.go index 7bde642412..1aeebff142 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -10,7 +10,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" @@ -127,7 +126,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { } if u.IsActive && user_model.IsLastAdminUser(ctx, u) { - return models.ErrDeleteLastAdminUser{UID: u.ID} + return user_model.ErrDeleteLastAdminUser{UID: u.ID} } if purge { @@ -225,7 +224,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { if err != nil { return fmt.Errorf("GetRepositoryCount: %w", err) } else if count > 0 { - return models.ErrUserOwnRepos{UID: u.ID} + return repo_model.ErrUserOwnRepos{UID: u.ID} } // Check membership of organization. @@ -233,14 +232,14 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { if err != nil { return fmt.Errorf("GetOrganizationCount: %w", err) } else if count > 0 { - return models.ErrUserHasOrgs{UID: u.ID} + return organization.ErrUserHasOrgs{UID: u.ID} } // Check ownership of packages. if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil { return fmt.Errorf("HasOwnerPackages: %w", err) } else if ownsPackages { - return models.ErrUserOwnPackages{UID: u.ID} + return packages_model.ErrUserOwnPackages{UID: u.ID} } if err := deleteUser(ctx, u, purge); err != nil { @@ -288,7 +287,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error { for _, u := range inactiveUsers { if err = DeleteUser(ctx, u, false); err != nil { // Ignore inactive users that were ever active but then were set inactive by admin - if models.IsErrUserOwnRepos(err) || models.IsErrUserHasOrgs(err) || models.IsErrUserOwnPackages(err) { + if repo_model.IsErrUserOwnRepos(err) || organization.IsErrUserHasOrgs(err) || packages_model.IsErrUserOwnPackages(err) { log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err) continue } diff --git a/services/user/user_test.go b/services/user/user_test.go index c668b005c5..162a735cd4 100644 --- a/services/user/user_test.go +++ b/services/user/user_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" @@ -37,7 +36,7 @@ func TestDeleteUser(t *testing.T) { if len(ownedRepos) > 0 { err := DeleteUser(db.DefaultContext, user, false) assert.Error(t, err) - assert.True(t, models.IsErrUserOwnRepos(err)) + assert.True(t, repo_model.IsErrUserOwnRepos(err)) return } |