diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 8af3eaaf4..dceb48f16 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -40,6 +40,7 @@ var ( DisabledRepoUnits []string DefaultRepoUnits []string PrefixArchiveFiles bool + RepoMaxSize int64 // Repository editor settings Editor struct { @@ -54,6 +55,7 @@ var ( AllowedTypes []string `delim:"|"` FileMaxSize int64 MaxFiles int + TotalMaxSize int64 } `ini:"-"` // Repository local settings @@ -104,6 +106,7 @@ var ( DisabledRepoUnits: []string{}, DefaultRepoUnits: []string{}, PrefixArchiveFiles: true, + RepoMaxSize: 1024, // Repository editor settings Editor: struct { @@ -121,12 +124,14 @@ var ( AllowedTypes []string `delim:"|"` FileMaxSize int64 MaxFiles int + TotalMaxSize int64 }{ Enabled: true, TempPath: "data/tmp/uploads", AllowedTypes: []string{}, - FileMaxSize: 3, - MaxFiles: 5, + FileMaxSize: 30, + MaxFiles: 10, + TotalMaxSize: 1024, }, // Repository local settings diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 661911883..394b9b7df 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1260,6 +1260,10 @@ editor.cannot_commit_to_protected_branch = Cannot commit to protected branch '%s editor.no_commit_to_branch = Unable to commit directly to branch because: editor.user_no_push_to_branch = User cannot push to branch editor.require_signed_commit = Branch requires a signed commit +editor.repo_too_large = Repository can not exceed %d MB +editor.repo_file_invalid = Upload files are invalid +editor.upload_file_too_much = Can not upload more than %d files at a time + commits.desc = Browse source code change history. commits.commits = Commits @@ -2867,6 +2871,8 @@ uploading = Uploading upload_complete = Uploading complete failed = Upload Failed enable_minio_support = Enable minio support to use the dataset service +max_file_tooltips= Upload a maximum of ? files at a time, each file does not exceed ? MB. +max_size_tooltips= You can only upload a maximum of ? files at a time. The upload limit has been reached, please do not add more files. [notification] notifications = Notifications diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index c30fbdf8c..8982d59d7 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1267,6 +1267,9 @@ editor.cannot_commit_to_protected_branch=不可以提交到受保护的分支 '% editor.no_commit_to_branch=无法直接提交分支,因为: editor.user_no_push_to_branch=用户不能推送到分支 editor.require_signed_commit=分支需要签名提交 +editor.repo_too_large = 代码仓总大小不能超过%dMB +editor.repo_file_invalid = 提交的文件非法 +editor.upload_file_too_much = 不能同时提交超过%d个文件 commits.desc=浏览代码修改历史 commits.commits=次代码提交 @@ -2873,6 +2876,8 @@ uploading=正在上传 upload_complete=上传完成 failed=上传失败 enable_minio_support=启用minio支持以使用数据集服务 +max_file_tooltips=单次最多上传?个文件,每个文件不超过? MB。 +max_size_tooltips=一次最多只能上传?个文件, 上传已达到上限,请勿再添加文件。 [notification] notifications=通知 diff --git a/routers/repo/editor.go b/routers/repo/editor.go index 2fa7976e0..8e13735df 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -5,6 +5,7 @@ package repo import ( + repo_service "code.gitea.io/gitea/services/repository" "encoding/json" "fmt" "io/ioutil" @@ -614,6 +615,19 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) { message += "\n\n" + form.CommitMessage } + if err := repo_service.CheckPushSizeLimit4Web(ctx.Repo.Repository, form.Files); err != nil { + if repo_service.IsRepoTooLargeErr(err) { + ctx.RenderWithErr(ctx.Tr("repo.editor.repo_too_large", setting.Repository.RepoMaxSize), tplUploadFile, &form) + } else if repo_service.IsUploadFileInvalidErr(err) { + ctx.RenderWithErr(ctx.Tr("repo.editor.repo_file_invalid"), tplUploadFile, &form) + } else if repo_service.IsUploadFileTooMuchErr(err) { + ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_too_much", setting.Repository.Upload.MaxFiles), tplUploadFile, &form) + } else { + ctx.RenderWithErr(err.Error(), tplUploadFile, &form) + } + return + } + if err := repofiles.UploadRepoFiles(ctx.Repo.Repository, ctx.User, &repofiles.UploadRepoFileOptions{ LastCommitID: ctx.Repo.CommitID, OldBranch: oldBranchName, diff --git a/services/repository/repository.go b/services/repository/repository.go index cea16516a..d0cd52653 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "net/http" + "os" "strings" "code.gitea.io/gitea/models" @@ -172,3 +173,137 @@ func RecommendFromPromote(url string) ([]string, error) { } return result, nil } + +func CheckPushSizeLimit4Web(repo *models.Repository, fileIds []string) error { + if err := CheckRepoNumOnceLimit(len(fileIds)); err != nil { + return err + } + totalSize, err := CountUploadFileSizeByIds(fileIds) + if err != nil { + return UploadFileInvalidErr{} + } + if err := CheckRepoTotalSizeLimit(repo, totalSize); err != nil { + return err + } + return nil +} + +func CheckPushSizeLimit4Http(repo *models.Repository, uploadFileSize int64) error { + if err := CheckRepoOnceTotalSizeLimit(uploadFileSize); err != nil { + return err + } + if err := CheckRepoTotalSizeLimit(repo, uploadFileSize); err != nil { + return err + } + return nil +} + +func CheckRepoTotalSizeLimit(repo *models.Repository, uploadFileSize int64) error { + if repo.Size+uploadFileSize > setting.Repository.RepoMaxSize*1024*1024 { + return RepoTooLargeErr{} + } + return nil +} + +func CheckRepoOnceTotalSizeLimit(uploadFileSize int64) error { + if uploadFileSize > setting.Repository.Upload.TotalMaxSize*1024*1024 { + return UploadFileTooLargeErr{} + } + return nil +} + +func CheckRepoNumOnceLimit(uploadFileNum int) error { + if uploadFileNum > setting.Repository.Upload.MaxFiles { + return UploadFileTooMuchErr{} + } + return nil +} + +func CountUploadFileSizeByIds(fileIds []string) (int64, error) { + if len(fileIds) == 0 { + return 0, nil + } + uploads, err := models.GetUploadsByUUIDs(fileIds) + if err != nil { + return 0, fmt.Errorf("CountUploadFileSizeByIds error [uuids: %v]: %v", fileIds, err) + } + var totalSize int64 + for _, upload := range uploads { + size, err := GetUploadFileSize(upload) + if err != nil { + return 0, err + } + totalSize += size + } + return totalSize, nil +} + +func GetUploadFileSize(upload *models.Upload) (int64, error) { + info, err := os.Lstat(upload.LocalPath()) + + if err != nil { + return 0, err + } + return info.Size(), nil + +} + +type RepoTooLargeErr struct { +} + +func (RepoTooLargeErr) Error() string { + return fmt.Sprintf("Repository can not exceed %d MB. Please remove some unnecessary files and try again", setting.Repository.RepoMaxSize) +} + +func IsRepoTooLargeErr(err error) bool { + _, ok := err.(RepoTooLargeErr) + return ok +} + +type UploadFileTooLargeErr struct { +} + +func (UploadFileTooLargeErr) Error() string { + return fmt.Sprintf("Upload files can not exceed %d MB at a time", setting.Repository.Upload.TotalMaxSize) +} + +func IsUploadFileTooLargeErr(err error) bool { + _, ok := err.(UploadFileTooLargeErr) + return ok +} + +type RepoFileTooLargeErr struct { +} + +func (RepoFileTooLargeErr) Error() string { + return "repository file is too large" +} + +func IsRepoFileTooLargeErr(err error) bool { + _, ok := err.(RepoFileTooLargeErr) + return ok +} + +type UploadFileTooMuchErr struct { +} + +func (UploadFileTooMuchErr) Error() string { + return "upload files are too lmuch" +} + +func IsUploadFileTooMuchErr(err error) bool { + _, ok := err.(UploadFileTooMuchErr) + return ok +} + +type UploadFileInvalidErr struct { +} + +func (UploadFileInvalidErr) Error() string { + return "upload files are invalid" +} + +func IsUploadFileInvalidErr(err error) bool { + _, ok := err.(UploadFileInvalidErr) + return ok +} diff --git a/templates/repo/editor/upload.tmpl b/templates/repo/editor/upload.tmpl index 7794c2a2d..7eae567c2 100644 --- a/templates/repo/editor/upload.tmpl +++ b/templates/repo/editor/upload.tmpl @@ -27,10 +27,10 @@