2022-03-30 11:42:47 +03:00
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package packages
import (
"context"
"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"
"code.gitea.io/gitea/modules/packages/composer"
"code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/packages/container"
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"
"code.gitea.io/gitea/modules/packages/rubygems"
2022-08-29 10:04:45 +03:00
"code.gitea.io/gitea/modules/packages/vagrant"
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
Metadata interface { }
Files [ ] * PackageFileDescriptor
2022-03-30 11:42:47 +03:00
}
// PackageFileDescriptor describes a package file
type PackageFileDescriptor struct {
File * PackageFile
Blob * PackageBlob
Properties PackagePropertyList
}
// PackageWebLink returns the package web link
func ( pd * PackageDescriptor ) PackageWebLink ( ) string {
return fmt . Sprintf ( "%s/-/packages/%s/%s" , pd . Owner . HTMLURL ( ) , string ( pd . Package . Type ) , url . PathEscape ( pd . Package . LowerName ) )
}
// FullWebLink returns the package version web link
func ( pd * PackageDescriptor ) FullWebLink ( ) string {
return fmt . Sprintf ( "%s/%s" , pd . PackageWebLink ( ) , url . PathEscape ( pd . Version . LowerVersion ) )
}
// 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
}
o , err := user_model . GetUserByIDCtx ( ctx , p . OwnerID )
if err != nil {
return nil , err
}
repository , err := repo_model . GetRepositoryByIDCtx ( ctx , p . RepoID )
if err != nil && ! repo_model . IsErrRepoNotExist ( err ) {
return nil , err
}
creator , err := user_model . GetUserByIDCtx ( ctx , pv . CreatorID )
if err != nil {
return nil , err
}
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
}
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 )
}
var metadata interface { }
switch p . Type {
case TypeComposer :
metadata = & composer . Metadata { }
case TypeConan :
metadata = & conan . Metadata { }
case TypeContainer :
metadata = & container . Metadata { }
case TypeGeneric :
// generic 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 { }
case TypeRubyGems :
metadata = & rubygems . 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
}
// 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
}