2022-03-30 11:42:47 +03:00
|
|
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
2022-11-27 21:20:29 +03:00
|
|
|
// SPDX-License-Identifier: MIT
|
2022-03-30 11:42:47 +03:00
|
|
|
|
|
|
|
package packages
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-04-04 11:14:46 +03:00
|
|
|
"errors"
|
2022-03-30 11:42:47 +03:00
|
|
|
"fmt"
|
|
|
|
"net/url"
|
|
|
|
|
|
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
|
|
"code.gitea.io/gitea/modules/json"
|
2023-05-12 20:27:50 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/alpine"
|
2024-08-04 09:16:29 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/arch"
|
2023-02-05 13:12:31 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/cargo"
|
2023-02-06 04:49:21 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/chef"
|
2022-03-30 11:42:47 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/composer"
|
|
|
|
"code.gitea.io/gitea/modules/packages/conan"
|
2023-02-01 21:30:39 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/conda"
|
2022-03-30 11:42:47 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/container"
|
2023-05-22 05:57:49 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/cran"
|
2023-05-02 19:31:35 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/debian"
|
2022-04-19 19:55:35 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/helm"
|
2022-03-30 11:42:47 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/maven"
|
|
|
|
"code.gitea.io/gitea/modules/packages/npm"
|
|
|
|
"code.gitea.io/gitea/modules/packages/nuget"
|
2022-08-07 13:09:54 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/pub"
|
2022-03-30 11:42:47 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/pypi"
|
2023-05-05 23:33:37 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/rpm"
|
2022-03-30 11:42:47 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/rubygems"
|
2023-03-13 23:28:39 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/swift"
|
2022-08-29 10:04:45 +03:00
|
|
|
"code.gitea.io/gitea/modules/packages/vagrant"
|
2023-04-04 11:14:46 +03:00
|
|
|
"code.gitea.io/gitea/modules/util"
|
2022-03-30 11:42:47 +03:00
|
|
|
|
|
|
|
"github.com/hashicorp/go-version"
|
|
|
|
)
|
|
|
|
|
|
|
|
// PackagePropertyList is a list of package properties
|
|
|
|
type PackagePropertyList []*PackageProperty
|
|
|
|
|
|
|
|
// GetByName gets the first property value with the specific name
|
|
|
|
func (l PackagePropertyList) GetByName(name string) string {
|
|
|
|
for _, pp := range l {
|
|
|
|
if pp.Name == name {
|
|
|
|
return pp.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// PackageDescriptor describes a package
|
|
|
|
type PackageDescriptor struct {
|
2022-07-28 06:59:39 +03:00
|
|
|
Package *Package
|
|
|
|
Owner *user_model.User
|
|
|
|
Repository *repo_model.Repository
|
|
|
|
Version *PackageVersion
|
|
|
|
SemVer *version.Version
|
|
|
|
Creator *user_model.User
|
|
|
|
PackageProperties PackagePropertyList
|
|
|
|
VersionProperties PackagePropertyList
|
2023-07-04 21:36:08 +03:00
|
|
|
Metadata any
|
2022-07-28 06:59:39 +03:00
|
|
|
Files []*PackageFileDescriptor
|
2022-03-30 11:42:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// PackageFileDescriptor describes a package file
|
|
|
|
type PackageFileDescriptor struct {
|
|
|
|
File *PackageFile
|
|
|
|
Blob *PackageBlob
|
|
|
|
Properties PackagePropertyList
|
|
|
|
}
|
|
|
|
|
2024-03-02 20:38:38 +03:00
|
|
|
// PackageWebLink returns the relative package web link
|
2022-03-30 11:42:47 +03:00
|
|
|
func (pd *PackageDescriptor) PackageWebLink() string {
|
2023-02-06 21:09:18 +03:00
|
|
|
return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HomeLink(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName))
|
2022-03-30 11:42:47 +03:00
|
|
|
}
|
|
|
|
|
2024-03-02 20:38:38 +03:00
|
|
|
// VersionWebLink returns the relative package version web link
|
|
|
|
func (pd *PackageDescriptor) VersionWebLink() string {
|
2022-03-30 11:42:47 +03:00
|
|
|
return fmt.Sprintf("%s/%s", pd.PackageWebLink(), url.PathEscape(pd.Version.LowerVersion))
|
|
|
|
}
|
|
|
|
|
2024-03-02 20:38:38 +03:00
|
|
|
// PackageHTMLURL returns the absolute package HTML URL
|
|
|
|
func (pd *PackageDescriptor) PackageHTMLURL() string {
|
|
|
|
return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName))
|
|
|
|
}
|
|
|
|
|
|
|
|
// VersionHTMLURL returns the absolute package version HTML URL
|
|
|
|
func (pd *PackageDescriptor) VersionHTMLURL() string {
|
|
|
|
return fmt.Sprintf("%s/%s", pd.PackageHTMLURL(), url.PathEscape(pd.Version.LowerVersion))
|
|
|
|
}
|
|
|
|
|
2022-03-30 11:42:47 +03:00
|
|
|
// CalculateBlobSize returns the total blobs size in bytes
|
|
|
|
func (pd *PackageDescriptor) CalculateBlobSize() int64 {
|
|
|
|
size := int64(0)
|
|
|
|
for _, f := range pd.Files {
|
|
|
|
size += f.Blob.Size
|
|
|
|
}
|
|
|
|
return size
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPackageDescriptor gets the package description for a version
|
|
|
|
func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDescriptor, error) {
|
|
|
|
p, err := GetPackageByID(ctx, pv.PackageID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-12-03 05:48:26 +03:00
|
|
|
o, err := user_model.GetUserByID(ctx, p.OwnerID)
|
2022-03-30 11:42:47 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-12-03 05:48:26 +03:00
|
|
|
repository, err := repo_model.GetRepositoryByID(ctx, p.RepoID)
|
2022-03-30 11:42:47 +03:00
|
|
|
if err != nil && !repo_model.IsErrRepoNotExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-12-03 05:48:26 +03:00
|
|
|
creator, err := user_model.GetUserByID(ctx, pv.CreatorID)
|
2022-03-30 11:42:47 +03:00
|
|
|
if err != nil {
|
2023-04-04 11:14:46 +03:00
|
|
|
if errors.Is(err, util.ErrNotExist) {
|
|
|
|
creator = user_model.NewGhostUser()
|
|
|
|
} else {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-03-30 11:42:47 +03:00
|
|
|
}
|
|
|
|
var semVer *version.Version
|
|
|
|
if p.SemverCompatible {
|
|
|
|
semVer, err = version.NewVersion(pv.Version)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-28 06:59:39 +03:00
|
|
|
pps, err := GetProperties(ctx, PropertyTypePackage, p.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-03-30 11:42:47 +03:00
|
|
|
pvps, err := GetProperties(ctx, PropertyTypeVersion, pv.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pfs, err := GetFilesByVersionID(ctx, pv.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-05-02 19:31:35 +03:00
|
|
|
pfds, err := GetPackageFileDescriptors(ctx, pfs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-03-30 11:42:47 +03:00
|
|
|
}
|
|
|
|
|
2023-07-04 21:36:08 +03:00
|
|
|
var metadata any
|
2022-03-30 11:42:47 +03:00
|
|
|
switch p.Type {
|
2023-05-12 20:27:50 +03:00
|
|
|
case TypeAlpine:
|
|
|
|
metadata = &alpine.VersionMetadata{}
|
2024-08-04 09:16:29 +03:00
|
|
|
case TypeArch:
|
|
|
|
metadata = &arch.VersionMetadata{}
|
2023-02-05 13:12:31 +03:00
|
|
|
case TypeCargo:
|
|
|
|
metadata = &cargo.Metadata{}
|
2023-02-06 04:49:21 +03:00
|
|
|
case TypeChef:
|
|
|
|
metadata = &chef.Metadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypeComposer:
|
|
|
|
metadata = &composer.Metadata{}
|
|
|
|
case TypeConan:
|
|
|
|
metadata = &conan.Metadata{}
|
2023-02-01 21:30:39 +03:00
|
|
|
case TypeConda:
|
|
|
|
metadata = &conda.VersionMetadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypeContainer:
|
|
|
|
metadata = &container.Metadata{}
|
2023-05-22 05:57:49 +03:00
|
|
|
case TypeCran:
|
|
|
|
metadata = &cran.Metadata{}
|
2023-05-02 19:31:35 +03:00
|
|
|
case TypeDebian:
|
|
|
|
metadata = &debian.Metadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypeGeneric:
|
|
|
|
// generic packages have no metadata
|
2023-05-14 18:38:40 +03:00
|
|
|
case TypeGo:
|
|
|
|
// go packages have no metadata
|
2022-04-19 19:55:35 +03:00
|
|
|
case TypeHelm:
|
|
|
|
metadata = &helm.Metadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypeNuGet:
|
|
|
|
metadata = &nuget.Metadata{}
|
|
|
|
case TypeNpm:
|
|
|
|
metadata = &npm.Metadata{}
|
|
|
|
case TypeMaven:
|
|
|
|
metadata = &maven.Metadata{}
|
2022-08-07 13:09:54 +03:00
|
|
|
case TypePub:
|
|
|
|
metadata = &pub.Metadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypePyPI:
|
|
|
|
metadata = &pypi.Metadata{}
|
2023-05-05 23:33:37 +03:00
|
|
|
case TypeRpm:
|
|
|
|
metadata = &rpm.VersionMetadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
case TypeRubyGems:
|
|
|
|
metadata = &rubygems.Metadata{}
|
2023-03-13 23:28:39 +03:00
|
|
|
case TypeSwift:
|
|
|
|
metadata = &swift.Metadata{}
|
2022-08-29 10:04:45 +03:00
|
|
|
case TypeVagrant:
|
|
|
|
metadata = &vagrant.Metadata{}
|
2022-03-30 11:42:47 +03:00
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unknown package type: %s", string(p.Type)))
|
|
|
|
}
|
|
|
|
if metadata != nil {
|
|
|
|
if err := json.Unmarshal([]byte(pv.MetadataJSON), &metadata); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &PackageDescriptor{
|
2022-07-28 06:59:39 +03:00
|
|
|
Package: p,
|
|
|
|
Owner: o,
|
|
|
|
Repository: repository,
|
|
|
|
Version: pv,
|
|
|
|
SemVer: semVer,
|
|
|
|
Creator: creator,
|
|
|
|
PackageProperties: PackagePropertyList(pps),
|
|
|
|
VersionProperties: PackagePropertyList(pvps),
|
|
|
|
Metadata: metadata,
|
|
|
|
Files: pfds,
|
2022-03-30 11:42:47 +03:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPackageFileDescriptor gets a package file descriptor for a package file
|
|
|
|
func GetPackageFileDescriptor(ctx context.Context, pf *PackageFile) (*PackageFileDescriptor, error) {
|
|
|
|
pb, err := GetBlobByID(ctx, pf.BlobID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pfps, err := GetProperties(ctx, PropertyTypeFile, pf.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &PackageFileDescriptor{
|
|
|
|
pf,
|
|
|
|
pb,
|
|
|
|
PackagePropertyList(pfps),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2023-05-02 19:31:35 +03:00
|
|
|
// GetPackageFileDescriptors gets the package file descriptors for the package files
|
|
|
|
func GetPackageFileDescriptors(ctx context.Context, pfs []*PackageFile) ([]*PackageFileDescriptor, error) {
|
|
|
|
pfds := make([]*PackageFileDescriptor, 0, len(pfs))
|
|
|
|
for _, pf := range pfs {
|
|
|
|
pfd, err := GetPackageFileDescriptor(ctx, pf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pfds = append(pfds, pfd)
|
|
|
|
}
|
|
|
|
return pfds, nil
|
|
|
|
}
|
|
|
|
|
2022-03-30 11:42:47 +03:00
|
|
|
// GetPackageDescriptors gets the package descriptions for the versions
|
|
|
|
func GetPackageDescriptors(ctx context.Context, pvs []*PackageVersion) ([]*PackageDescriptor, error) {
|
|
|
|
pds := make([]*PackageDescriptor, 0, len(pvs))
|
|
|
|
for _, pv := range pvs {
|
|
|
|
pd, err := GetPackageDescriptor(ctx, pv)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pds = append(pds, pd)
|
|
|
|
}
|
|
|
|
return pds, nil
|
|
|
|
}
|