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.5KB

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