Skip to content

Commit 3054104

Browse files
committed
fix
1 parent b388138 commit 3054104

File tree

10 files changed

+107
-34
lines changed

10 files changed

+107
-34
lines changed

models/packages/package_property.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ func DeletePropertyByID(ctx context.Context, propertyID int64) error {
9292
return err
9393
}
9494

95-
// DeletePropertyByName deletes properties by name
96-
func DeletePropertyByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
95+
// DeletePropertiesByName deletes properties by name
96+
func DeletePropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
9797
_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Delete(&PackageProperty{})
9898
return err
9999
}

modules/packages/content_store.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ func NewContentStore() *ContentStore {
2828
return contentStore
2929
}
3030

31-
// Get gets a package blob
32-
func (s *ContentStore) Get(key BlobHash256Key) (storage.Object, error) {
31+
func (s *ContentStore) OpenBlob(key BlobHash256Key) (storage.Object, error) {
3332
return s.store.Open(KeyToRelativePath(key))
3433
}
3534

routers/api/packages/container/manifest.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func processOciImageManifest(ctx context.Context, mci *manifestCreationInfo, buf
108108
return err
109109
}
110110

111-
configReader, err := packages_module.NewContentStore().Get(packages_module.BlobHash256Key(configDescriptor.Blob.HashSHA256))
111+
configReader, err := packages_module.NewContentStore().OpenBlob(packages_module.BlobHash256Key(configDescriptor.Blob.HashSHA256))
112112
if err != nil {
113113
return err
114114
}
@@ -388,19 +388,16 @@ func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, met
388388
return nil, err
389389
}
390390
} else {
391-
props, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeVersion, pv.ID, container_module.PropertyManifestTagged)
392-
if err != nil {
391+
if err = packages_model.DeletePropertiesByName(ctx, packages_model.PropertyTypeVersion, pv.ID, container_module.PropertyManifestTagged); err != nil {
393392
return nil, err
394393
}
395-
for _, prop := range props {
396-
if err = packages_model.DeletePropertyByID(ctx, prop.ID); err != nil {
397-
return nil, err
398-
}
399-
}
400394
}
401395

396+
if err = packages_model.DeletePropertiesByName(ctx, packages_model.PropertyTypeVersion, pv.ID, container_module.PropertyManifestReference); err != nil {
397+
return nil, err
398+
}
402399
for _, manifest := range metadata.Manifests {
403-
if err = packages_model.InsertOrUpdateProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, container_module.PropertyManifestReference, manifest.Digest); err != nil {
400+
if _, err = packages_model.InsertProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, container_module.PropertyManifestReference, manifest.Digest); err != nil {
404401
return nil, err
405402
}
406403
}

routers/web/user/package.go

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
package user
55

