Skip to content

Support for grouping RPMs using paths #26984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 50 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4ced55f
Remove extraneous code and prepare for commit
ExplodingDragon Sep 9, 2023
f3c4131
Change rpm help description
ExplodingDragon Sep 9, 2023
b7b593d
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 9, 2023
895f419
Fix bugs and optimize queries
ExplodingDragon Sep 10, 2023
c04789e
Merge branch 'feature-support-multi-rpm-dist' of github.com:Exploding…
ExplodingDragon Sep 10, 2023
c718aad
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 10, 2023
4d28c8d
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 10, 2023
2adb75e
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 11, 2023
e1e2575
Fix formatting
ExplodingDragon Sep 11, 2023
f12c8cc
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 12, 2023
51596b6
Fix some problems
ExplodingDragon Sep 12, 2023
9c3cde6
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 12, 2023
6fb18d3
fix tests
ExplodingDragon Sep 13, 2023
0d9cba5
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 13, 2023
17693fb
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 13, 2023
22211ee
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 13, 2023
ad83ae0
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 13, 2023
ac6a6e0
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 14, 2023
109d077
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 14, 2023
6682654
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Sep 14, 2023
a593edf
Merge branch 'main' of into feature-rpm-dist
ExplodingDragon Oct 28, 2023
b860b79
Merge branch 'main' of into feature-rpm-dist
ExplodingDragon Oct 28, 2023
ca647ee
compress filter
ExplodingDragon Oct 28, 2023
64c3a7e
rpm packages with arbitrary depth paths
ExplodingDragon Oct 28, 2023
561d86b
fix ui
ExplodingDragon Oct 28, 2023
7957d60
fix migrations
ExplodingDragon Oct 28, 2023
2e2cd0f
i10n clean
ExplodingDragon Oct 28, 2023
a8fff90
move varfunc
ExplodingDragon Oct 28, 2023
1887c93
fix docs
ExplodingDragon Oct 28, 2023
a4fc3ed
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Oct 29, 2023
a66f80b
fixed bugs
ExplodingDragon Oct 29, 2023
5519c17
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Oct 30, 2023
83a4b18
add group by version
ExplodingDragon Oct 30, 2023
5f6ebb5
add group by version
ExplodingDragon Oct 30, 2023
d8ede80
fix nogroup upload
ExplodingDragon Oct 30, 2023
2ea6ca3
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Oct 30, 2023
1b4e2ce
style clean
ExplodingDragon Oct 30, 2023
f66f1b9
remove db merge
ExplodingDragon Oct 30, 2023
85c54fe
remove db merge
ExplodingDragon Oct 30, 2023
56350e4
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Oct 30, 2023
884adb4
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Nov 1, 2023
695b2d2
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Nov 9, 2023
3a27fe3
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Nov 14, 2023
0369dc4
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Nov 23, 2023
3cf416d
merge #28309
ExplodingDragon Dec 5, 2023
d69539c
merge #28309
ExplodingDragon Dec 5, 2023
7926b48
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Jan 8, 2024
5bb1193
fix rpm unit test
ExplodingDragon Jan 8, 2024
4ce3226
Merge branch 'main' into feature-support-multi-rpm-dist
ExplodingDragon Jan 10, 2024
3611059
Merge branch 'main' into feature-support-multi-rpm-dist
GiteaBot Jan 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions docs/content/usage/packages/rpm.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/{group}.repo
```

| Placeholder | Description |
| ----------- | ----------- |
| `owner` | The owner of the package. |
| Placeholder | Description |
| ----------- |----------------------------------------------------|
| `owner` | The owner of the package. |
| `group` | Everything, e.g. `el7`, `rocky/el9` , `test/fc38`.|

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/{group}.repo
```

You have to add the credentials to the urls in the `rpm.repo` file in `/etc/yum.repos.d` too.
Expand All @@ -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/{group}/upload
```

| Parameter | Description |
| --------- | ----------- |
| `owner` | The owner of the package. |
| `group` | Everything, e.g. `el7`, `rocky/el9` , `test/fc38`.|

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/centos/el7/upload
```

If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
Expand All @@ -78,21 +80,22 @@ 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/{group}/package/{package_name}/{package_version}/{architecture}
```

| Parameter | Description |
| ----------------- | ----------- |
| `owner` | The owner of the package. |
| `package_name` | The package name. |
| `package_version` | The package version. |
| `architecture` | The package architecture. |
| Parameter | Description |
|-------------------|----------------------------|
| `owner` | The owner of the package. |
| `group` | The package group . |
| `package_name` | The package name. |
| `package_version` | The package version. |
| `architecture` | The package architecture. |

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/centos/el7/package/test-package/1.0.0/x86_64
```

The server responds with the following HTTP Status codes.
Expand Down
25 changes: 14 additions & 11 deletions docs/content/usage/packages/rpm.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/{group}.repo
```

| 占位符 | 描述 |
| ------- | -------------- |
| `owner` | 软件包的所有者 |
| 占位符 | 描述 |
| ------- |--------------------------------------|
| `owner` | 软件包的所有者 |
| `group` | 任何名称,例如 `centos/7`、`el-7`、`fc38` |

如果注册表是私有的,请在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/{group}.repo
```

您还必须将凭据添加到 `/etc/yum.repos.d` 中的 `rpm.repo` 文件中的URL中。
Expand All @@ -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/{group}/upload
```

| 参数 | 描述 |
| ------- | -------------- |
| `owner` | 软件包的所有者 |
| ------- |--------------|
| `owner` | 软件包的所有者 |
| `group` | 软件包自定义分组名称 |

使用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/centos/el7/version/upload
```

如果您使用 2FA 或 OAuth,请使用[个人访问令牌](development/api-usage.md#通过-api-认证)替代密码。您无法将具有相同名称的文件两次发布到软件包中。您必须先删除现有的软件包版本。
Expand All @@ -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/{group}/package/{package_name}/{package_version}/{architecture}
```

| 参数 | 描述 |
| ----------------- | -------------- |
| `owner` | 软件包的所有者 |
| `group` | 软件包自定义分组 |
| `package_name` | 软件包名称 |
| `package_version` | 软件包版本 |
| `architecture` | 软件包架构 |
Expand All @@ -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/centos/el7/package/test-package/1.0.0/x86_64
```

服务器将以以下HTTP状态码响应:
Expand Down
3 changes: 1 addition & 2 deletions modules/packages/rpm/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import (
)

const (
PropertyMetadata = "rpm.metadata"

PropertyMetadata = "rpm.metadata"
SettingKeyPrivate = "rpm.key.private"
SettingKeyPublic = "rpm.key.public"

Expand Down
5 changes: 5 additions & 0 deletions modules/templates/util_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package templates

import (
"regexp"
"strings"

"code.gitea.io/gitea/modules/base"
Expand All @@ -25,6 +26,10 @@ func (su *StringUtils) Contains(s, substr string) bool {
return strings.Contains(s, substr)
}

func (su *StringUtils) ReplaceAllStringRegex(s, regex, new string) string {
return regexp.MustCompile(regex).ReplaceAllString(s, new)
}

func (su *StringUtils) Split(s, sep string) []string {
return strings.Split(s, sep)
}
Expand Down
90 changes: 77 additions & 13 deletions routers/api/packages/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading