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 CRAN package registry #22331

Merged
merged 25 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3d722c9
Add CRAN package registry.
KN4CK3R Jan 3, 2023
1a6991a
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jan 3, 2023
c509694
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Jan 25, 2023
fd9b1f0
Merge branch 'main' into feature-cran
KN4CK3R Jan 31, 2023
69e6f1c
Merge branch 'main' into feature-cran
lunny Feb 1, 2023
d6f5dce
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Feb 5, 2023
b3888e3
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Feb 19, 2023
1caa4d4
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 9, 2023
6c075d8
Use relative url.
KN4CK3R Mar 13, 2023
dad233d
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 13, 2023
6dfd20f
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 14, 2023
dd02f85
Add suggestions.
KN4CK3R Mar 15, 2023
6b85c09
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 15, 2023
49aca08
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 28, 2023
3dc959a
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R Mar 28, 2023
04d85f1
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 12, 2023
05f8059
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 14, 2023
15cf315
Crop svg.
KN4CK3R May 14, 2023
c3bdb00
Update docs.
KN4CK3R May 14, 2023
4a1859f
fix path
KN4CK3R May 14, 2023
2fb6bd7
Apply suggestions from code review
KN4CK3R May 14, 2023
ea313a6
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R May 15, 2023
dc4e5e2
Merge branch 'feature-cran' of https://github.com/KN4CK3R/gitea into …
KN4CK3R May 15, 2023
01f9b55
Merge branch 'main' into feature-cran
GiteaBot May 22, 2023
e0ab621
Merge branch 'main' into feature-cran
GiteaBot May 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,8 @@ ROUTER = console
;LIMIT_SIZE_CONAN = -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 CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_CRAN = -1
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_GENERIC = -1
;; Maximum size of a Helm 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
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
- `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_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_CRAN`: **-1**: Maximum size of a CRAN 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`)
- `LIMIT_SIZE_MAVEN`: **-1**: Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
Expand Down
96 changes: 96 additions & 0 deletions docs/content/doc/packages/cran.en-us.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
date: "2023-01-01T00:00:00+00:00"
title: "CRAN Packages Repository"
slug: "packages/cran"
draft: false
toc: false
menu:
sidebar:
parent: "packages"
name: "CRAN"
weight: 35
identifier: "cran"
---

# CRAN Packages Repository

Publish [CRAN](https://cran.r-project.org/) packages for your user or organization.
silverwind marked this conversation as resolved.
Show resolved Hide resolved

**Table of Contents**

{{< toc >}}

## Requirements

To work with the CRAN package registry, you need to install [the R toolset](https://cran.r-project.org/).
silverwind marked this conversation as resolved.
Show resolved Hide resolved

## Configuring the package registry

To register the package registry you need to add it in your `Rprofile.site` file:
KN4CK3R marked this conversation as resolved.
Show resolved Hide resolved

```
local({
r <- list("gitea" = "https://gitea.example.com/api/packages/{owner}/cran")
options(repos = r)
})
KN4CK3R marked this conversation as resolved.
Show resolved Hide resolved
```

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

If you need to provide credentials, you may embed them as part of the 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.

Source packages:

```
PUT https://gitea.example.com/api/packages/{owner}/cran/src
```

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

Binary packages:

```
PUT https://gitea.example.com/api/packages/{owner}/cran/bin?platform={platform}&rversion={rversion}
```

| Parameter | Description |
| ---------- | ----------- |
| `owner` | The owner of the package. |
| `platform` | The name of the platform. |
| `rversion` | The R version of the binary. |

For example:

```shell
curl --user your_username:your_password_or_token \
--upload-file path/to/package.zip \
https://gitea.example.com/api/packages/testuser/cran/bin?platform=windows&rversion=4.2
```

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 CRAN package from the package registry, execute the following command:

```shell
install.packages({package_name})
```

| Parameter | Description |
| -------------- | ----------- |
| `package_name` | The package name. |

For example:

```shell
install.packages("testpackage")
```
1 change: 1 addition & 0 deletions docs/content/doc/packages/overview.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,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` |
| [Container]({{< relref "doc/packages/container.en-us.md" >}}) | - | any OCI compliant client |
| [CRAN]({{< relref "doc/packages/cran.en-us.md" >}}) | R | - |
| [Generic]({{< relref "doc/packages/generic.en-us.md" >}}) | - | any HTTP client |
| [Helm]({{< relref "doc/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` |
| [Maven]({{< relref "doc/packages/maven.en-us.md" >}}) | Java | `mvn`, `gradle` |
Expand Down
90 changes: 90 additions & 0 deletions models/packages/cran/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package cran

import (
"context"
"strconv"
"strings"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
cran_module "code.gitea.io/gitea/modules/packages/cran"

"xorm.io/builder"
)

type SearchOptions struct {
OwnerID int64
FileType string
Platform string
RVersion string
Filename string
}

func (opts *SearchOptions) toConds() builder.Cond {
var cond builder.Cond = builder.Eq{
"package.type": packages.TypeCran,
"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 propsCond builder.Cond = builder.Eq{
"package_property.ref_type": packages.PropertyTypeFile,
}
propsCond = propsCond.And(builder.Expr("package_property.ref_id = package_file.id"))

count := 1
propsCondBlock := builder.Eq{"package_property.name": cran_module.PropertyType}.And(builder.Eq{"package_property.value": opts.FileType})

if opts.Platform != "" {
count += 2
propsCondBlock = propsCondBlock.
Or(builder.Eq{"package_property.name": cran_module.PropertyPlatform}.And(builder.Eq{"package_property.value": opts.Platform})).
Or(builder.Eq{"package_property.name": cran_module.PropertyRVersion}.And(builder.Eq{"package_property.value": opts.RVersion}))
}

propsCond = propsCond.And(propsCondBlock)

cond = cond.And(builder.Eq{
strconv.Itoa(count): builder.Select("COUNT(*)").Where(propsCond).From("package_property"),
})

return cond
}

func SearchLatestVersions(ctx context.Context, opts *SearchOptions) ([]*packages.PackageVersion, error) {
sess := db.GetEngine(ctx).
Table("package_version").
Select("package_version.*").
Join("LEFT", "package_version pv2", builder.Expr("package_version.package_id = pv2.package_id AND pv2.is_internal = ? AND (package_version.created_unix < pv2.created_unix OR (package_version.created_unix = pv2.created_unix AND package_version.id < pv2.id))", false)).
Join("INNER", "package", "package.id = package_version.package_id").
Join("INNER", "package_file", "package_file.version_id = package_version.id").
Where(opts.toConds().And(builder.Expr("pv2.id IS NULL"))).
Asc("package.name")

pvs := make([]*packages.PackageVersion, 0, 10)
return pvs, sess.Find(&pvs)
}

func SearchFile(ctx context.Context, opts *SearchOptions) (*packages.PackageFile, error) {
sess := db.GetEngine(ctx).
Table("package_version").
Select("package_file.*").
Join("INNER", "package", "package.id = package_version.package_id").
Join("INNER", "package_file", "package_file.version_id = package_version.id").
Where(opts.toConds())

pf := &packages.PackageFile{}
if has, err := sess.Get(pf); err != nil {
return nil, err
} else if !has {
return nil, packages.ErrPackageFileNotExist
}
return pf, nil
}
3 changes: 3 additions & 0 deletions models/packages/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/packages/composer"
"code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/packages/container"
"code.gitea.io/gitea/modules/packages/cran"
"code.gitea.io/gitea/modules/packages/helm"
"code.gitea.io/gitea/modules/packages/maven"
"code.gitea.io/gitea/modules/packages/npm"
Expand Down Expand Up @@ -134,6 +135,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
metadata = &conan.Metadata{}
case TypeContainer:
metadata = &container.Metadata{}
case TypeCran:
metadata = &cran.Metadata{}
case TypeGeneric:
// generic packages have no metadata
case TypeHelm:
Expand Down
6 changes: 6 additions & 0 deletions models/packages/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
TypeComposer Type = "composer"
TypeConan Type = "conan"
TypeContainer Type = "container"
TypeCran Type = "cran"
TypeGeneric Type = "generic"
TypeHelm Type = "helm"
TypeMaven Type = "maven"
Expand All @@ -48,6 +49,7 @@ var TypeList = []Type{
TypeComposer,
TypeConan,
TypeContainer,
TypeCran,
TypeGeneric,
TypeHelm,
TypeMaven,
Expand All @@ -68,6 +70,8 @@ func (pt Type) Name() string {
return "Conan"
case TypeContainer:
return "Container"
case TypeCran:
return "CRAN"
case TypeGeneric:
return "Generic"
case TypeHelm:
Expand Down Expand Up @@ -99,6 +103,8 @@ func (pt Type) SVGName() string {
return "gitea-conan"
case TypeContainer:
return "octicon-container"
case TypeCran:
return "gitea-cran"
case TypeGeneric:
return "octicon-package"
case TypeHelm:
Expand Down