66
import (
7+
"code.gitea.io/gitea/modules/json"
8+
packages_module "code.gitea.io/gitea/modules/packages"
9+
container_module "code.gitea.io/gitea/modules/packages/container"
10+
gocontext "context"
11+
"errors"
12+
oci "github.com/opencontainers/image-spec/specs-go/v1"
13+
"io"
714
"net/http"
815
"net/url"
916

@@ -162,13 +169,55 @@ func RedirectToLastVersion(ctx *context.Context) {
162169
ctx.Redirect(pd.VersionWebLink())
163170
}
164171

172+
func viewPackageContainerImage(ctx gocontext.Context, pd *packages_model.PackageDescriptor, digest string) (*container_module.Metadata, error) {
173+
manifestBlob, err := container_model.GetContainerBlob(ctx, &container_model.BlobSearchOptions{
174+
OwnerID: pd.Owner.ID,
175+
Image: pd.Package.LowerName,
176+
Digest: digest,
177+
})
178+
if err != nil {
179+
return nil, err
180+
}
181+
subManifestStream, err := packages_service.OpenPackageBlobStream(manifestBlob.Blob)
182+
if err != nil {
183+
return nil, err
184+
}
185+
defer subManifestStream.Close()
186+
187+
buf, err := io.ReadAll(subManifestStream)
188+
if err != nil {
189+
return nil, err
190+
}
191+
var manifest oci.Manifest
192+
if err := json.Unmarshal(buf, &manifest); err != nil {
193+
return nil, err
194+
}
195+
configDescriptor, err := container_model.GetContainerBlob(ctx, &container_model.BlobSearchOptions{
196+
OwnerID: pd.Owner.ID,
197+
Image: pd.Package.LowerName,
198+
Digest: string(manifest.Config.Digest),
199+
})
200+
if err != nil {
201+
return nil, err
202+
}
203+
204+
configReader, err := packages_module.NewContentStore().OpenBlob(packages_module.BlobHash256Key(configDescriptor.Blob.HashSHA256))
205+
if err != nil {
206+
return nil, err
207+
}
208+
defer configReader.Close()
209+
210+
return container_module.ParseImageConfig(manifest.Config.MediaType, configReader)
211+
}
212+
165213
// ViewPackageVersion displays a single package version
166214
func ViewPackageVersion(ctx *context.Context) {
167215
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
168216
ctx.ServerError("RenderUserOrgHeader", err)
169217
return
170218
}
171219

220+
versionSub := ctx.PathParam("version_sub")
172221
pd := ctx.Package.Descriptor
173222
ctx.Data["Title"] = pd.Package.Name
174223
ctx.Data["IsPackagesPage"] = true
@@ -180,6 +229,9 @@ func ViewPackageVersion(ctx *context.Context) {
180229
}
181230
ctx.Data["PackageRegistryHost"] = registryHostURL.Host
182231

232+
var pvs []*packages_model.PackageVersion
233+
pvsTotal := int64(0)
234+
183235
switch pd.Package.Type {
184236
case packages_model.TypeAlpine:
185237
branches := make(container.Set[string])
@@ -257,21 +309,26 @@ func ViewPackageVersion(ctx *context.Context) {
257309

258310
ctx.Data["Groups"] = util.Sorted(groups.Values())
259311
ctx.Data["Architectures"] = util.Sorted(architectures.Values())
260-
}
261-
262-
var (
263-
total int64
264-
pvs []*packages_model.PackageVersion
265-
)
266-
switch pd.Package.Type {
267312
case packages_model.TypeContainer:
268-
pvs, total, err = container_model.SearchImageTags(ctx, &container_model.ImageTagsSearchOptions{
313+
pvs, pvsTotal, err = container_model.SearchImageTags(ctx, &container_model.ImageTagsSearchOptions{
269314
Paginator: db.NewAbsoluteListOptions(0, 5),
270315
PackageID: pd.Package.ID,
271316
IsTagged: true,
272317
})
318+
ctx.Data["ContainerImageMetadata"] = pd.Metadata
319+
if versionSub != "" {
320+
imageMeta, err := viewPackageContainerImage(ctx, pd, versionSub)
321+
if errors.Is(err, util.ErrNotExist) {
322+
ctx.NotFound(nil)
323+
return
324+
} else if err != nil {
325+
ctx.ServerError("viewPackageContainerImage", err)
326+
return
327+
}
328+
ctx.Data["ContainerImageMetadata"] = imageMeta
329+
}
273330
default:
274-
pvs, total, err = packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
331+
pvs, pvsTotal, err = packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
275332
Paginator: db.NewAbsoluteListOptions(0, 5),
276333
PackageID: pd.Package.ID,
277334
IsInternal: optional.Some(false),
@@ -283,7 +340,7 @@ func ViewPackageVersion(ctx *context.Context) {
283340
}
284341

285342
ctx.Data["LatestVersions"] = pvs
286-
ctx.Data["TotalVersionCount"] = total
343+
ctx.Data["TotalVersionCount"] = pvsTotal
287344

288345
ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
289346

routers/web/web.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,7 @@ func registerWebRoutes(m *web.Router) {
10121012
m.Get("/versions", user.ListPackageVersions)
10131013
m.Group("/{version}", func() {
10141014
m.Get("", user.ViewPackageVersion)
1015+
m.Get("/{version_sub}", user.ViewPackageVersion)
10151016
m.Get("/files/{fileid}", user.DownloadPackageFile)
10161017
m.Group("/settings", func() {
10171018
m.Get("", user.PackageSettings)

services/packages/container/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func UpdateRepositoryNames(ctx context.Context, owner *user_model.User, newOwner
2222
newOwnerName = strings.ToLower(newOwnerName)
2323

2424
for _, p := range ps {
25-
if err := packages_model.DeletePropertyByName(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository); err != nil {
25+
if err := packages_model.DeletePropertiesByName(ctx, packages_model.PropertyTypePackage, p.ID, container_module.PropertyRepository); err != nil {
2626
return err
2727
}
2828

services/packages/packages.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (
599599
return GetPackageBlobStream(ctx, pf, pb, nil)
600600
}
601601

602+
func OpenPackageBlobStream(pb *packages_model.PackageBlob) (io.ReadSeekCloser, error) {
603+
cs := packages_module.NewContentStore()
604+
key := packages_module.BlobHash256Key(pb.HashSHA256)
605+
return cs.OpenBlob(key)
606+
}
607+
602608
// GetPackageBlobStream returns the content of the specific package blob
603609
// If the storage supports direct serving and it's enabled, only the direct serving url is returned.
604610
func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, pb *packages_model.PackageBlob, serveDirectReqParams url.Values) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
@@ -617,7 +623,7 @@ func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, p
617623
}
618624
}
619625
if u == nil {
620-
s, err = cs.Get(key)
626+
s, err = cs.OpenBlob(key)
621627
}
622628

623629
if err == nil {

templates/package/content/container.tmpl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@
4949
{{/* "unknown/unknown" is attestation-manifest, so we should skip it */}}
5050
{{if ne .Platform "unknown/unknown"}}
5151
<tr>
52-
<td><a class="tw-font-mono" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .Digest}}">{{StringUtils.TrimPrefix .Digest "sha256:" | ShortSha}}</a></td>
52+
<td>
53+
<a class="tw-font-mono" href="{{$.PackageDescriptor.PackageWebLink}}/{{$.PackageDescriptor.Version.LowerVersion}}/{{PathEscape .Digest}}">
54+
{{StringUtils.TrimPrefix .Digest "sha256:" | ShortSha}}
55+
</a>
56+
</td>
5357
<td>{{.Platform}}</td>
5458
<td>{{FileSize .Size}}</td>
5559
</tr>
@@ -65,12 +69,22 @@
6569
{{.PackageDescriptor.Metadata.Description}}
6670
</div>
6771
{{end}}
68-
{{if .PackageDescriptor.Metadata.ImageLayers}}
69-
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.container.layers"}}</h4>
72+
73+
{{/* a container manifest may contain sub manifests, so here we try to display the layers and labels of the sub manifest */}}
74+
{{$imageMetadata := .ContainerImageMetadata}}
75+
{{if $imageMetadata.ImageLayers}}
76+
<h4 class="ui top attached header flex-text-block">
77+
{{ctx.Locale.Tr "packages.container.layers"}}
78+
{{if ne .ContainerImageMetadata .PackageDescriptor.Metadata}}
79+
<span class="tw-text-sm flex-text-inline" title="{{ctx.Locale.Tr "packages.container.details.platform"}}">
80+
({{svg "octicon-cpu" 12}} {{.ContainerImageMetadata.Platform}})
81+
</span>
82+
{{end}}
83+
</h4>
7084
<div class="ui attached segment tw-break-anywhere">
7185
<table class="ui very basic compact table">
7286
<tbody>
73-
{{range .PackageDescriptor.Metadata.ImageLayers}}
87+
{{range $imageMetadata.ImageLayers}}
7488
<tr>
7589
<td>{{.}}</td>
7690
</tr>
@@ -79,7 +93,7 @@
7993
</table>
8094
</div>
8195
{{end}}
82-
{{if .PackageDescriptor.Metadata.Labels}}
96+
{{if $imageMetadata.Labels}}
8397
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.container.labels"}}</h4>
8498
<div class="ui attached segment">
8599
<table class="ui very basic compact table">
@@ -90,7 +104,7 @@
90104
</tr>
91105
</thead>
92106
<tbody>
93-
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
107+
{{range $key, $value := $imageMetadata.Labels}}
94108
<tr>
95109
<td class="tw-align-top">{{$key}}</td>
96110
<td class="tw-break-anywhere">{{$value}}</td>

templates/package/content/pypi.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="ui form">
55
<div class="field">
66
<label>{{svg "octicon-terminal"}} {{ctx.Locale.Tr "packages.pypi.install"}}</label>
7-
<div class="markup"><pre class="code-block"><code>pip install --index-url <origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pypi/simple/"></origin-url> {{.PackageDescriptor.Package.Name}}</code></pre></div>
7+
<div class="markup"><pre class="code-block"><code>pip install --index-url <origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/pypi/simple/"></origin-url> --extra-index-url https://pypi.org/ {{.PackageDescriptor.Package.Name}}</code></pre></div>
88
</div>
99
<div class="field">
1010
<label>{{ctx.Locale.Tr "packages.registry.documentation" "PyPI" "https://docs.gitea.com/usage/packages/pypi/"}}</label>

tests/integration/api_packages_container_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,7 @@ func TestPackageContainer(t *testing.T) {
562562
assert.ElementsMatch(t, []string{strings.ToLower(user.LowerName + "/" + image)}, getAllByName(pd.PackageProperties, container_module.PropertyRepository))
563563
assert.True(t, has(pd.VersionProperties, container_module.PropertyManifestTagged))
564564

565-
// only the last manifest digest is associated with the version (OCI builders will push the index manifest digest as the final step)
566-
assert.ElementsMatch(t, []string{untaggedManifestDigest}, getAllByName(pd.VersionProperties, container_module.PropertyManifestReference))
565+
assert.ElementsMatch(t, []string{manifestDigest, untaggedManifestDigest}, getAllByName(pd.VersionProperties, container_module.PropertyManifestReference))
567566

568567
assert.IsType(t, &container_module.Metadata{}, pd.Metadata)
569568
metadata := pd.Metadata.(*container_module.Metadata)

0 commit comments

Comments
 (0)