Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ociarchive: Add new ArchiveFileNotFoundError #2123

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions oci/archive/oci_src.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ func (e ImageNotFoundError) Error() string {
return fmt.Sprintf("no descriptor found for reference %q", e.ref.image)
}

// ArchiveFileNotFoundError occurs when the archive file does not exist.
type ArchiveFileNotFoundError struct {
// ref is the image reference
ref ociArchiveReference
// path is the file path that was not present
path string
}

func (e ArchiveFileNotFoundError) Error() string {
return fmt.Sprintf("archive file not found: %q", e.path)
}

type ociArchiveImageSource struct {
impl.Compat

Expand Down
23 changes: 22 additions & 1 deletion oci/archive/oci_src_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
package archive

import "github.com/containers/image/v5/internal/private"
import (
"path/filepath"
"testing"

"github.com/containers/image/v5/internal/private"
"github.com/containers/image/v5/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var _ private.ImageSource = (*ociArchiveImageSource)(nil)

func TestNewImageSourceNotFound(t *testing.T) {
sysctx := types.SystemContext{}
emptyDir := t.TempDir()
archivePath := filepath.Join(emptyDir, "foo.ociarchive")
imgref, err := ParseReference(archivePath)
require.NoError(t, err)
_, err = LoadManifestDescriptorWithContext(&sysctx, imgref)
assert.NotNil(t, err)
var aerr ArchiveFileNotFoundError
assert.ErrorAs(t, err, &aerr)
assert.Equal(t, aerr.path, archivePath)
}
19 changes: 13 additions & 6 deletions oci/archive/oci_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"strings"

Expand Down Expand Up @@ -171,18 +172,24 @@ func createOCIRef(sys *types.SystemContext, image string) (tempDirOCIRef, error)

// creates the temporary directory and copies the tarred content to it
func createUntarTempDir(sys *types.SystemContext, ref ociArchiveReference) (tempDirOCIRef, error) {
src := ref.resolvedFile
arch, err := os.Open(src)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return tempDirOCIRef{}, ArchiveFileNotFoundError{ref: ref, path: src}
} else {
return tempDirOCIRef{}, err
}
}
defer arch.Close()

tempDirRef, err := createOCIRef(sys, ref.image)
if err != nil {
return tempDirOCIRef{}, fmt.Errorf("creating oci reference: %w", err)
}
src := ref.resolvedFile
dst := tempDirRef.tempDirectory

// TODO: This can take quite some time, and should ideally be cancellable using a context.Context.
arch, err := os.Open(src)
if err != nil {
return tempDirOCIRef{}, err
}
defer arch.Close()
if err := archive.NewDefaultArchiver().Untar(arch, dst, &archive.TarOptions{NoLchown: true}); err != nil {
if err := tempDirRef.deleteTempDir(); err != nil {
return tempDirOCIRef{}, fmt.Errorf("deleting temp directory %q: %w", tempDirRef.tempDirectory, err)
Expand Down