You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

descriptor.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package packages
  4. import (
  5. "context"
  6. "fmt"
  7. "net/url"
  8. repo_model "code.gitea.io/gitea/models/repo"
  9. user_model "code.gitea.io/gitea/models/user"
  10. "code.gitea.io/gitea/modules/json"
  11. "code.gitea.io/gitea/modules/packages/composer"
  12. "code.gitea.io/gitea/modules/packages/conan"
  13. "code.gitea.io/gitea/modules/packages/conda"
  14. "code.gitea.io/gitea/modules/packages/container"
  15. "code.gitea.io/gitea/modules/packages/helm"
  16. "code.gitea.io/gitea/modules/packages/maven"
  17. "code.gitea.io/gitea/modules/packages/npm"
  18. "code.gitea.io/gitea/modules/packages/nuget"
  19. "code.gitea.io/gitea/modules/packages/pub"
  20. "code.gitea.io/gitea/modules/packages/pypi"
  21. "code.gitea.io/gitea/modules/packages/rubygems"
  22. "code.gitea.io/gitea/modules/packages/vagrant"
  23. "github.com/hashicorp/go-version"
  24. )
  25. // PackagePropertyList is a list of package properties
  26. type PackagePropertyList []*PackageProperty
  27. // GetByName gets the first property value with the specific name
  28. func (l PackagePropertyList) GetByName(name string) string {
  29. for _, pp := range l {
  30. if pp.Name == name {
  31. return pp.Value
  32. }
  33. }
  34. return ""
  35. }
  36. // PackageDescriptor describes a package
  37. type PackageDescriptor struct {
  38. Package *Package
  39. Owner *user_model.User
  40. Repository *repo_model.Repository
  41. Version *PackageVersion
  42. SemVer *version.Version
  43. Creator *user_model.User
  44. PackageProperties PackagePropertyList
  45. VersionProperties PackagePropertyList
  46. Metadata interface{}
  47. Files []*PackageFileDescriptor
  48. }
  49. // PackageFileDescriptor describes a package file
  50. type PackageFileDescriptor struct {
  51. File *PackageFile
  52. Blob *PackageBlob
  53. Properties PackagePropertyList
  54. }
  55. // PackageWebLink returns the package web link
  56. func (pd *PackageDescriptor) PackageWebLink() string {
  57. return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName))
  58. }
  59. // FullWebLink returns the package version web link
  60. func (pd *PackageDescriptor) FullWebLink() string {
  61. return fmt.Sprintf("%s/%s", pd.PackageWebLink(), url.PathEscape(pd.Version.LowerVersion))
  62. }
  63. // CalculateBlobSize returns the total blobs size in bytes
  64. func (pd *PackageDescriptor) CalculateBlobSize() int64 {
  65. size := int64(0)
  66. for _, f := range pd.Files {
  67. size += f.Blob.Size
  68. }
  69. return size
  70. }
  71. // GetPackageDescriptor gets the package description for a version
  72. func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDescriptor, error) {
  73. p, err := GetPackageByID(ctx, pv.PackageID)
  74. if err != nil {
  75. return nil, err
  76. }
  77. o, err := user_model.GetUserByID(ctx, p.OwnerID)
  78. if err != nil {
  79. return nil, err
  80. }
  81. repository, err := repo_model.GetRepositoryByID(ctx, p.RepoID)
  82. if err != nil && !repo_model.IsErrRepoNotExist(err) {
  83. return nil, err
  84. }
  85. creator, err := user_model.GetUserByID(ctx, pv.CreatorID)
  86. if err != nil {
  87. return nil, err
  88. }
  89. var semVer *version.Version
  90. if p.SemverCompatible {
  91. semVer, err = version.NewVersion(pv.Version)
  92. if err != nil {
  93. return nil, err
  94. }
  95. }
  96. pps, err := GetProperties(ctx, PropertyTypePackage, p.ID)
  97. if err != nil {
  98. return nil, err
  99. }
  100. pvps, err := GetProperties(ctx, PropertyTypeVersion, pv.ID)
  101. if err != nil {
  102. return nil, err
  103. }
  104. pfs, err := GetFilesByVersionID(ctx, pv.ID)
  105. if err != nil {
  106. return nil, err
  107. }
  108. pfds := make([]*PackageFileDescriptor, 0, len(pfs))
  109. for _, pf := range pfs {
  110. pfd, err := GetPackageFileDescriptor(ctx, pf)
  111. if err != nil {
  112. return nil, err
  113. }
  114. pfds = append(pfds, pfd)
  115. }
  116. var metadata interface{}
  117. switch p.Type {
  118. case TypeComposer:
  119. metadata = &composer.Metadata{}
  120. case TypeConan:
  121. metadata = &conan.Metadata{}
  122. case TypeConda:
  123. metadata = &conda.VersionMetadata{}
  124. case TypeContainer:
  125. metadata = &container.Metadata{}
  126. case TypeGeneric:
  127. // generic packages have no metadata
  128. case TypeHelm:
  129. metadata = &helm.Metadata{}
  130. case TypeNuGet:
  131. metadata = &nuget.Metadata{}
  132. case TypeNpm:
  133. metadata = &npm.Metadata{}
  134. case TypeMaven:
  135. metadata = &maven.Metadata{}
  136. case TypePub:
  137. metadata = &pub.Metadata{}
  138. case TypePyPI:
  139. metadata = &pypi.Metadata{}
  140. case TypeRubyGems:
  141. metadata = &rubygems.Metadata{}
  142. case TypeVagrant:
  143. metadata = &vagrant.Metadata{}
  144. default:
  145. panic(fmt.Sprintf("unknown package type: %s", string(p.Type)))
  146. }
  147. if metadata != nil {
  148. if err := json.Unmarshal([]byte(pv.MetadataJSON), &metadata); err != nil {
  149. return nil, err
  150. }
  151. }
  152. return &PackageDescriptor{
  153. Package: p,
  154. Owner: o,
  155. Repository: repository,
  156. Version: pv,
  157. SemVer: semVer,
  158. Creator: creator,
  159. PackageProperties: PackagePropertyList(pps),
  160. VersionProperties: PackagePropertyList(pvps),
  161. Metadata: metadata,
  162. Files: pfds,
  163. }, nil
  164. }
  165. // GetPackageFileDescriptor gets a package file descriptor for a package file
  166. func GetPackageFileDescriptor(ctx context.Context, pf *PackageFile) (*PackageFileDescriptor, error) {
  167. pb, err := GetBlobByID(ctx, pf.BlobID)
  168. if err != nil {
  169. return nil, err
  170. }
  171. pfps, err := GetProperties(ctx, PropertyTypeFile, pf.ID)
  172. if err != nil {
  173. return nil, err
  174. }
  175. return &PackageFileDescriptor{
  176. pf,
  177. pb,
  178. PackagePropertyList(pfps),
  179. }, nil
  180. }
  181. // GetPackageDescriptors gets the package descriptions for the versions
  182. func GetPackageDescriptors(ctx context.Context, pvs []*PackageVersion) ([]*PackageDescriptor, error) {
  183. pds := make([]*PackageDescriptor, 0, len(pvs))
  184. for _, pv := range pvs {
  185. pd, err := GetPackageDescriptor(ctx, pv)
  186. if err != nil {
  187. return nil, err
  188. }
  189. pds = append(pds, pd)
  190. }
  191. return pds, nil
  192. }