-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
// 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"
"code.gitea.io/gitea/modules/packages/helm"
"code.gitea.io/gitea/modules/packages/maven"
"code.gitea.io/gitea/modules/packages/npm"
"code.gitea.io/gitea/modules/packages/nuget"
"code.gitea.io/gitea/modules/packages/pypi"
"code.gitea.io/gitea/modules/packages/rubygems"
"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 {
Package *Package
Owner *user_model.User
Repository *repo_model.Repository
Version *PackageVersion
SemVer *version.Version
Creator *user_model.User
Properties PackagePropertyList
Metadata interface{}
Files []*PackageFileDescriptor
}
// 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
}
}
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
case TypeHelm:
metadata = &helm.Metadata{}
case TypeNuGet:
metadata = &nuget.Metadata{}
case TypeNpm:
metadata = &npm.Metadata{}
case TypeMaven:
metadata = &maven.Metadata{}
case TypePyPI:
metadata = &pypi.Metadata{}
case TypeRubyGems:
metadata = &rubygems.Metadata{}
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{
Package: p,
Owner: o,
Repository: repository,
Version: pv,
SemVer: semVer,
Creator: creator,
Properties: PackagePropertyList(pvps),
Metadata: metadata,
Files: pfds,
}, 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
}