From 121e1f3ddc5764ddfb792c317bcd06219769d2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Vl=C3=A9rick?= Date: Sat, 24 Jun 2023 15:27:05 +0200 Subject: [PATCH] Implementing the shared blob case logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Vlérick --- oci/layout/oci_transport.go | 39 ++++++++++++++++++++++++-------- oci/layout/oci_transport_test.go | 2 +- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/oci/layout/oci_transport.go b/oci/layout/oci_transport.go index 653e35128c..1a7c791262 100644 --- a/oci/layout/oci_transport.go +++ b/oci/layout/oci_transport.go @@ -249,19 +249,43 @@ func (ref ociReference) NewImageDestination(ctx context.Context, sys *types.Syst func (ref ociReference) DeleteImage(ctx context.Context, sys *types.SystemContext) error { // Get the manifest for the image - descriptor, err := ref.getManifestDescriptor() + manifestDescriptor, err := ref.getManifestDescriptor() if err != nil { return err } - manifest, err := ref.getManifest(descriptor) + manifest, err := ref.getManifest(manifestDescriptor) if err != nil { return err } + // Get all the layers used by all other images + index, err := ref.getIndex() + if err != nil { + return err + } + layersUsedByOtherImages := make(map[digest.Digest]bool, len(index.Manifests)) + for _, v := range index.Manifests { + if v.Digest != manifestDescriptor.Digest { + otherImageManifest, err := ref.getManifest(v) + if err != nil { + return err + } + for _, layer := range otherImageManifest.Layers { + layersUsedByOtherImages[layer.Digest] = true + } + } + } + // Delete all blobs - for _, d := range append(manifest.Layers, manifest.Config, descriptor) { - blobPath, err := ref.blobPath(d.Digest, "") + blobsToDelete := make([]digest.Digest, 0, len(manifest.Layers)) + for _, layer := range manifest.Layers { + if !layersUsedByOtherImages[layer.Digest] { + blobsToDelete = append(blobsToDelete, layer.Digest) + } + } + for _, digest := range append(blobsToDelete, manifest.Config.Digest, manifestDescriptor.Digest) { + blobPath, err := ref.blobPath(digest, "") if err != nil { return err } @@ -272,14 +296,9 @@ func (ref ociReference) DeleteImage(ctx context.Context, sys *types.SystemContex } // Update the index - index, err := ref.getIndex() - if err != nil { - return err - } - newManifests := make([]imgspecv1.Descriptor, 0, len(index.Manifests)-1) for _, v := range index.Manifests { - if v.Digest != descriptor.Digest { + if v.Digest != manifestDescriptor.Digest { newManifests = append(newManifests, v) } } diff --git a/oci/layout/oci_transport_test.go b/oci/layout/oci_transport_test.go index c3587c7d8a..eb699dd8fa 100644 --- a/oci/layout/oci_transport_test.go +++ b/oci/layout/oci_transport_test.go @@ -576,7 +576,7 @@ func TestReferenceDeleteImage_someLayersAreReferencedByOtherImages(t *testing.T) blobDoesNotExist(t, blobsDir, image.layers[0]) blobDoesNotExist(t, blobsDir, image.layers[2]) - // Check that the blob used by another image is still there + // Check that the blob used by another image was not deleted commonBlobDigest, err := digest.Parse(commonLayer) require.NoError(t, err) _, err = os.Stat(filepath.Join(blobsDir, commonBlobDigest.Algorithm().String(), commonBlobDigest.Hex()))