diff options
Diffstat (limited to 'services/repository/files')
-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 |
7 files changed, 176 insertions, 28 deletions
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, } } |