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"
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 { }
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
}