Skip to content

Commit 6ba9ff7

Browse files
authored
Add Conda package registry (#22262)
This PR adds a [Conda](https://conda.io/) package registry.
1 parent 5882e17 commit 6ba9ff7

File tree

24 files changed

+1244
-3
lines changed

24 files changed

+1244
-3
lines changed

custom/conf/app.example.ini

+2
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,8 @@ ROUTER = console
24582458
;LIMIT_SIZE_COMPOSER = -1
24592459
;; Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
24602460
;LIMIT_SIZE_CONAN = -1
2461+
;; Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
2462+
;LIMIT_SIZE_CONDA = -1
24612463
;; Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
24622464
;LIMIT_SIZE_CONTAINER = -1
24632465
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
12141214
- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
12151215
- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
12161216
- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
1217+
- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
12171218
- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
12181219
- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
12191220
- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
date: "2022-12-28T00:00:00+00:00"
3+
title: "Conda Packages Repository"
4+
slug: "packages/conda"
5+
draft: false
6+
toc: false
7+
menu:
8+
sidebar:
9+
parent: "packages"
10+
name: "Conda"
11+
weight: 25
12+
identifier: "conda"
13+
---
14+
15+
# Conda Packages Repository
16+
17+
Publish [Conda](https://docs.conda.io/en/latest/) packages for your user or organization.
18+
19+
**Table of Contents**
20+
21+
{{< toc >}}
22+
23+
## Requirements
24+
25+
To work with the Conda package registry, you need to use [conda](https://docs.conda.io/projects/conda/en/stable/user-guide/install/index.html).
26+
27+
## Configuring the package registry
28+
29+
To register the package registry and provide credentials, edit your `.condarc` file:
30+
31+
```yaml
32+
channel_alias: https://gitea.example.com/api/packages/{owner}/conda
33+
channels:
34+
- https://gitea.example.com/api/packages/{owner}/conda
35+
default_channels:
36+
- https://gitea.example.com/api/packages/{owner}/conda
37+
```
38+
39+
| Placeholder | Description |
40+
| ------------ | ----------- |
41+
| `owner` | The owner of the package. |
42+
43+
See the [official documentation](https://conda.io/projects/conda/en/latest/user-guide/configuration/use-condarc.html) for explanations of the individual settings.
44+
45+
If you need to provide credentials, you may embed them as part of the channel url (`https://user:password@gitea.example.com/...`).
46+
47+
## Publish a package
48+
49+
To publish a package, perform a HTTP PUT operation with the package content in the request body.
50+
51+
```
52+
PUT https://gitea.example.com/api/packages/{owner}/conda/{channel}/{filename}
53+
```
54+
55+
| Placeholder | Description |
56+
| ------------ | ----------- |
57+
| `owner` | The owner of the package. |
58+
| `channel` | The [channel](https://conda.io/projects/conda/en/latest/user-guide/concepts/channels.html) of the package. (optional) |
59+
| `filename` | The name of the file. |
60+
61+
Example request using HTTP Basic authentication:
62+
63+
```shell
64+
curl --user your_username:your_password_or_token \
65+
--upload-file path/to/package-1.0.conda \
66+
https://gitea.example.com/api/packages/testuser/conda/package-1.0.conda
67+
```
68+
69+
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
70+
71+
## Install a package
72+
73+
To install a package from the package registry, execute one of the following commands:
74+
75+
```shell
76+
conda install {package_name}
77+
conda install {package_name}={package_version}
78+
conda install -c {channel} {package_name}
79+
```
80+
81+
| Parameter | Description |
82+
| ----------------- | ----------- |
83+
| `package_name` | The package name. |
84+
| `package_version` | The package version. |
85+
| `channel` | The channel of the package. (optional) |

docs/content/doc/packages/overview.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The following package managers are currently supported:
2828
| ---- | -------- | -------------- |
2929
| [Composer]({{< relref "doc/packages/composer.en-us.md" >}}) | PHP | `composer` |
3030
| [Conan]({{< relref "doc/packages/conan.en-us.md" >}}) | C++ | `conan` |
31+
| [Conda]({{< relref "doc/packages/conda.en-us.md" >}}) | - | `conda` |
3132
| [Container]({{< relref "doc/packages/container.en-us.md" >}}) | - | any OCI compliant client |
3233
| [Generic]({{< relref "doc/packages/generic.en-us.md" >}}) | - | any HTTP client |
3334
| [Helm]({{< relref "doc/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` |

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ require (
2626
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
2727
github.com/djherbis/buffer v1.2.0
2828
github.com/djherbis/nio/v3 v3.0.1
29+
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5
2930
github.com/dustin/go-humanize v1.0.0
3031
github.com/editorconfig/editorconfig-core-go/v2 v2.5.1
3132
github.com/emersion/go-imap v1.2.1
@@ -161,7 +162,6 @@ require (
161162
github.com/davecgh/go-spew v1.1.1 // indirect
162163
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
163164
github.com/dlclark/regexp2 v1.7.0 // indirect
164-
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
165165
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
166166
github.com/fatih/color v1.13.0 // indirect
167167
github.com/felixge/httpsnoop v1.0.3 // indirect

models/packages/conda/search.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package conda
5+
6+
import (
7+
"context"
8+
"strings"
9+
10+
"code.gitea.io/gitea/models/db"
11+
"code.gitea.io/gitea/models/packages"
12+
conda_module "code.gitea.io/gitea/modules/packages/conda"
13+
14+
"xorm.io/builder"
15+
)
16+
17+
type FileSearchOptions struct {
18+
OwnerID int64
19+
Channel string
20+
Subdir string
21+
Filename string
22+
}
23+
24+
// SearchFiles gets all files matching the search options
25+
func SearchFiles(ctx context.Context, opts *FileSearchOptions) ([]*packages.PackageFile, error) {
26+
var cond builder.Cond = builder.Eq{
27+
"package.type": packages.TypeConda,
28+
"package.owner_id": opts.OwnerID,
29+
"package_version.is_internal": false,
30+
}
31+
32+
if opts.Filename != "" {
33+
cond = cond.And(builder.Eq{
34+
"package_file.lower_name": strings.ToLower(opts.Filename),
35+
})
36+
}
37+
38+
var versionPropsCond builder.Cond = builder.Eq{
39+
"package_property.ref_type": packages.PropertyTypePackage,
40+
"package_property.name": conda_module.PropertyChannel,
41+
"package_property.value": opts.Channel,
42+
}
43+
44+
cond = cond.And(builder.In("package.id", builder.Select("package_property.ref_id").Where(versionPropsCond).From("package_property")))
45+
46+
var filePropsCond builder.Cond = builder.Eq{
47+
"package_property.ref_type": packages.PropertyTypeFile,
48+
"package_property.name": conda_module.PropertySubdir,
49+
"package_property.value": opts.Subdir,
50+
}
51+
52+
cond = cond.And(builder.In("package_file.id", builder.Select("package_property.ref_id").Where(filePropsCond).From("package_property")))
53+
54+
sess := db.GetEngine(ctx).
55+
Select("package_file.*").
56+
Table("package_file").
57+
Join("INNER", "package_version", "package_version.id = package_file.version_id").
58+
Join("INNER", "package", "package.id = package_version.package_id").
59+
Where(cond)
60+
61+
pfs := make([]*packages.PackageFile, 0, 10)
62+
return pfs, sess.Find(&pfs)
63+
}

models/packages/descriptor.go

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"code.gitea.io/gitea/modules/json"
1414
"code.gitea.io/gitea/modules/packages/composer"
1515
"code.gitea.io/gitea/modules/packages/conan"
16+
"code.gitea.io/gitea/modules/packages/conda"
1617
"code.gitea.io/gitea/modules/packages/container"
1718
"code.gitea.io/gitea/modules/packages/helm"
1819
"code.gitea.io/gitea/modules/packages/maven"
@@ -132,6 +133,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
132133
metadata = &composer.Metadata{}
133134
case TypeConan:
134135
metadata = &conan.Metadata{}
136+
case TypeConda:
137+
metadata = &conda.VersionMetadata{}
135138
case TypeContainer:
136139
metadata = &container.Metadata{}
137140
case TypeGeneric:

models/packages/package.go

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Type string
3232
const (
3333
TypeComposer Type = "composer"
3434
TypeConan Type = "conan"
35+
TypeConda Type = "conda"
3536
TypeContainer Type = "container"
3637
TypeGeneric Type = "generic"
3738
TypeHelm Type = "helm"
@@ -47,6 +48,7 @@ const (
4748
var TypeList = []Type{
4849
TypeComposer,
4950
TypeConan,
51+
TypeConda,
5052
TypeContainer,
5153
TypeGeneric,
5254
TypeHelm,
@@ -66,6 +68,8 @@ func (pt Type) Name() string {
6668
return "Composer"
6769
case TypeConan:
6870
return "Conan"
71+
case TypeConda:
72+
return "Conda"
6973
case TypeContainer:
7074
return "Container"
7175
case TypeGeneric:
@@ -97,6 +101,8 @@ func (pt Type) SVGName() string {
97101
return "gitea-composer"
98102
case TypeConan:
99103
return "gitea-conan"
104+
case TypeConda:
105+
return "gitea-conda"
100106
case TypeContainer:
101107
return "octicon-container"
102108
case TypeGeneric:

0 commit comments

Comments
 (0)