@@ -928,11 +928,103 @@ func (s *manifestStore) Exists(ctx context.Context, target ocispec.Descriptor) (
928
928
return false , err
929
929
}
930
930
931
- // Delete removes the content identified by the descriptor.
931
+ // Delete removes the manifest content identified by the descriptor.
932
932
func (s * manifestStore ) Delete (ctx context.Context , target ocispec.Descriptor ) error {
933
+ return s .deleteWithIndexing (ctx , target )
934
+ }
935
+
936
+ // deleteWithIndexing removes the manifest content identified by the descriptor,
937
+ // and indexes referrers for the manifest when needed.
938
+ func (s * manifestStore ) deleteWithIndexing (ctx context.Context , target ocispec.Descriptor ) error {
939
+ if target .MediaType == ocispec .MediaTypeArtifactManifest || target .MediaType == ocispec .MediaTypeImageManifest {
940
+ if state := s .repo .loadReferrersState (); state == referrersStateSupported {
941
+ // referrers API is available, no client-side indexing needed
942
+ return s .repo .delete (ctx , target , true )
943
+ }
944
+
945
+ if err := limitSize (target , s .repo .MaxMetadataBytes ); err != nil {
946
+ return err
947
+ }
948
+ manifestJSON , err := content .FetchAll (ctx , s , target )
949
+ if err != nil {
950
+ return err
951
+ }
952
+ if err := s .indexReferrersForDelete (ctx , target , manifestJSON ); err != nil {
953
+ return err
954
+ }
955
+ }
956
+
933
957
return s .repo .delete (ctx , target , true )
934
958
}
935
959
960
+ // indexReferrersForDelete indexes referrers for image or artifact manifest with
961
+ // the subject field on manifest delete.
962
+ // Reference: https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-manifests
963
+ func (s * manifestStore ) indexReferrersForDelete (ctx context.Context , desc ocispec.Descriptor , manifestJSON []byte ) error {
964
+ var manifest struct {
965
+ Subject * ocispec.Descriptor `json:"subject"`
966
+ }
967
+ if err := json .Unmarshal (manifestJSON , & manifest ); err != nil {
968
+ return fmt .Errorf ("failed to decode manifest: %s: %s: %w" , desc .Digest , desc .MediaType , err )
969
+ }
970
+ if manifest .Subject == nil {
971
+ // no subject, no indexing needed
972
+ return nil
973
+ }
974
+
975
+ subject := * manifest .Subject
976
+ yes , err := s .repo .isReferrersAPIAvailable (ctx , subject )
977
+ if err != nil {
978
+ return err
979
+ }
980
+ if yes {
981
+ // referrers API is available, no client-side indexing needed
982
+ return nil
983
+ }
984
+ return s .updateReferrersIndexForDelete (ctx , desc , subject )
985
+ }
986
+
987
+ // updateReferrersIndexForDelete updates the referrers index for desc referencing
988
+ // subject on manifest delete.
989
+ func (s * manifestStore ) updateReferrersIndexForDelete (ctx context.Context , desc , subject ocispec.Descriptor ) error {
990
+ // there can be multiple go-routines updating the referrers tag concurrently
991
+ referrersTag := buildReferrersTag (subject )
992
+ s .repo .lockReferrersTag (referrersTag )
993
+ defer s .repo .unlockReferrersTag (referrersTag )
994
+
995
+ oldIndexDesc , referrers , err := s .repo .referrersFromIndex (ctx , referrersTag )
996
+ if err != nil {
997
+ if errors .Is (err , errdef .ErrNotFound ) {
998
+ // inconsistent indexing state: no old index found, skip update
999
+ return nil
1000
+ }
1001
+ return err
1002
+ }
1003
+ if len (referrers ) == 0 {
1004
+ // inconsistent indexing state: no referrers to the subject, skip update
1005
+ return nil
1006
+ }
1007
+
1008
+ var updatedReferrers []ocispec.Descriptor
1009
+ for _ , r := range referrers {
1010
+ // remove the current entry
1011
+ if ! content .Equal (r , desc ) {
1012
+ updatedReferrers = append (updatedReferrers , r )
1013
+ }
1014
+ }
1015
+ if len (updatedReferrers ) > 0 {
1016
+ newIndexDesc , newIndex , err := generateIndex (updatedReferrers )
1017
+ if err != nil {
1018
+ return fmt .Errorf ("failed to generate referrers index for referrers tag %s: %w" , referrersTag , err )
1019
+ }
1020
+ if err := s .push (ctx , newIndexDesc , bytes .NewReader (newIndex ), referrersTag ); err != nil {
1021
+ return fmt .Errorf ("failed to push referrers index tagged by %s: %w" , referrersTag , err )
1022
+ }
1023
+ }
1024
+
1025
+ return s .repo .delete (ctx , oldIndexDesc , true )
1026
+ }
1027
+
936
1028
// Resolve resolves a reference to a descriptor.
937
1029
// See also `ManifestMediaTypes`.
938
1030
func (s * manifestStore ) Resolve (ctx context.Context , reference string ) (ocispec.Descriptor , error ) {
@@ -1106,16 +1198,16 @@ func (s *manifestStore) pushWithIndexing(ctx context.Context, expected ocispec.D
1106
1198
if err := s .push (ctx , expected , bytes .NewReader (manifestJSON ), reference ); err != nil {
1107
1199
return err
1108
1200
}
1109
- return s .indexReferrers (ctx , expected , manifestJSON )
1201
+ return s .indexReferrersForPush (ctx , expected , manifestJSON )
1110
1202
default :
1111
1203
return s .push (ctx , expected , r , reference )
1112
1204
}
1113
1205
}
1114
1206
1115
- // indexReferrers indexes referrers for image or artifact manifest with
1116
- // the subject field.
1207
+ // indexReferrersForPush indexes referrers for image or artifact manifest with
1208
+ // the subject field on manifest push .
1117
1209
// Reference: https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-manifests-with-subject
1118
- func (s * manifestStore ) indexReferrers (ctx context.Context , desc ocispec.Descriptor , manifestJSON []byte ) error {
1210
+ func (s * manifestStore ) indexReferrersForPush (ctx context.Context , desc ocispec.Descriptor , manifestJSON []byte ) error {
1119
1211
var subject ocispec.Descriptor
1120
1212
switch desc .MediaType {
1121
1213
case ocispec .MediaTypeArtifactManifest :
@@ -1154,11 +1246,12 @@ func (s *manifestStore) indexReferrers(ctx context.Context, desc ocispec.Descrip
1154
1246
// referrers API is available, no client-side indexing needed
1155
1247
return nil
1156
1248
}
1157
- return s .updateReferrersIndex (ctx , desc , subject )
1249
+ return s .updateReferrersIndexForPush (ctx , desc , subject )
1158
1250
}
1159
1251
1160
- // updateReferrersIndex updates the referrers index for desc referencing subject.
1161
- func (s * manifestStore ) updateReferrersIndex (ctx context.Context , desc , subject ocispec.Descriptor ) error {
1252
+ // updateReferrersIndexForPush updates the referrers index for desc referencing
1253
+ // subject on manifest push.
1254
+ func (s * manifestStore ) updateReferrersIndexForPush (ctx context.Context , desc , subject ocispec.Descriptor ) error {
1162
1255
// there can be multiple go-routines updating the referrers tag concurrently
1163
1256
referrersTag := buildReferrersTag (subject )
1164
1257
s .repo .lockReferrersTag (referrersTag )
0 commit comments