diff options
author | Exploding Dragon <explodingfkl@gmail.com> | 2024-01-12 11:16:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-12 03:16:05 +0000 |
commit | ba4d0b8ffbd78473273800f586ae8bde55cda6c5 (patch) | |
tree | d828fd0f24bf6ddb38b2b4993b152f225c778c0a /routers/api/packages | |
parent | 7c2f093e856395cc118dcaa390b7a2234b8363f3 (diff) | |
download | gitea-ba4d0b8ffbd78473273800f586ae8bde55cda6c5.tar.gz gitea-ba4d0b8ffbd78473273800f586ae8bde55cda6c5.zip |
Support for grouping RPMs using paths (#26984)
The current rpm repository places all packages in the same repository,
and different systems (el7,f34) may hit packages that do not belong to
this distribution ( #25304 ) , which now supports grouping of rpm.
![图片](https://github.com/go-gitea/gitea/assets/33776693/d1e1d99f-7799-4b2b-a19b-cb2a5c692914)
Fixes #25304 .
Fixes #27056 .
Refactor: [#25866](https://github.com/go-gitea/gitea/pull/25866)
Diffstat (limited to 'routers/api/packages')
-rw-r--r-- | routers/api/packages/api.go | 90 | ||||
-rw-r--r-- | routers/api/packages/rpm/rpm.go | 45 |
2 files changed, 105 insertions, 30 deletions
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 76116d0751..9026387129 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -512,19 +512,7 @@ func CommonRoutes() *web.Route { r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile) r.Get("/simple/{id}", pypi.PackageMetadata) }, reqPackageAccess(perm.AccessModeRead)) - r.Group("/rpm", func() { - r.Get(".repo", rpm.GetRepositoryConfig) - r.Get("/repository.key", rpm.GetRepositoryKey) - r.Put("/upload", reqPackageAccess(perm.AccessModeWrite), rpm.UploadPackageFile) - r.Group("/package/{name}/{version}/{architecture}", func() { - r.Get("", rpm.DownloadPackageFile) - r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile) - }) - r.Group("/repodata/{filename}", func() { - r.Head("", rpm.CheckRepositoryFileExistence) - r.Get("", rpm.GetRepositoryFile) - }) - }, reqPackageAccess(perm.AccessModeRead)) + r.Group("/rpm", RpmRoutes(r), reqPackageAccess(perm.AccessModeRead)) r.Group("/rubygems", func() { r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) r.Get("/latest_specs.4.8.gz", rubygems.EnumeratePackagesLatest) @@ -589,6 +577,82 @@ func CommonRoutes() *web.Route { return r } +// Support for uploading rpm packages with arbitrary depth paths +func RpmRoutes(r *web.Route) func() { + var ( + groupRepoInfo = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)\.repo\z`) + groupUpload = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/upload\z`) + groupRpm = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/package/([^/]+)/([^/]+)/([^/]+)(?:/([^/]+\.rpm)|)\z`) + groupMetadata = regexp.MustCompile(`\A((?:/(?:[^/]+))*|)/repodata/([^/]+)\z`) + ) + + return func() { + r.Methods("HEAD,GET,POST,PUT,PATCH,DELETE", "*", func(ctx *context.Context) { + path := ctx.Params("*") + isHead := ctx.Req.Method == "HEAD" + isGetHead := ctx.Req.Method == "HEAD" || ctx.Req.Method == "GET" + isPut := ctx.Req.Method == "PUT" + isDelete := ctx.Req.Method == "DELETE" + + if path == "/repository.key" && isGetHead { + rpm.GetRepositoryKey(ctx) + return + } + + // get repo + m := groupRepoInfo.FindStringSubmatch(path) + if len(m) == 2 && isGetHead { + ctx.SetParams("group", strings.Trim(m[1], "/")) + rpm.GetRepositoryConfig(ctx) + return + } + // get meta + m = groupMetadata.FindStringSubmatch(path) + if len(m) == 3 && isGetHead { + ctx.SetParams("group", strings.Trim(m[1], "/")) + ctx.SetParams("filename", m[2]) + if isHead { + rpm.CheckRepositoryFileExistence(ctx) + } else { + rpm.GetRepositoryFile(ctx) + } + return + } + // upload + m = groupUpload.FindStringSubmatch(path) + if len(m) == 2 && isPut { + reqPackageAccess(perm.AccessModeWrite)(ctx) + if ctx.Written() { + return + } + ctx.SetParams("group", strings.Trim(m[1], "/")) + rpm.UploadPackageFile(ctx) + return + } + // rpm down/delete + m = groupRpm.FindStringSubmatch(path) + if len(m) == 6 { + ctx.SetParams("group", strings.Trim(m[1], "/")) + ctx.SetParams("name", m[2]) + ctx.SetParams("version", m[3]) + ctx.SetParams("architecture", m[4]) + if isGetHead { + rpm.DownloadPackageFile(ctx) + return + } else if isDelete { + reqPackageAccess(perm.AccessModeWrite)(ctx) + if ctx.Written() { + return + } + rpm.DeletePackageFile(ctx) + } + } + // default + ctx.Status(http.StatusNotFound) + }) + } +} + // ContainerRoutes provides endpoints that implement the OCI API to serve containers // These have to be mounted on `/v2/...` to comply with the OCI spec: // https://github.com/opencontainers/distribution-spec/blob/main/spec.md diff --git a/routers/api/packages/rpm/rpm.go b/routers/api/packages/rpm/rpm.go index 2e161940b8..75d19e2b43 100644 --- a/routers/api/packages/rpm/rpm.go +++ b/routers/api/packages/rpm/rpm.go @@ -33,11 +33,14 @@ func apiError(ctx *context.Context, status int, obj any) { // https://dnf.readthedocs.io/en/latest/conf_ref.html func GetRepositoryConfig(ctx *context.Context) { + group := ctx.Params("group") + if group != "" { + group = fmt.Sprintf("/%s", group) + } url := fmt.Sprintf("%sapi/packages/%s/rpm", setting.AppURL, ctx.Package.Owner.Name) - - ctx.PlainText(http.StatusOK, `[gitea-`+ctx.Package.Owner.LowerName+`] -name=`+ctx.Package.Owner.Name+` - `+setting.AppName+` -baseurl=`+url+` + ctx.PlainText(http.StatusOK, `[gitea-`+ctx.Package.Owner.LowerName+strings.ReplaceAll(group, "/", "-")+`] +name=`+ctx.Package.Owner.Name+` - `+setting.AppName+strings.ReplaceAll(group, "/", " - ")+` +baseurl=`+url+group+`/ enabled=1 gpgcheck=1 gpgkey=`+url+`/repository.key`) @@ -64,7 +67,7 @@ func CheckRepositoryFileExistence(ctx *context.Context) { return } - pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, ctx.Params("filename"), packages_model.EmptyFileKey) + pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, ctx.Params("filename"), ctx.Params("group")) if err != nil { if errors.Is(err, util.ErrNotExist) { ctx.Status(http.StatusNotFound) @@ -93,7 +96,8 @@ func GetRepositoryFile(ctx *context.Context) { ctx, pv, &packages_service.PackageFileInfo{ - Filename: ctx.Params("filename"), + Filename: ctx.Params("filename"), + CompositeKey: ctx.Params("group"), }, ) if err != nil { @@ -145,7 +149,7 @@ func UploadPackageFile(ctx *context.Context) { apiError(ctx, http.StatusInternalServerError, err) return } - + group := ctx.Params("group") _, _, err = packages_service.CreatePackageOrAddFileToExisting( ctx, &packages_service.PackageCreationInfo{ @@ -153,14 +157,15 @@ func UploadPackageFile(ctx *context.Context) { Owner: ctx.Package.Owner, PackageType: packages_model.TypeRpm, Name: pck.Name, - Version: pck.Version, + Version: strings.Trim(fmt.Sprintf("%s/%s", group, pck.Version), "/"), }, Creator: ctx.Doer, Metadata: pck.VersionMetadata, }, &packages_service.PackageFileCreationInfo{ PackageFileInfo: packages_service.PackageFileInfo{ - Filename: fmt.Sprintf("%s-%s.%s.rpm", pck.Name, pck.Version, pck.FileMetadata.Architecture), + Filename: fmt.Sprintf("%s-%s.%s.rpm", pck.Name, pck.Version, pck.FileMetadata.Architecture), + CompositeKey: group, }, Creator: ctx.Doer, Data: buf, @@ -182,7 +187,7 @@ func UploadPackageFile(ctx *context.Context) { return } - if err := rpm_service.BuildRepositoryFiles(ctx, ctx.Package.Owner.ID); err != nil { + if err := rpm_service.BuildRepositoryFiles(ctx, ctx.Package.Owner.ID, group); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } @@ -191,19 +196,20 @@ func UploadPackageFile(ctx *context.Context) { } func DownloadPackageFile(ctx *context.Context) { + group := ctx.Params("group") name := ctx.Params("name") version := ctx.Params("version") - s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion( ctx, &packages_service.PackageInfo{ Owner: ctx.Package.Owner, PackageType: packages_model.TypeRpm, Name: name, - Version: version, + Version: strings.Trim(fmt.Sprintf("%s/%s", group, version), "/"), }, &packages_service.PackageFileInfo{ - Filename: fmt.Sprintf("%s-%s.%s.rpm", name, version, ctx.Params("architecture")), + Filename: fmt.Sprintf("%s-%s.%s.rpm", name, version, ctx.Params("architecture")), + CompositeKey: group, }, ) if err != nil { @@ -219,14 +225,19 @@ func DownloadPackageFile(ctx *context.Context) { } func DeletePackageFile(webctx *context.Context) { + group := webctx.Params("group") name := webctx.Params("name") version := webctx.Params("version") architecture := webctx.Params("architecture") - var pd *packages_model.PackageDescriptor err := db.WithTx(webctx, func(ctx stdctx.Context) error { - pv, err := packages_model.GetVersionByNameAndVersion(ctx, webctx.Package.Owner.ID, packages_model.TypeRpm, name, version) + pv, err := packages_model.GetVersionByNameAndVersion(ctx, + webctx.Package.Owner.ID, + packages_model.TypeRpm, + name, + strings.Trim(fmt.Sprintf("%s/%s", group, version), "/"), + ) if err != nil { return err } @@ -235,7 +246,7 @@ func DeletePackageFile(webctx *context.Context) { ctx, pv.ID, fmt.Sprintf("%s-%s.%s.rpm", name, version, architecture), - packages_model.EmptyFileKey, + group, ) if err != nil { return err @@ -275,7 +286,7 @@ func DeletePackageFile(webctx *context.Context) { notify_service.PackageDelete(webctx, webctx.Doer, pd) } - if err := rpm_service.BuildRepositoryFiles(webctx, webctx.Package.Owner.ID); err != nil { + if err := rpm_service.BuildRepositoryFiles(webctx, webctx.Package.Owner.ID, group); err != nil { apiError(webctx, http.StatusInternalServerError, err) return } |