99 "encoding/json"
1010 "fmt"
1111 "io"
12- "strings"
1312
1413 "github.com/opencontainers/go-digest"
1514 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -35,7 +34,6 @@ const maxManifestLayers = 64
3534// Compile-time interface checks.
3635var (
3736 _ RegistryClient = (* Registry )(nil )
38- _ oras.Target = (* storeAdapter )(nil )
3937 _ oras.Target = (* validatingTarget )(nil )
4038)
4139
@@ -100,10 +98,8 @@ func (r *Registry) Push(ctx context.Context, store *Store, artifactDigest digest
10098 return err
10199 }
102100
103- adapter := newStoreAdapter (store )
104-
105- // Resolve the artifact to get its descriptor for oras.CopyGraph
106- desc , err := adapter .descriptorFromDigest (ctx , artifactDigest )
101+ // Resolve the artifact to get its full descriptor from the OCI store.
102+ desc , err := store .Target ().Resolve (ctx , artifactDigest .String ())
107103 if err != nil {
108104 return fmt .Errorf ("resolving artifact descriptor: %w" , err )
109105 }
@@ -114,7 +110,7 @@ func (r *Registry) Push(ctx context.Context, store *Store, artifactDigest digest
114110 }
115111
116112 // Copy the content graph (blobs → manifests → index) to the remote
117- if err := oras .CopyGraph (ctx , adapter , target , desc , oras .DefaultCopyGraphOptions ); err != nil {
113+ if err := oras .CopyGraph (ctx , store . Target () , target , desc , oras .DefaultCopyGraphOptions ); err != nil {
118114 return fmt .Errorf ("pushing to registry: %w" , err )
119115 }
120116
@@ -139,8 +135,7 @@ func (r *Registry) Pull(ctx context.Context, store *Store, ref string) (digest.D
139135 return "" , fmt .Errorf ("getting repository: %w" , err )
140136 }
141137
142- adapter := newStoreAdapter (store )
143- validated := newValidatingTarget (adapter )
138+ validated := newValidatingTarget (store .Target ())
144139
145140 // Copy from remote to the validated local store
146141 desc , err := oras .Copy (
@@ -159,114 +154,6 @@ func (r *Registry) Pull(ctx context.Context, store *Store, ref string) (digest.D
159154 return desc .Digest , nil
160155}
161156
162- // storeAdapter wraps a Store to satisfy ORAS content interfaces,
163- // routing content by media type to the appropriate Store methods.
164- type storeAdapter struct {
165- store * Store
166- }
167-
168- func newStoreAdapter (store * Store ) * storeAdapter {
169- return & storeAdapter {store : store }
170- }
171-
172- // Push routes content to PutManifest or PutBlob based on media type.
173- // Verifies the content digest matches the expected descriptor.
174- func (a * storeAdapter ) Push (ctx context.Context , expected ocispec.Descriptor , content io.Reader ) error {
175- data , err := io .ReadAll (io .LimitReader (content , MaxBlobSize + 1 ))
176- if err != nil {
177- return fmt .Errorf ("reading content: %w" , err )
178- }
179- if int64 (len (data )) > MaxBlobSize {
180- return fmt .Errorf ("content exceeds maximum size of %d bytes" , MaxBlobSize )
181- }
182-
183- // Verify digest integrity
184- actual := digest .FromBytes (data )
185- if actual != expected .Digest {
186- return fmt .Errorf ("digest mismatch: expected %s, got %s" , expected .Digest , actual )
187- }
188-
189- if isManifestMediaType (expected .MediaType ) {
190- _ , err = a .store .PutManifest (ctx , data )
191- } else {
192- _ , err = a .store .PutBlob (ctx , data )
193- }
194- return err
195- }
196-
197- // Fetch retrieves content from the store by descriptor.
198- func (a * storeAdapter ) Fetch (ctx context.Context , target ocispec.Descriptor ) (io.ReadCloser , error ) {
199- var data []byte
200- var err error
201-
202- if isManifestMediaType (target .MediaType ) {
203- data , err = a .store .GetManifest (ctx , target .Digest )
204- } else {
205- data , err = a .store .GetBlob (ctx , target .Digest )
206- }
207- if err != nil {
208- return nil , err
209- }
210- return io .NopCloser (bytes .NewReader (data )), nil
211- }
212-
213- // Exists checks whether content exists in the store.
214- func (a * storeAdapter ) Exists (ctx context.Context , target ocispec.Descriptor ) (bool , error ) {
215- if isManifestMediaType (target .MediaType ) {
216- _ , err := a .store .GetManifest (ctx , target .Digest )
217- if err != nil {
218- if strings .Contains (err .Error (), "not found" ) {
219- return false , nil
220- }
221- return false , err
222- }
223- return true , nil
224- }
225- _ , err := a .store .GetBlob (ctx , target .Digest )
226- if err != nil {
227- if strings .Contains (err .Error (), "not found" ) {
228- return false , nil
229- }
230- return false , err
231- }
232- return true , nil
233- }
234-
235- // Resolve resolves a reference (tag or digest) to a full descriptor.
236- func (a * storeAdapter ) Resolve (ctx context.Context , reference string ) (ocispec.Descriptor , error ) {
237- d , err := a .store .Resolve (ctx , reference )
238- if err != nil {
239- return ocispec.Descriptor {}, err
240- }
241- return a .descriptorFromDigest (ctx , d )
242- }
243-
244- // Tag associates a reference with a descriptor in the store.
245- func (a * storeAdapter ) Tag (ctx context.Context , desc ocispec.Descriptor , reference string ) error {
246- return a .store .Tag (ctx , desc .Digest , reference )
247- }
248-
249- // descriptorFromDigest reads content to build a full OCI descriptor.
250- func (a * storeAdapter ) descriptorFromDigest (ctx context.Context , d digest.Digest ) (ocispec.Descriptor , error ) {
251- data , err := a .store .GetManifest (ctx , d )
252- if err != nil {
253- return ocispec.Descriptor {}, fmt .Errorf ("reading content for descriptor: %w" , err )
254- }
255-
256- var header struct {
257- MediaType string `json:"mediaType"`
258- }
259- if err := json .Unmarshal (data , & header ); err != nil {
260- return ocispec.Descriptor {}, fmt .Errorf ("parsing media type: %w" , err )
261- }
262-
263- return ocispec.Descriptor {
264- MediaType : header .MediaType ,
265- Digest : d ,
266- Size : int64 (len (data )),
267- }, nil
268- }
269-
270157// validatingTarget wraps an oras.Target to enforce size and count limits
271158// on pushed content. This prevents OOM and resource exhaustion from
272159// malicious registries during pull operations.
0 commit comments