From 94805254ef1eb24b7e7cea46eec5841f0924d4d0 Mon Sep 17 00:00:00 2001 From: "Clarence \"Sparr\" Risher" Date: Sun, 25 Jun 2023 09:16:38 -0400 Subject: [PATCH] fix(oci): create blobs dir and define blobs dir name constant (#520) https://github.com/opencontainers/image-spec/blob/v1.0/image-layout.md#content specifies that the blobs dir must exist, so the changed ensureDir in this PR is a bugfix. The addition and use of the ociBlobsDir constant is more of a cleanup suggestion, and I can remove it if necessary. I've also asked for it to be added upstream at https://github.com/opencontainers/image-spec/issues/1069 but that will probably take significantly longer. Signed-off-by: Clarence "Sparr" Risher --- content/oci/oci.go | 7 ++++++- content/oci/readonlyoci_test.go | 6 +++--- content/oci/readonlystorage.go | 2 +- content/oci/readonlystorage_test.go | 6 +++--- content/oci/storage_test.go | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/content/oci/oci.go b/content/oci/oci.go index a473e5c1..cf9c3f21 100644 --- a/content/oci/oci.go +++ b/content/oci/oci.go @@ -43,6 +43,11 @@ import ( // Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/image-layout.md#indexjson-file const ociImageIndexFile = "index.json" +// ociBlobsDir is the name of the blobs directory +// from the OCI Image Layout Specification. +// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/image-layout.md#content +const ociBlobsDir = "blobs" + // Store implements `oras.Target`, and represents a content store // based on file system with the OCI-Image layout. // Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/image-layout.md @@ -90,7 +95,7 @@ func NewWithContext(ctx context.Context, root string) (*Store, error) { graph: graph.NewMemory(), } - if err := ensureDir(rootAbs); err != nil { + if err := ensureDir(filepath.Join(rootAbs, ociBlobsDir)); err != nil { return nil, err } if err := store.ensureOCILayoutFile(); err != nil { diff --git a/content/oci/readonlyoci_test.go b/content/oci/readonlyoci_test.go index 346c126f..fdc0cde3 100644 --- a/content/oci/readonlyoci_test.go +++ b/content/oci/readonlyoci_test.go @@ -123,7 +123,7 @@ func TestReadOnlyStore(t *testing.T) { // build fs fsys := fstest.MapFS{} for i, desc := range descs { - path := strings.Join([]string{"blobs", desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") + path := strings.Join([]string{ociBlobsDir, desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") fsys[path] = &fstest.MapFile{Data: blobs[i]} } fsys[ocispec.ImageLayoutFile] = &fstest.MapFile{Data: layoutJSON} @@ -603,7 +603,7 @@ func TestReadOnlyStore_Copy_OCIToMemory(t *testing.T) { // build fs fsys := fstest.MapFS{} for i, desc := range descs { - path := strings.Join([]string{"blobs", desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") + path := strings.Join([]string{ociBlobsDir, desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") fsys[path] = &fstest.MapFile{Data: blobs[i]} } fsys[ocispec.ImageLayoutFile] = &fstest.MapFile{Data: layoutJSON} @@ -717,7 +717,7 @@ func TestReadOnlyStore_Tags(t *testing.T) { // build fs fsys := fstest.MapFS{} for i, desc := range descs { - path := strings.Join([]string{"blobs", desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") + path := strings.Join([]string{ociBlobsDir, desc.Digest.Algorithm().String(), desc.Digest.Encoded()}, "/") fsys[path] = &fstest.MapFile{Data: blobs[i]} } fsys[ocispec.ImageLayoutFile] = &fstest.MapFile{Data: layoutJSON} diff --git a/content/oci/readonlystorage.go b/content/oci/readonlystorage.go index 8a5b39c5..3cab94fa 100644 --- a/content/oci/readonlystorage.go +++ b/content/oci/readonlystorage.go @@ -95,5 +95,5 @@ func blobPath(dgst digest.Digest) (string, error) { return "", fmt.Errorf("cannot calculate blob path from invalid digest %s: %w: %v", dgst.String(), errdef.ErrInvalidDigest, err) } - return path.Join("blobs", dgst.Algorithm().String(), dgst.Encoded()), nil + return path.Join(ociBlobsDir, dgst.Algorithm().String(), dgst.Encoded()), nil } diff --git a/content/oci/readonlystorage_test.go b/content/oci/readonlystorage_test.go index b1d1906a..d7b4f176 100644 --- a/content/oci/readonlystorage_test.go +++ b/content/oci/readonlystorage_test.go @@ -38,7 +38,7 @@ func TestReadOnlyStorage_Exists(t *testing.T) { dgst := digest.FromBytes(blob) desc := content.NewDescriptorFromBytes("", blob) fsys := fstest.MapFS{ - strings.Join([]string{"blobs", dgst.Algorithm().String(), dgst.Encoded()}, "/"): {}, + strings.Join([]string{ociBlobsDir, dgst.Algorithm().String(), dgst.Encoded()}, "/"): {}, } s := NewStorageFromFS(fsys) ctx := context.Background() @@ -76,7 +76,7 @@ func TestReadOnlyStorage_Fetch(t *testing.T) { dgst := digest.FromBytes(blob) desc := content.NewDescriptorFromBytes("", blob) fsys := fstest.MapFS{ - strings.Join([]string{"blobs", dgst.Algorithm().String(), dgst.Encoded()}, "/"): { + strings.Join([]string{ociBlobsDir, dgst.Algorithm().String(), dgst.Encoded()}, "/"): { Data: blob, }, } @@ -123,7 +123,7 @@ func TestReadOnlyStorage_DirFS(t *testing.T) { dgst := digest.FromBytes(blob) desc := content.NewDescriptorFromBytes("test", blob) // write blob to disk - path := filepath.Join(tempDir, "blobs", dgst.Algorithm().String(), dgst.Encoded()) + path := filepath.Join(tempDir, ociBlobsDir, dgst.Algorithm().String(), dgst.Encoded()) if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { t.Fatal("error calling Mkdir(), error =", err) } diff --git a/content/oci/storage_test.go b/content/oci/storage_test.go index 7e3b1e58..ac6ae8dd 100644 --- a/content/oci/storage_test.go +++ b/content/oci/storage_test.go @@ -289,7 +289,7 @@ func TestStorage_Fetch_ExistingBlobs(t *testing.T) { } tempDir := t.TempDir() - path := filepath.Join(tempDir, "blobs", dgst.Algorithm().String(), dgst.Encoded()) + path := filepath.Join(tempDir, ociBlobsDir, dgst.Algorithm().String(), dgst.Encoded()) if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { t.Fatal("error calling Mkdir(), error =", err) }