Files
cluster/handler/manifest_handler.go
2025-11-09 15:19:11 +08:00

107 lines
3.0 KiB
Go

package handler
import (
"bytes"
"context"
"io"
"gitea.loveuer.com/loveuer/cluster/internal/database"
"gitea.loveuer.com/loveuer/cluster/internal/model"
"gitea.loveuer.com/loveuer/cluster/internal/rerr"
"gitea.loveuer.com/loveuer/cluster/internal/registry/storage"
"gorm.io/gorm"
)
type manifestHandlerImpl struct {
store storage.Storage
}
// NewManifestHandler creates a new manifest handler
func NewManifestHandler(store storage.Storage) ManifestHandler {
return &manifestHandlerImpl{store: store}
}
func (m *manifestHandlerImpl) Get(ctx context.Context, repo, tag string) (io.ReadCloser, string, *rerr.RepositoryError) {
data, mediaType, err := m.store.GetManifest(repo, tag)
if err != nil {
return nil, "", &rerr.RepositoryError{
Status: 404,
Code: "MANIFEST_UNKNOWN",
Message: "manifest not found",
}
}
return io.NopCloser(bytes.NewReader(data)), mediaType, nil
}
func (m *manifestHandlerImpl) Put(ctx context.Context, repo, tag, digest string, mf *model.RepoSimpleManifest) error {
return m.store.PutManifest(repo, tag, mf.Blob, mf.ContentType)
}
func (m *manifestHandlerImpl) Delete(ctx context.Context, repo, tag string) error {
return m.store.DeleteManifest(repo, tag)
}
func (m *manifestHandlerImpl) Tags(ctx context.Context, repo string, n, last int, prefix string) (*model.Tag, *rerr.RepositoryError) {
var repository model.RegistryRepository
if err := database.DB.Where("name = ?", repo).First(&repository).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &model.Tag{Name: repo, Tags: []string{}}, nil
}
return nil, rerr.ErrInternal(err)
}
var tags []model.RegistryTag
query := database.DB.Where("repository_id = ?", repository.ID)
if prefix != "" {
query = query.Where("name LIKE ?", prefix+"%")
}
if last > 0 {
query = query.Where("id > ?", last)
}
query = query.Order("id ASC").Limit(n)
if err := query.Find(&tags).Error; err != nil {
return nil, rerr.ErrInternal(err)
}
tagNames := make([]string, len(tags))
for i, tag := range tags {
tagNames[i] = tag.Name
}
return &model.Tag{Name: repo, Tags: tagNames}, nil
}
func (m *manifestHandlerImpl) Catalog(ctx context.Context, n, last int, prefix string) (*model.Catalog, *rerr.RepositoryError) {
var repositories []model.RegistryRepository
query := database.DB
if prefix != "" {
query = query.Where("name LIKE ?", prefix+"%")
}
if last > 0 {
query = query.Where("id > ?", last)
}
query = query.Order("id ASC").Limit(n)
if err := query.Find(&repositories).Error; err != nil {
return nil, rerr.ErrInternal(err)
}
repoNames := make([]string, len(repositories))
for i, repo := range repositories {
repoNames[i] = repo.Name
}
return &model.Catalog{Repositories: repoNames}, nil
}
func (m *manifestHandlerImpl) Referrers(ctx context.Context, repo, target string) (*model.IndexManifest, *rerr.RepositoryError) {
// For now, return an empty index manifest
return &model.IndexManifest{
SchemaVersion: 2,
MediaType: "application/vnd.oci.image.index.v1+json",
Manifests: []model.IndexManifestEntry{},
}, nil
}