aboutsummaryrefslogtreecommitdiffstats
path: root/routers/api/v1/packages/package.go
diff options
context:
space:
mode:
Diffstat (limited to 'routers/api/v1/packages/package.go')
-rw-r--r--routers/api/v1/packages/package.go291
1 files changed, 266 insertions, 25 deletions
diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go
index b38aa13167..41b7f2a43f 100644
--- a/routers/api/v1/packages/package.go
+++ b/routers/api/v1/packages/package.go
@@ -4,11 +4,14 @@
package packages
import (
+ "errors"
"net/http"
"code.gitea.io/gitea/models/packages"
+ repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/optional"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
@@ -53,37 +56,18 @@ func ListPackages(ctx *context.APIContext) {
listOptions := utils.GetListOptions(ctx)
- packageType := ctx.FormTrim("type")
- query := ctx.FormTrim("q")
-
- pvs, count, err := packages.SearchVersions(ctx, &packages.PackageSearchOptions{
+ apiPackages, count, err := searchPackages(ctx, &packages.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
- Type: packages.Type(packageType),
- Name: packages.SearchValue{Value: query},
+ Type: packages.Type(ctx.FormTrim("type")),
+ Name: packages.SearchValue{Value: ctx.FormTrim("q")},
IsInternal: optional.Some(false),
Paginator: &listOptions,
})
if err != nil {
- ctx.Error(http.StatusInternalServerError, "SearchVersions", err)
+ ctx.APIErrorInternal(err)
return
}
- pds, err := packages.GetPackageDescriptors(ctx, pvs)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetPackageDescriptors", err)
- return
- }
-
- apiPackages := make([]*api.Package, 0, len(pds))
- for _, pd := range pds {
- apiPackage, err := convert.ToPackage(ctx, pd, ctx.Doer)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "Error converting package for api", err)
- return
- }
- apiPackages = append(apiPackages, apiPackage)
- }
-
ctx.SetLinkHeader(int(count), listOptions.PageSize)
ctx.SetTotalCountHeader(count)
ctx.JSON(http.StatusOK, apiPackages)
@@ -125,7 +109,7 @@ func GetPackage(ctx *context.APIContext) {
apiPackage, err := convert.ToPackage(ctx, ctx.Package.Descriptor, ctx.Doer)
if err != nil {
- ctx.Error(http.StatusInternalServerError, "Error converting package for api", err)
+ ctx.APIErrorInternal(err)
return
}
@@ -166,7 +150,7 @@ func DeletePackage(ctx *context.APIContext) {
err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version)
if err != nil {
- ctx.Error(http.StatusInternalServerError, "RemovePackageVersion", err)
+ ctx.APIErrorInternal(err)
return
}
ctx.Status(http.StatusNoContent)
@@ -213,3 +197,260 @@ func ListPackageFiles(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, apiPackageFiles)
}
+
+// ListPackageVersions gets all versions of a package
+func ListPackageVersions(ctx *context.APIContext) {
+ // swagger:operation GET /packages/{owner}/{type}/{name} package listPackageVersions
+ // ---
+ // summary: Gets all versions of a package
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the package
+ // type: string
+ // required: true
+ // - name: type
+ // in: path
+ // description: type of the package
+ // type: string
+ // required: true
+ // - name: name
+ // in: path
+ // description: name of the package
+ // type: string
+ // required: true
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/PackageList"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ listOptions := utils.GetListOptions(ctx)
+
+ apiPackages, count, err := searchPackages(ctx, &packages.PackageSearchOptions{
+ OwnerID: ctx.Package.Owner.ID,
+ Type: packages.Type(ctx.PathParam("type")),
+ Name: packages.SearchValue{Value: ctx.PathParam("name"), ExactMatch: true},
+ IsInternal: optional.Some(false),
+ Paginator: &listOptions,
+ })
+ if err != nil {
+ ctx.APIErrorInternal(err)
+ return
+ }
+
+ ctx.SetLinkHeader(int(count), listOptions.PageSize)
+ ctx.SetTotalCountHeader(count)
+ ctx.JSON(http.StatusOK, apiPackages)
+}
+
+// GetLatestPackageVersion gets the latest version of a package
+func GetLatestPackageVersion(ctx *context.APIContext) {
+ // swagger:operation GET /packages/{owner}/{type}/{name}/-/latest package getLatestPackageVersion
+ // ---
+ // summary: Gets the latest version of a package
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the package
+ // type: string
+ // required: true
+ // - name: type
+ // in: path
+ // description: type of the package
+ // type: string
+ // required: true
+ // - name: name
+ // in: path
+ // description: name of the package
+ // type: string
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/Package"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ pvs, _, err := packages.SearchLatestVersions(ctx, &packages.PackageSearchOptions{
+ OwnerID: ctx.Package.Owner.ID,
+ Type: packages.Type(ctx.PathParam("type")),
+ Name: packages.SearchValue{Value: ctx.PathParam("name"), ExactMatch: true},
+ IsInternal: optional.Some(false),
+ })
+ if err != nil {
+ ctx.APIErrorInternal(err)
+ return
+ }
+ if len(pvs) == 0 {
+ ctx.APIError(http.StatusNotFound, err)
+ return
+ }
+
+ pd, err := packages.GetPackageDescriptor(ctx, pvs[0])
+ if err != nil {
+ ctx.APIErrorInternal(err)
+ return
+ }
+
+ apiPackage, err := convert.ToPackage(ctx, pd, ctx.Doer)
+ if err != nil {
+ ctx.APIErrorInternal(err)
+ return
+ }
+
+ ctx.JSON(http.StatusOK, apiPackage)
+}
+
+// LinkPackage sets a repository link for a package
+func LinkPackage(ctx *context.APIContext) {
+ // swagger:operation POST /packages/{owner}/{type}/{name}/-/link/{repo_name} package linkPackage
+ // ---
+ // summary: Link a package to a repository
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the package
+ // type: string
+ // required: true
+ // - name: type
+ // in: path
+ // description: type of the package
+ // type: string
+ // required: true
+ // - name: name
+ // in: path
+ // description: name of the package
+ // type: string
+ // required: true
+ // - name: repo_name
+ // in: path
+ // description: name of the repository to link.
+ // type: string
+ // required: true
+ // responses:
+ // "201":
+ // "$ref": "#/responses/empty"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ pkg, err := packages.GetPackageByName(ctx, ctx.ContextUser.ID, packages.Type(ctx.PathParam("type")), ctx.PathParam("name"))
+ if err != nil {
+ if errors.Is(err, util.ErrNotExist) {
+ ctx.APIError(http.StatusNotFound, err)
+ } else {
+ ctx.APIErrorInternal(err)
+ }
+ return
+ }
+
+ repo, err := repo_model.GetRepositoryByName(ctx, ctx.ContextUser.ID, ctx.PathParam("repo_name"))
+ if err != nil {
+ if errors.Is(err, util.ErrNotExist) {
+ ctx.APIError(http.StatusNotFound, err)
+ } else {
+ ctx.APIErrorInternal(err)
+ }
+ return
+ }
+
+ err = packages_service.LinkToRepository(ctx, pkg, repo, ctx.Doer)
+ if err != nil {
+ switch {
+ case errors.Is(err, util.ErrInvalidArgument):
+ ctx.APIError(http.StatusBadRequest, err)
+ case errors.Is(err, util.ErrPermissionDenied):
+ ctx.APIError(http.StatusForbidden, err)
+ default:
+ ctx.APIErrorInternal(err)
+ }
+ return
+ }
+ ctx.Status(http.StatusCreated)
+}
+
+// UnlinkPackage sets a repository link for a package
+func UnlinkPackage(ctx *context.APIContext) {
+ // swagger:operation POST /packages/{owner}/{type}/{name}/-/unlink package unlinkPackage
+ // ---
+ // summary: Unlink a package from a repository
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the package
+ // type: string
+ // required: true
+ // - name: type
+ // in: path
+ // description: type of the package
+ // type: string
+ // required: true
+ // - name: name
+ // in: path
+ // description: name of the package
+ // type: string
+ // required: true
+ // responses:
+ // "201":
+ // "$ref": "#/responses/empty"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ pkg, err := packages.GetPackageByName(ctx, ctx.ContextUser.ID, packages.Type(ctx.PathParam("type")), ctx.PathParam("name"))
+ if err != nil {
+ if errors.Is(err, util.ErrNotExist) {
+ ctx.APIError(http.StatusNotFound, err)
+ } else {
+ ctx.APIErrorInternal(err)
+ }
+ return
+ }
+
+ err = packages_service.UnlinkFromRepository(ctx, pkg, ctx.Doer)
+ if err != nil {
+ switch {
+ case errors.Is(err, util.ErrPermissionDenied):
+ ctx.APIError(http.StatusForbidden, err)
+ case errors.Is(err, util.ErrInvalidArgument):
+ ctx.APIError(http.StatusBadRequest, err)
+ default:
+ ctx.APIErrorInternal(err)
+ }
+ return
+ }
+ ctx.Status(http.StatusNoContent)
+}
+
+func searchPackages(ctx *context.APIContext, opts *packages.PackageSearchOptions) ([]*api.Package, int64, error) {
+ pvs, count, err := packages.SearchVersions(ctx, opts)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ pds, err := packages.GetPackageDescriptors(ctx, pvs)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ apiPackages := make([]*api.Package, 0, len(pds))
+ for _, pd := range pds {
+ apiPackage, err := convert.ToPackage(ctx, pd, ctx.Doer)
+ if err != nil {
+ return nil, 0, err
+ }
+ apiPackages = append(apiPackages, apiPackage)
+ }
+
+ return apiPackages, count, nil
+}