Skip to content
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

Add Conda package registry #22262

Merged
merged 12 commits into from Feb 1, 2023
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Expand Up @@ -2395,6 +2395,8 @@ ROUTER = console
;LIMIT_SIZE_COMPOSER = -1
;; Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_CONAN = -1
;; Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_CONDA = -1
;; Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_CONTAINER = -1
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
Expand Down
1 change: 1 addition & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Expand Up @@ -1190,6 +1190,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
Expand Down
85 changes: 85 additions & 0 deletions docs/content/doc/packages/conda.en-us.md
@@ -0,0 +1,85 @@
---
date: "2022-12-28T00:00:00+00:00"
title: "Conda Packages Repository"
slug: "packages/conda"
draft: false
toc: false
menu:
sidebar:
parent: "packages"
name: "Conda"
weight: 25
identifier: "conda"
---

# Conda Packages Repository

Publish [Conda](https://docs.conda.io/en/latest/) packages for your user or organization.

**Table of Contents**

{{< toc >}}

## Requirements

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).

## Configuring the package registry

To register the package registry and provide credentials, edit your `.condarc` file:

```yaml
channel_alias: https://gitea.example.com/api/packages/{owner}/conda
channels:
- https://gitea.example.com/api/packages/{owner}/conda
default_channels:
- https://gitea.example.com/api/packages/{owner}/conda
```

| Placeholder | Description |
| ------------ | ----------- |
| `owner` | The owner of the package. |

See the [official documentation](https://conda.io/projects/conda/en/latest/user-guide/configuration/use-condarc.html) for explanations of the individual settings.

If you need to provide credentials, you may embed them as part of the channel url (`https://user:password@gitea.example.com/...`).

## Publish a package

To publish a package, perform a HTTP PUT operation with the package content in the request body.

```
PUT https://gitea.example.com/api/packages/{owner}/conda/{channel}/{filename}
```

| Placeholder | Description |
| ------------ | ----------- |
| `owner` | The owner of the package. |
| `channel` | The [channel](https://conda.io/projects/conda/en/latest/user-guide/concepts/channels.html) of the package. (optional) |
| `filename` | The name of the file. |

Example request using HTTP Basic authentication:

```shell
curl --user your_username:your_password_or_token \
--upload-file path/to/package-1.0.conda \
https://gitea.example.com/api/packages/testuser/conda/package-1.0.conda
```

You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.

## Install a package

To install a package from the package registry, execute one of the following commands:

```shell
conda install {package_name}
conda install {package_name}={package_version}
conda install -c {channel} {package_name}
```

| Parameter | Description |
| ----------------- | ----------- |
| `package_name` | The package name. |
| `package_version` | The package version. |
| `channel` | The channel of the package. (optional) |
1 change: 1 addition & 0 deletions docs/content/doc/packages/overview.en-us.md
Expand Up @@ -28,6 +28,7 @@ The following package managers are currently supported:
| ---- | -------- | -------------- |
| [Composer]({{< relref "doc/packages/composer.en-us.md" >}}) | PHP | `composer` |
| [Conan]({{< relref "doc/packages/conan.en-us.md" >}}) | C++ | `conan` |
| [Conda]({{< relref "doc/packages/conda.en-us.md" >}}) | - | `conda` |
| [Container]({{< relref "doc/packages/container.en-us.md" >}}) | - | any OCI compliant client |
| [Generic]({{< relref "doc/packages/generic.en-us.md" >}}) | - | any HTTP client |
| [Helm]({{< relref "doc/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` |
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -23,6 +23,7 @@ require (
github.com/denisenkom/go-mssqldb v0.12.3
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5
github.com/dustin/go-humanize v1.0.0
github.com/editorconfig/editorconfig-core-go/v2 v2.5.1
github.com/emirpasic/gods v1.18.1
Expand Down Expand Up @@ -154,7 +155,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea // indirect
Expand Down
63 changes: 63 additions & 0 deletions models/packages/conda/search.go
@@ -0,0 +1,63 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package conda

import (
"context"
"strings"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
conda_module "code.gitea.io/gitea/modules/packages/conda"

"xorm.io/builder"
)

type FileSearchOptions struct {
OwnerID int64
Channel string
Subdir string
Filename string
}

// SearchFiles gets all files matching the search options
func SearchFiles(ctx context.Context, opts *FileSearchOptions) ([]*packages.PackageFile, error) {
var cond builder.Cond = builder.Eq{
"package.type": packages.TypeConda,
"package.owner_id": opts.OwnerID,
"package_version.is_internal": false,
}

if opts.Filename != "" {
cond = cond.And(builder.Eq{
"package_file.lower_name": strings.ToLower(opts.Filename),
})
}

var versionPropsCond builder.Cond = builder.Eq{
"package_property.ref_type": packages.PropertyTypePackage,
"package_property.name": conda_module.PropertyChannel,
"package_property.value": opts.Channel,
}

cond = cond.And(builder.In("package.id", builder.Select("package_property.ref_id").Where(versionPropsCond).From("package_property")))

var filePropsCond builder.Cond = builder.Eq{
"package_property.ref_type": packages.PropertyTypeFile,
"package_property.name": conda_module.PropertySubdir,
"package_property.value": opts.Subdir,
}

cond = cond.And(builder.In("package_file.id", builder.Select("package_property.ref_id").Where(filePropsCond).From("package_property")))

sess := db.GetEngine(ctx).
Select("package_file.*").
Table("package_file").
Join("INNER", "package_version", "package_version.id = package_file.version_id").
Join("INNER", "package", "package.id = package_version.package_id").
Where(cond)

pfs := make([]*packages.PackageFile, 0, 10)
return pfs, sess.Find(&pfs)
}
3 changes: 3 additions & 0 deletions models/packages/descriptor.go
Expand Up @@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/packages/composer"
"code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/packages/conda"
"code.gitea.io/gitea/modules/packages/container"
"code.gitea.io/gitea/modules/packages/helm"
"code.gitea.io/gitea/modules/packages/maven"
Expand Down Expand Up @@ -132,6 +133,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
metadata = &composer.Metadata{}
case TypeConan:
metadata = &conan.Metadata{}
case TypeConda:
metadata = &conda.VersionMetadata{}
case TypeContainer:
metadata = &container.Metadata{}
case TypeGeneric:
Expand Down
6 changes: 6 additions & 0 deletions models/packages/package.go
Expand Up @@ -32,6 +32,7 @@ type Type string
const (
TypeComposer Type = "composer"
TypeConan Type = "conan"
TypeConda Type = "conda"
TypeContainer Type = "container"
TypeGeneric Type = "generic"
TypeHelm Type = "helm"
Expand All @@ -47,6 +48,7 @@ const (
var TypeList = []Type{
TypeComposer,
TypeConan,
TypeConda,
TypeContainer,
TypeGeneric,
TypeHelm,
Expand All @@ -66,6 +68,8 @@ func (pt Type) Name() string {
return "Composer"
case TypeConan:
return "Conan"
case TypeConda:
return "Conda"
case TypeContainer:
return "Container"
case TypeGeneric:
Expand Down Expand Up @@ -97,6 +101,8 @@ func (pt Type) SVGName() string {
return "gitea-composer"
case TypeConan:
return "gitea-conan"
case TypeConda:
return "gitea-conda"
case TypeContainer:
return "octicon-container"
case TypeGeneric:
Expand Down