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 }