mirror of
https://github.com/go-gitea/gitea
synced 2026-02-03 11:10:40 +00:00
Add ability to download subpath archive (#36371)
closes: https://github.com/go-gitea/gitea/issues/4478 --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -8,25 +8,35 @@ import (
|
||||
"net/http"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
archiver_service "code.gitea.io/gitea/services/repository/archiver"
|
||||
)
|
||||
|
||||
func serveRepoArchive(ctx *context.APIContext, reqFileName string) {
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, reqFileName)
|
||||
func serveRepoArchive(ctx *context.APIContext, reqFileName string, paths []string) {
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, reqFileName, paths)
|
||||
if err != nil {
|
||||
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
} else if errors.Is(err, archiver_service.RepoRefNotFoundError{}) {
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.APIError(http.StatusNotFound, err)
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
archiver_service.ServeRepoArchive(ctx.Base, aReq)
|
||||
err = archiver_service.ServeRepoArchive(ctx.Base, aReq)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DownloadArchive is the GitHub-compatible endpoint to download repository archives
|
||||
// TODO: The API document is missing: Add github compatible tarball download API endpoints (#32572)
|
||||
func DownloadArchive(ctx *context.APIContext) {
|
||||
var tp repo_model.ArchiveType
|
||||
switch ballType := ctx.PathParam("ball_type"); ballType {
|
||||
@@ -40,5 +50,5 @@ func DownloadArchive(ctx *context.APIContext) {
|
||||
ctx.APIError(http.StatusBadRequest, "Unknown archive type: "+ballType)
|
||||
return
|
||||
}
|
||||
serveRepoArchive(ctx, ctx.PathParam("*")+"."+tp.String())
|
||||
serveRepoArchive(ctx, ctx.PathParam("*")+"."+tp.String(), ctx.FormStrings("path"))
|
||||
}
|
||||
|
||||
@@ -273,13 +273,19 @@ func GetArchive(ctx *context.APIContext) {
|
||||
// description: the git reference for download with attached archive format (e.g. master.zip)
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: path
|
||||
// in: query
|
||||
// type: array
|
||||
// items:
|
||||
// type: string
|
||||
// description: subpath of the repository to download
|
||||
// collectionFormat: multi
|
||||
// responses:
|
||||
// 200:
|
||||
// description: success
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
serveRepoArchive(ctx, ctx.PathParam("*"))
|
||||
serveRepoArchive(ctx, ctx.PathParam("*"), ctx.FormStrings("path"))
|
||||
}
|
||||
|
||||
// GetEditorconfig get editor config of a repository
|
||||
|
||||
@@ -364,31 +364,39 @@ func RedirectDownload(ctx *context.Context) {
|
||||
|
||||
// Download an archive of a repository
|
||||
func Download(ctx *context.Context) {
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.PathParam("*"))
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.PathParam("*"), ctx.FormStrings("path"))
|
||||
if err != nil {
|
||||
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.HTTPError(http.StatusBadRequest, err.Error())
|
||||
} else if errors.Is(err, archiver_service.RepoRefNotFoundError{}) {
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.HTTPError(http.StatusNotFound, err.Error())
|
||||
} else {
|
||||
ctx.ServerError("archiver_service.NewRequest", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
archiver_service.ServeRepoArchive(ctx.Base, aReq)
|
||||
err = archiver_service.ServeRepoArchive(ctx.Base, aReq)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.HTTPError(http.StatusBadRequest, err.Error())
|
||||
} else {
|
||||
ctx.ServerError("archiver_service.ServeRepoArchive", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// InitiateDownload will enqueue an archival request, as needed. It may submit
|
||||
// a request that's already in-progress, but the archiver service will just
|
||||
// kind of drop it on the floor if this is the case.
|
||||
func InitiateDownload(ctx *context.Context) {
|
||||
if setting.Repository.StreamArchives {
|
||||
paths := ctx.FormStrings("path")
|
||||
if setting.Repository.StreamArchives || len(paths) > 0 {
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"complete": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.PathParam("*"))
|
||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.PathParam("*"), paths)
|
||||
if err != nil {
|
||||
ctx.HTTPError(http.StatusBadRequest, "invalid archive request")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user