diff --git a/docs/content/usage/packages/rpm.en-us.md b/docs/content/usage/packages/rpm.en-us.md index 5a4a31ee39dfe..f20f77258e2a6 100644 --- a/docs/content/usage/packages/rpm.en-us.md +++ b/docs/content/usage/packages/rpm.en-us.md @@ -27,17 +27,18 @@ The following examples use `dnf`. To register the RPM registry add the url to the list of known apt sources: ```shell -dnf config-manager --add-repo https://gitea.example.com/api/packages/{owner}/rpm.repo +dnf config-manager --add-repo https://gitea.example.com/api/packages/{owner}/rpm/{distribution}.repo ``` | Placeholder | Description | | ----------- | ----------- | | `owner` | The owner of the package. | +| `distribution` | Package group name, e.g. `el7`, `el9` , `test-el9`. | If the registry is private, provide credentials in the url. You can use a password or a [personal access token](development/api-usage.md#authentication): ```shell -dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea.example.com/api/packages/{owner}/rpm.repo +dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea.example.com/api/packages/{owner}/rpm/{distribution}.repo ``` You have to add the credentials to the urls in the `rpm.repo` file in `/etc/yum.repos.d` too. @@ -47,19 +48,20 @@ You have to add the credentials to the urls in the `rpm.repo` file in `/etc/yum. To publish a RPM package (`*.rpm`), perform a HTTP PUT operation with the package content in the request body. ``` -PUT https://gitea.example.com/api/packages/{owner}/rpm/upload +PUT https://gitea.example.com/api/packages/{owner}/rpm/{distribution}/upload ``` | Parameter | Description | | --------- | ----------- | | `owner` | The owner of the package. | +| `distribution` | Package group name, e.g. `el7`, `el9` , `test-el9`. | Example request using HTTP Basic authentication: ```shell curl --user your_username:your_password_or_token \ --upload-file path/to/file.rpm \ - https://gitea.example.com/api/packages/testuser/rpm/upload + https://gitea.example.com/api/packages/testuser/rpm/default/upload ``` If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password. @@ -78,12 +80,13 @@ The server responds with the following HTTP Status codes. To delete an RPM package perform a HTTP DELETE operation. This will delete the package version too if there is no file left. ``` -DELETE https://gitea.example.com/api/packages/{owner}/rpm/{package_name}/{package_version}/{architecture} +DELETE https://gitea.example.com/api/packages/{owner}/rpm/{distribution}/package/{package_name}/{package_version}/{architecture} ``` | Parameter | Description | | ----------------- | ----------- | | `owner` | The owner of the package. | +| `distribution` | The package distribution. | | `package_name` | The package name. | | `package_version` | The package version. | | `architecture` | The package architecture. | @@ -92,7 +95,7 @@ Example request using HTTP Basic authentication: ```shell curl --user your_username:your_token_or_password -X DELETE \ - https://gitea.example.com/api/packages/testuser/rpm/test-package/1.0.0/x86_64 + https://gitea.example.com/api/packages/testuser/rpm/default/test-package/1.0.0/x86_64 ``` The server responds with the following HTTP Status codes. diff --git a/docs/content/usage/packages/rpm.zh-cn.md b/docs/content/usage/packages/rpm.zh-cn.md index 3cc7dca8ff2cf..d6d62487559a4 100644 --- a/docs/content/usage/packages/rpm.zh-cn.md +++ b/docs/content/usage/packages/rpm.zh-cn.md @@ -27,17 +27,18 @@ menu: 要注册RPM注册表,请将 URL 添加到已知 `apt` 源列表中: ```shell -dnf config-manager --add-repo https://gitea.example.com/api/packages/{owner}/rpm.repo +dnf config-manager --add-repo https://gitea.example.com/api/packages/{owner}/rpm/{distribution}.repo ``` | 占位符 | 描述 | | ------- | -------------- | | `owner` | 软件包的所有者 | +| `distribution` | 一个任意的名称,例如:el7、el9 | 如果注册表是私有的,请在URL中提供凭据。您可以使用密码或[个人访问令牌](development/api-usage.md#通过-api-认证): ```shell -dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea.example.com/api/packages/{owner}/rpm.repo +dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea.example.com/api/packages/{owner}/rpm/{distribution}.repo ``` 您还必须将凭据添加到 `/etc/yum.repos.d` 中的 `rpm.repo` 文件中的URL中。 @@ -47,19 +48,20 @@ dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea. 要发布RPM软件包(`*.rpm`),请执行带有软件包内容的 HTTP `PUT` 操作。 ``` -PUT https://gitea.example.com/api/packages/{owner}/rpm/upload +PUT https://gitea.example.com/api/packages/{owner}/rpm/{distribution}/upload ``` | 参数 | 描述 | | ------- | -------------- | | `owner` | 软件包的所有者 | +| `distribution` | 软件包组名称,例如:`el7`、`el9`、`test-el9` | 使用HTTP基本身份验证的示例请求: ```shell curl --user your_username:your_password_or_token \ --upload-file path/to/file.rpm \ - https://gitea.example.com/api/packages/testuser/rpm/upload + https://gitea.example.com/api/packages/testuser/rpm/default/upload ``` 如果您使用 2FA 或 OAuth,请使用[个人访问令牌](development/api-usage.md#通过-api-认证)替代密码。您无法将具有相同名称的文件两次发布到软件包中。您必须先删除现有的软件包版本。 @@ -77,12 +79,13 @@ curl --user your_username:your_password_or_token \ 要删除 RPM 软件包,请执行 HTTP `DELETE` 操作。如果没有文件剩余,这也将删除软件包版本。 ``` -DELETE https://gitea.example.com/api/packages/{owner}/rpm/{package_name}/{package_version}/{architecture} +DELETE https://gitea.example.com/api/packages/{owner}/rpm/{distribution}/package/{package_name}/{package_version}/{architecture} ``` | 参数 | 描述 | | ----------------- | -------------- | | `owner` | 软件包的所有者 | +| `distribution` | 软件包组名称 | | `package_name` | 软件包名称 | | `package_version` | 软件包版本 | | `architecture` | 软件包架构 | @@ -91,7 +94,7 @@ DELETE https://gitea.example.com/api/packages/{owner}/rpm/{package_name}/{packag ```shell curl --user your_username:your_token_or_password -X DELETE \ - https://gitea.example.com/api/packages/testuser/rpm/test-package/1.0.0/x86_64 + https://gitea.example.com/api/packages/testuser/rpm/default/package/test-package/1.0.0/x86_64 ``` 服务器将以以下HTTP状态码响应: diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 9f4acda23699a..530df3c962fdc 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -528,6 +528,8 @@ var migrations = []Migration{ NewMigration("Add Version to ActionRun table", v1_21.AddVersionToActionRunTable), // v273 -> v274 NewMigration("Add Action Schedule Table", v1_21.AddActionScheduleTable), + // v274 -> v275 + NewMigration("Migrate old rpm package index", v1_21.RebuildRpmPackage), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_21/v274.go b/models/migrations/v1_21/v274.go new file mode 100644 index 0000000000000..ee944b54b4a55 --- /dev/null +++ b/models/migrations/v1_21/v274.go @@ -0,0 +1,81 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_21 //nolint + +import ( + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/packages/rpm" + + "xorm.io/xorm" +) + +func RebuildRpmPackage(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + defaultDistribution := rpm.RepositoryDefaultDistribution + // select all old rpm package + var oldRpmIds []int64 + ss := sess.Cols("id"). + Table("package_file"). + Where("composite_key = ?", ""). + And("lower_name like ?", "%.rpm") + err := ss.Find(&oldRpmIds) + if err != nil { + return err + } + // add metadata + // NOTE: package_property[name='rpm.metdata'] is very large, + // and to avoid querying all of them resulting in large memory, + // a single RPM package is now used for updating. + for _, id := range oldRpmIds { + + metadata := make([]string, 0, 3) + _, err := sess.Cols("ref_type", "ref_id", "value"). + Table("package_property"). + Where("name = 'rpm.metdata'"). + And("ref_id = ?", id). + Get(&metadata) + if err != nil { + return err + } + // get rpm info + var rpmMetadata rpm.FileMetadata + err = json.Unmarshal([]byte(metadata[2]), &rpmMetadata) + if err != nil { + return err + } + _, err = sess.Exec( + "INSERT INTO package_property(ref_type, ref_id, name, value) values (?,?,?,?),(?,?,?,?)", + metadata[0], metadata[1], "rpm.distribution", defaultDistribution, + metadata[0], metadata[1], "rpm.architecture", rpmMetadata.Architecture, + ) + if err != nil { + return err + } + // set default distribution + _, err = sess.Table("package_file"). + Where("id = ?", id). + Update(map[string]any{ + "composite_key": defaultDistribution, + }) + if err != nil { + return err + } + } + // set old rpm index file to default distribution + _, err = sess.Table("package_file"). + Where( + "composite_key = '' AND " + + "lower_name IN" + + "(" + + "'primary.xml.gz','other.xml.gz','filelists.xml.gz','other.xml.gz','repomd.xml','repomd.xml.asc'" + + ")"). + Update(map[string]any{ + "composite_key": defaultDistribution, + }) + if err != nil { + return err + } + return nil +} diff --git a/modules/packages/rpm/metadata.go b/modules/packages/rpm/metadata.go index f019a8dde1aaa..c7580a1294684 100644 --- a/modules/packages/rpm/metadata.go +++ b/modules/packages/rpm/metadata.go @@ -15,13 +15,17 @@ import ( ) const ( - PropertyMetadata = "rpm.metadata" + PropertyMetadata = "rpm.metadata" + PropertyDistribution = "rpm.distribution" + PropertyArchitecture = "rpm.architecture" SettingKeyPrivate = "rpm.key.private" SettingKeyPublic = "rpm.key.public" RepositoryPackage = "_rpm" RepositoryVersion = "_repository" + + RepositoryDefaultDistribution = "default" ) const ( diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 66f67d4896a54..e215effab5f9a 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3381,6 +3381,11 @@ rpm.registry = Setup this registry from the command line: rpm.distros.redhat = on RedHat based distributions rpm.distros.suse = on SUSE based distributions rpm.install = To install the package, run the following command: +rpm.package.info = Package Info +rpm.package.distributions = Distributions +rpm.package.architectures = Architectures +rpm.package.description = Description +rpm.package.summary = Summary rubygems.install = To install the package using gem, run the following command: rubygems.install2 = or add it to the Gemfile: rubygems.dependencies.runtime = Runtime Dependencies diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 2ba35e21380b2..a30688d68cf67 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -513,14 +513,25 @@ func CommonRoutes() *web.Route { r.Get("/simple/{id}", pypi.PackageMetadata) }, reqPackageAccess(perm.AccessModeRead)) r.Group("/rpm", func() { - r.Get(".repo", rpm.GetRepositoryConfig) + r.Get(".repo", func(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + strings.Replace(ctx.Base.Req.URL.Path, "/rpm.repo", "/rpm/default.repo", 1)) + }) + r.Get("/repodata/{filename}", func(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + strings.Replace(ctx.Base.Req.URL.Path, "/rpm/repodata/", "/rpm/default/repodata/", 1)) + }) + r.Get("/package/{name}/{version}/{architecture}", func(ctx *context.Context) { + ctx.Redirect(setting.AppSubURL + strings.Replace(ctx.Base.Req.URL.Path, "/rpm/package/", "/rpm/default/package/", 1)) + }) 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("/{distribution}", func() { + r.Get(".repo", rpm.GetRepositoryConfig) + 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.Get("/repodata/{filename}", rpm.GetRepositoryFile) }) - r.Get("/repodata/{filename}", rpm.GetRepositoryFile) }, reqPackageAccess(perm.AccessModeRead)) r.Group("/rubygems", func() { r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) diff --git a/routers/api/packages/rpm/rpm.go b/routers/api/packages/rpm/rpm.go index 930b20208ae17..b5286741816c8 100644 --- a/routers/api/packages/rpm/rpm.go +++ b/routers/api/packages/rpm/rpm.go @@ -33,11 +33,12 @@ func apiError(ctx *context.Context, status int, obj any) { // https://dnf.readthedocs.io/en/latest/conf_ref.html func GetRepositoryConfig(ctx *context.Context) { + distribution := ctx.Params("distribution") 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+`-`+distribution+`] +name=`+ctx.Package.Owner.Name+` - `+setting.AppName+` - `+distribution+` +baseurl=`+url+`/`+distribution+` enabled=1 gpgcheck=1 gpgkey=`+url+`/repository.key`) @@ -69,7 +70,8 @@ func GetRepositoryFile(ctx *context.Context) { ctx, pv, &packages_service.PackageFileInfo{ - Filename: ctx.Params("filename"), + Filename: ctx.Params("filename"), + CompositeKey: ctx.Params("distribution"), }, ) if err != nil { @@ -121,7 +123,7 @@ func UploadPackageFile(ctx *context.Context) { apiError(ctx, http.StatusInternalServerError, err) return } - + distribution := ctx.Params("distribution") _, _, err = packages_service.CreatePackageOrAddFileToExisting( &packages_service.PackageCreationInfo{ PackageInfo: packages_service.PackageInfo{ @@ -135,13 +137,16 @@ func UploadPackageFile(ctx *context.Context) { }, &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: distribution, }, Creator: ctx.Doer, Data: buf, IsLead: true, Properties: map[string]string{ - rpm_module.PropertyMetadata: string(fileMetadataRaw), + rpm_module.PropertyMetadata: string(fileMetadataRaw), + rpm_module.PropertyDistribution: distribution, + rpm_module.PropertyArchitecture: pck.FileMetadata.Architecture, }, }, ) @@ -157,7 +162,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, distribution); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } @@ -168,7 +173,6 @@ func UploadPackageFile(ctx *context.Context) { func DownloadPackageFile(ctx *context.Context) { name := ctx.Params("name") version := ctx.Params("version") - s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion( ctx, &packages_service.PackageInfo{ @@ -178,7 +182,8 @@ func DownloadPackageFile(ctx *context.Context) { Version: 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: ctx.Params("distribution"), }, ) if err != nil { @@ -197,6 +202,7 @@ func DeletePackageFile(webctx *context.Context) { name := webctx.Params("name") version := webctx.Params("version") architecture := webctx.Params("architecture") + distribution := webctx.Params("distribution") var pd *packages_model.PackageDescriptor @@ -210,7 +216,7 @@ func DeletePackageFile(webctx *context.Context) { ctx, pv.ID, fmt.Sprintf("%s-%s.%s.rpm", name, version, architecture), - packages_model.EmptyFileKey, + distribution, ) if err != nil { return err @@ -250,7 +256,7 @@ func DeletePackageFile(webctx *context.Context) { notification.NotifyPackageDelete(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, distribution); err != nil { apiError(webctx, http.StatusInternalServerError, err) return } diff --git a/routers/web/user/package.go b/routers/web/user/package.go index d44638d48bbc0..168e7c63d316b 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/modules/log" alpine_module "code.gitea.io/gitea/modules/packages/alpine" debian_module "code.gitea.io/gitea/modules/packages/debian" + rpm_module "code.gitea.io/gitea/modules/packages/rpm" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" @@ -219,6 +220,21 @@ func ViewPackageVersion(ctx *context.Context) { ctx.Data["Distributions"] = distributions.Values() ctx.Data["Components"] = components.Values() ctx.Data["Architectures"] = architectures.Values() + case packages_model.TypeRpm: + distributions := make(container.Set[string]) + architectures := make(container.Set[string]) + for _, f := range pd.Files { + for _, pp := range f.Properties { + switch pp.Name { + case rpm_module.PropertyDistribution: + distributions.Add(pp.Value) + case rpm_module.PropertyArchitecture: + architectures.Add(pp.Value) + } + } + } + ctx.Data["Distributions"] = distributions.Values() + ctx.Data["Architectures"] = architectures.Values() } var ( diff --git a/services/packages/rpm/repository.go b/services/packages/rpm/repository.go index cfd70ec23e2c7..ff6ea4a041d46 100644 --- a/services/packages/rpm/repository.go +++ b/services/packages/rpm/repository.go @@ -127,16 +127,17 @@ type packageData struct { type packageCache = map[*packages_model.PackageFile]*packageData // BuildSpecificRepositoryFiles builds metadata files for the repository -func BuildRepositoryFiles(ctx context.Context, ownerID int64) error { +func BuildRepositoryFiles(ctx context.Context, ownerID int64, distribution string) error { pv, err := GetOrCreateRepositoryVersion(ownerID) if err != nil { return err } pfs, _, err := packages_model.SearchFiles(ctx, &packages_model.PackageFileSearchOptions{ - OwnerID: ownerID, - PackageType: packages_model.TypeRpm, - Query: "%.rpm", + OwnerID: ownerID, + PackageType: packages_model.TypeRpm, + Query: "%.rpm", + CompositeKey: distribution, }) if err != nil { return err @@ -198,15 +199,15 @@ func BuildRepositoryFiles(ctx context.Context, ownerID int64) error { cache[pf] = pd } - primary, err := buildPrimary(pv, pfs, cache) + primary, err := buildPrimary(pv, pfs, cache, distribution) if err != nil { return err } - filelists, err := buildFilelists(pv, pfs, cache) + filelists, err := buildFilelists(pv, pfs, cache, distribution) if err != nil { return err } - other, err := buildOther(pv, pfs, cache) + other, err := buildOther(pv, pfs, cache, distribution) if err != nil { return err } @@ -219,11 +220,12 @@ func BuildRepositoryFiles(ctx context.Context, ownerID int64) error { filelists, other, }, + distribution, ) } // https://docs.pulpproject.org/en/2.19/plugins/pulp_rpm/tech-reference/rpm.html#repomd-xml -func buildRepomd(pv *packages_model.PackageVersion, ownerID int64, data []*repoData) error { +func buildRepomd(pv *packages_model.PackageVersion, ownerID int64, data []*repoData, distribution string) error { type Repomd struct { XMLName xml.Name `xml:"repomd"` Xmlns string `xml:"xmlns,attr"` @@ -274,7 +276,8 @@ func buildRepomd(pv *packages_model.PackageVersion, ownerID int64, data []*repoD pv, &packages_service.PackageFileCreationInfo{ PackageFileInfo: packages_service.PackageFileInfo{ - Filename: file.Name, + Filename: file.Name, + CompositeKey: distribution, }, Creator: user_model.NewGhostUser(), Data: file.Data, @@ -291,7 +294,7 @@ func buildRepomd(pv *packages_model.PackageVersion, ownerID int64, data []*repoD } // https://docs.pulpproject.org/en/2.19/plugins/pulp_rpm/tech-reference/rpm.html#primary-xml -func buildPrimary(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache) (*repoData, error) { +func buildPrimary(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache, distribution string) (*repoData, error) { type Version struct { Epoch string `xml:"epoch,attr"` Version string `xml:"ver,attr"` @@ -430,11 +433,11 @@ func buildPrimary(pv *packages_model.PackageVersion, pfs []*packages_model.Packa XmlnsRpm: "http://linux.duke.edu/metadata/rpm", PackageCount: len(pfs), Packages: packages, - }) + }, distribution) } // https://docs.pulpproject.org/en/2.19/plugins/pulp_rpm/tech-reference/rpm.html#filelists-xml -func buildFilelists(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache) (*repoData, error) { //nolint:dupl +func buildFilelists(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache, distribution string) (*repoData, error) { //nolint:dupl type Version struct { Epoch string `xml:"epoch,attr"` Version string `xml:"ver,attr"` @@ -477,11 +480,12 @@ func buildFilelists(pv *packages_model.PackageVersion, pfs []*packages_model.Pac Xmlns: "http://linux.duke.edu/metadata/other", PackageCount: len(pfs), Packages: packages, - }) + }, + distribution) } // https://docs.pulpproject.org/en/2.19/plugins/pulp_rpm/tech-reference/rpm.html#other-xml -func buildOther(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache) (*repoData, error) { //nolint:dupl +func buildOther(pv *packages_model.PackageVersion, pfs []*packages_model.PackageFile, c packageCache, distribution string) (*repoData, error) { //nolint:dupl type Version struct { Epoch string `xml:"epoch,attr"` Version string `xml:"ver,attr"` @@ -524,7 +528,7 @@ func buildOther(pv *packages_model.PackageVersion, pfs []*packages_model.Package Xmlns: "http://linux.duke.edu/metadata/other", PackageCount: len(pfs), Packages: packages, - }) + }, distribution) } // writtenCounter counts all written bytes @@ -544,7 +548,7 @@ func (wc *writtenCounter) Written() int64 { return wc.written } -func addDataAsFileToRepo(pv *packages_model.PackageVersion, filetype string, obj any) (*repoData, error) { +func addDataAsFileToRepo(pv *packages_model.PackageVersion, filetype string, obj any, distribution string) (*repoData, error) { content, _ := packages_module.NewHashedBuffer() gzw := gzip.NewWriter(content) wc := &writtenCounter{} @@ -567,7 +571,8 @@ func addDataAsFileToRepo(pv *packages_model.PackageVersion, filetype string, obj pv, &packages_service.PackageFileCreationInfo{ PackageFileInfo: packages_service.PackageFileInfo{ - Filename: filename, + Filename: filename, + CompositeKey: distribution, }, Creator: user_model.NewGhostUser(), Data: content, diff --git a/templates/package/content/rpm.tmpl b/templates/package/content/rpm.tmpl index fc7af639aa30a..233c95ab676ae 100644 --- a/templates/package/content/rpm.tmpl +++ b/templates/package/content/rpm.tmpl @@ -5,10 +5,10 @@
# {{.locale.Tr "packages.rpm.distro.redhat"}}
-dnf config-manager --add-repo 
+dnf config-manager --add-repo 
 
 # {{.locale.Tr "packages.rpm.distro.suse"}}
-zypper addrepo 
+zypper addrepo
@@ -26,9 +26,31 @@ zypper install {{$.PackageDescriptor.Package.Name}}
- {{if or .PackageDescriptor.Metadata.Summary .PackageDescriptor.Metadata.Description}} -

{{.locale.Tr "packages.about"}}

- {{if .PackageDescriptor.Metadata.Summary}}
{{.PackageDescriptor.Metadata.Summary}}
{{end}} - {{if .PackageDescriptor.Metadata.Description}}
{{.PackageDescriptor.Metadata.Description}}
{{end}} - {{end}} +

{{.locale.Tr "packages.rpm.package.info"}}

+
+ + + + + + + + + + + {{if .PackageDescriptor.Metadata.Summary}} + + + + + {{end}} + {{if .PackageDescriptor.Metadata.Description}} + + + + + {{end}} + +
{{.locale.Tr "packages.rpm.package.distributions"}}
{{StringUtils.Join .Distributions ", "}}
{{.locale.Tr "packages.rpm.package.architectures"}}
{{StringUtils.Join .Architectures ", "}}
{{.locale.Tr "packages.rpm.package.summary"}}
{{.PackageDescriptor.Metadata.Summary}}
{{.locale.Tr "packages.rpm.package.description"}}
{{.PackageDescriptor.Metadata.Description}}
+
{{end}} diff --git a/tests/integration/api_packages_rpm_test.go b/tests/integration/api_packages_rpm_test.go index fc4c4d1c4b66c..e6d2d31117290 100644 --- a/tests/integration/api_packages_rpm_test.go +++ b/tests/integration/api_packages_rpm_test.go @@ -76,12 +76,12 @@ Mu0UFYgZ/bYnuvn/vz4wtCz8qMwsHUvP0PX3tbYFUctAPdrY6tiiDtcCddDECahx7SuVNP5dpmb5 t.Run("RepositoryConfig", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - req := NewRequest(t, "GET", rootURL+".repo") + req := NewRequest(t, "GET", rootURL+"/el9.repo") resp := MakeRequest(t, req, http.StatusOK) - expected := fmt.Sprintf(`[gitea-%s] -name=%s - %s -baseurl=%sapi/packages/%s/rpm + expected := fmt.Sprintf(`[gitea-%s-el9] +name=%s - %s - el9 +baseurl=%sapi/packages/%s/rpm/el9 enabled=1 gpgcheck=1 gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppName, setting.AppURL, user.Name, setting.AppURL, user.Name) @@ -100,7 +100,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN }) t.Run("Upload", func(t *testing.T) { - url := rootURL + "/upload" + url := rootURL + "/el9/upload" req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)) MakeRequest(t, req, http.StatusUnauthorized) @@ -138,7 +138,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN t.Run("Download", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) + req := NewRequest(t, "GET", fmt.Sprintf("%s/el9/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) resp := MakeRequest(t, req, http.StatusOK) assert.Equal(t, content, resp.Body.Bytes()) @@ -147,7 +147,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN t.Run("Repository", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - url := rootURL + "/repodata" + url := rootURL + "/el9/repodata" req := NewRequest(t, "GET", url+"/dummy.xml") MakeRequest(t, req, http.StatusNotFound) @@ -395,10 +395,10 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN t.Run("Delete", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - req := NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) + req := NewRequest(t, "DELETE", fmt.Sprintf("%s/el9/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) MakeRequest(t, req, http.StatusUnauthorized) - req = NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) + req = NewRequest(t, "DELETE", fmt.Sprintf("%s/el9/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusNoContent) @@ -406,7 +406,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN assert.NoError(t, err) assert.Empty(t, pvs) - req = NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) + req = NewRequest(t, "DELETE", fmt.Sprintf("%s/el9/package/%s/%s/%s", rootURL, packageName, packageVersion, packageArchitecture)) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusNotFound) })