parent
326f0cfa2f
commit
5c292c61c6
1437 changed files with 208886 additions and 87131 deletions
39
vendor/github.com/containers/image/v5/docker/archive/dest.go
generated
vendored
39
vendor/github.com/containers/image/v5/docker/archive/dest.go
generated
vendored
|
|
@ -3,7 +3,6 @@ package archive
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/containers/image/v5/docker/internal/tarfile"
|
||||
"github.com/containers/image/v5/internal/private"
|
||||
|
|
@ -13,8 +12,8 @@ import (
|
|||
type archiveImageDestination struct {
|
||||
*tarfile.Destination // Implements most of types.ImageDestination
|
||||
ref archiveReference
|
||||
archive *tarfile.Writer // Should only be closed if writer != nil
|
||||
writer io.Closer // May be nil if the archive is shared
|
||||
writer *Writer // Should be closed if closeWriter
|
||||
closeWriter bool
|
||||
}
|
||||
|
||||
func newImageDestination(sys *types.SystemContext, ref archiveReference) (private.ImageDestination, error) {
|
||||
|
|
@ -22,29 +21,28 @@ func newImageDestination(sys *types.SystemContext, ref archiveReference) (privat
|
|||
return nil, fmt.Errorf("Destination reference must not contain a manifest index @%d", ref.sourceIndex)
|
||||
}
|
||||
|
||||
var archive *tarfile.Writer
|
||||
var writer io.Closer
|
||||
if ref.archiveWriter != nil {
|
||||
archive = ref.archiveWriter
|
||||
writer = nil
|
||||
var writer *Writer
|
||||
var closeWriter bool
|
||||
if ref.writer != nil {
|
||||
writer = ref.writer
|
||||
closeWriter = false
|
||||
} else {
|
||||
fh, err := openArchiveForWriting(ref.path)
|
||||
w, err := NewWriter(sys, ref.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
archive = tarfile.NewWriter(fh)
|
||||
writer = fh
|
||||
writer = w
|
||||
closeWriter = true
|
||||
}
|
||||
tarDest := tarfile.NewDestination(sys, archive, ref.Transport().Name(), ref.ref)
|
||||
tarDest := tarfile.NewDestination(sys, writer.archive, ref.Transport().Name(), ref.ref)
|
||||
if sys != nil && sys.DockerArchiveAdditionalTags != nil {
|
||||
tarDest.AddRepoTags(sys.DockerArchiveAdditionalTags)
|
||||
}
|
||||
return &archiveImageDestination{
|
||||
Destination: tarDest,
|
||||
ref: ref,
|
||||
archive: archive,
|
||||
writer: writer,
|
||||
closeWriter: closeWriter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +54,7 @@ func (d *archiveImageDestination) Reference() types.ImageReference {
|
|||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *archiveImageDestination) Close() error {
|
||||
if d.writer != nil {
|
||||
if d.closeWriter {
|
||||
return d.writer.Close()
|
||||
}
|
||||
return nil
|
||||
|
|
@ -70,8 +68,15 @@ func (d *archiveImageDestination) Close() error {
|
|||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *archiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
if d.writer != nil {
|
||||
return d.archive.Close()
|
||||
d.writer.imageCommitted()
|
||||
if d.closeWriter {
|
||||
// We could do this only in .Close(), but failures in .Close() are much more likely to be
|
||||
// ignored by callers that use defer. So, in single-image destinations, try to complete
|
||||
// the archive here.
|
||||
// But if Commit() is never called, let .Close() clean up.
|
||||
err := d.writer.Close()
|
||||
d.closeWriter = false
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/containers/image/v5/docker/archive/src.go
generated
vendored
4
vendor/github.com/containers/image/v5/docker/archive/src.go
generated
vendored
|
|
@ -1,8 +1,6 @@
|
|||
package archive
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v5/docker/internal/tarfile"
|
||||
"github.com/containers/image/v5/internal/private"
|
||||
"github.com/containers/image/v5/types"
|
||||
|
|
@ -15,7 +13,7 @@ type archiveImageSource struct {
|
|||
|
||||
// newImageSource returns a types.ImageSource for the specified image reference.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ctx context.Context, sys *types.SystemContext, ref archiveReference) (private.ImageSource, error) {
|
||||
func newImageSource(sys *types.SystemContext, ref archiveReference) (private.ImageSource, error) {
|
||||
var archive *tarfile.Reader
|
||||
var closeArchive bool
|
||||
if ref.archiveReader != nil {
|
||||
|
|
|
|||
23
vendor/github.com/containers/image/v5/docker/archive/transport.go
generated
vendored
23
vendor/github.com/containers/image/v5/docker/archive/transport.go
generated
vendored
|
|
@ -53,7 +53,7 @@ type archiveReference struct {
|
|||
// file, not necessarily path precisely).
|
||||
archiveReader *tarfile.Reader
|
||||
// If not nil, must have been created for path
|
||||
archiveWriter *tarfile.Writer
|
||||
writer *Writer
|
||||
}
|
||||
|
||||
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an Docker ImageReference.
|
||||
|
|
@ -62,24 +62,23 @@ func ParseReference(refString string) (types.ImageReference, error) {
|
|||
return nil, fmt.Errorf("docker-archive reference %s isn't of the form <path>[:<reference>]", refString)
|
||||
}
|
||||
|
||||
parts := strings.SplitN(refString, ":", 2)
|
||||
path := parts[0]
|
||||
path, tagOrIndex, gotTagOrIndex := strings.Cut(refString, ":")
|
||||
var nt reference.NamedTagged
|
||||
sourceIndex := -1
|
||||
|
||||
if len(parts) == 2 {
|
||||
if gotTagOrIndex {
|
||||
// A :tag or :@index was specified.
|
||||
if len(parts[1]) > 0 && parts[1][0] == '@' {
|
||||
i, err := strconv.Atoi(parts[1][1:])
|
||||
if len(tagOrIndex) > 0 && tagOrIndex[0] == '@' {
|
||||
i, err := strconv.Atoi(tagOrIndex[1:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid source index %s: %w", parts[1], err)
|
||||
return nil, fmt.Errorf("Invalid source index %s: %w", tagOrIndex, err)
|
||||
}
|
||||
if i < 0 {
|
||||
return nil, fmt.Errorf("Invalid source index @%d: must not be negative", i)
|
||||
}
|
||||
sourceIndex = i
|
||||
} else {
|
||||
ref, err := reference.ParseNormalizedNamed(parts[1])
|
||||
ref, err := reference.ParseNormalizedNamed(tagOrIndex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("docker-archive parsing reference: %w", err)
|
||||
}
|
||||
|
|
@ -108,7 +107,7 @@ func NewIndexReference(path string, sourceIndex int) (types.ImageReference, erro
|
|||
// newReference returns a docker archive reference for a path, an optional reference or sourceIndex,
|
||||
// and optionally a tarfile.Reader and/or a tarfile.Writer matching path.
|
||||
func newReference(path string, ref reference.NamedTagged, sourceIndex int,
|
||||
archiveReader *tarfile.Reader, archiveWriter *tarfile.Writer) (types.ImageReference, error) {
|
||||
archiveReader *tarfile.Reader, writer *Writer) (types.ImageReference, error) {
|
||||
if strings.Contains(path, ":") {
|
||||
return nil, fmt.Errorf("Invalid docker-archive: reference: colon in path %q is not supported", path)
|
||||
}
|
||||
|
|
@ -126,7 +125,7 @@ func newReference(path string, ref reference.NamedTagged, sourceIndex int,
|
|||
ref: ref,
|
||||
sourceIndex: sourceIndex,
|
||||
archiveReader: archiveReader,
|
||||
archiveWriter: archiveWriter,
|
||||
writer: writer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +136,7 @@ func (ref archiveReference) Transport() types.ImageTransport {
|
|||
// StringWithinTransport returns a string representation of the reference, which MUST be such that
|
||||
// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference.
|
||||
// NOTE: The returned string is not promised to be equal to the original input to ParseReference;
|
||||
// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
|
||||
// e.g. default attribute values omitted by the user may be filled in the return value, or vice versa.
|
||||
// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix.
|
||||
func (ref archiveReference) StringWithinTransport() string {
|
||||
switch {
|
||||
|
|
@ -191,7 +190,7 @@ func (ref archiveReference) NewImage(ctx context.Context, sys *types.SystemConte
|
|||
// NewImageSource returns a types.ImageSource for this reference.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref archiveReference) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
|
||||
return newImageSource(ctx, sys, ref)
|
||||
return newImageSource(sys, ref)
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
|
|
|
|||
98
vendor/github.com/containers/image/v5/docker/archive/writer.go
generated
vendored
98
vendor/github.com/containers/image/v5/docker/archive/writer.go
generated
vendored
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/image/v5/docker/internal/tarfile"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
|
|
@ -13,47 +14,19 @@ import (
|
|||
|
||||
// Writer manages a single in-progress Docker archive and allows adding images to it.
|
||||
type Writer struct {
|
||||
path string // The original, user-specified path; not the maintained temporary file, if any
|
||||
archive *tarfile.Writer
|
||||
writer io.Closer
|
||||
path string // The original, user-specified path; not the maintained temporary file, if any
|
||||
regularFile bool // path refers to a regular file (e.g. not a pipe)
|
||||
archive *tarfile.Writer
|
||||
writer io.Closer
|
||||
|
||||
// The following state can only be accessed with the mutex held.
|
||||
mutex sync.Mutex
|
||||
hadCommit bool // At least one successful commit has happened
|
||||
}
|
||||
|
||||
// NewWriter returns a Writer for path.
|
||||
// The caller should call .Close() on the returned object.
|
||||
func NewWriter(sys *types.SystemContext, path string) (*Writer, error) {
|
||||
fh, err := openArchiveForWriting(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
archive := tarfile.NewWriter(fh)
|
||||
|
||||
return &Writer{
|
||||
path: path,
|
||||
archive: archive,
|
||||
writer: fh,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close writes all outstanding data about images to the archive, and
|
||||
// releases state associated with the Writer, if any.
|
||||
// No more images can be added after this is called.
|
||||
func (w *Writer) Close() error {
|
||||
err := w.archive.Close()
|
||||
if err2 := w.writer.Close(); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewReference returns an ImageReference that allows adding an image to Writer,
|
||||
// with an optional reference.
|
||||
func (w *Writer) NewReference(destinationRef reference.NamedTagged) (types.ImageReference, error) {
|
||||
return newReference(w.path, destinationRef, -1, nil, w.archive)
|
||||
}
|
||||
|
||||
// openArchiveForWriting opens path for writing a tar archive,
|
||||
// making a few sanity checks.
|
||||
func openArchiveForWriting(path string) (*os.File, error) {
|
||||
// path can be either a pipe or a regular file
|
||||
// in the case of a pipe, we require that we can open it for write
|
||||
// in the case of a regular file, we don't want to overwrite any pre-existing file
|
||||
|
|
@ -69,15 +42,62 @@ func openArchiveForWriting(path string) (*os.File, error) {
|
|||
fh.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
fhStat, err := fh.Stat()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("statting file %q: %w", path, err)
|
||||
}
|
||||
|
||||
if fhStat.Mode().IsRegular() && fhStat.Size() != 0 {
|
||||
regularFile := fhStat.Mode().IsRegular()
|
||||
if regularFile && fhStat.Size() != 0 {
|
||||
return nil, errors.New("docker-archive doesn't support modifying existing images")
|
||||
}
|
||||
|
||||
archive := tarfile.NewWriter(fh)
|
||||
|
||||
succeeded = true
|
||||
return fh, nil
|
||||
return &Writer{
|
||||
path: path,
|
||||
regularFile: regularFile,
|
||||
archive: archive,
|
||||
writer: fh,
|
||||
hadCommit: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// imageCommitted notifies the Writer that at least one image was successfully committed to the stream.
|
||||
func (w *Writer) imageCommitted() {
|
||||
w.mutex.Lock()
|
||||
defer w.mutex.Unlock()
|
||||
w.hadCommit = true
|
||||
}
|
||||
|
||||
// Close writes all outstanding data about images to the archive, and
|
||||
// releases state associated with the Writer, if any.
|
||||
// No more images can be added after this is called.
|
||||
func (w *Writer) Close() error {
|
||||
err := w.archive.Close()
|
||||
if err2 := w.writer.Close(); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
if err == nil && w.regularFile && !w.hadCommit {
|
||||
// Writing to the destination never had a success; delete the destination if we created it.
|
||||
// This is done primarily because we don’t implement adding another image to a pre-existing image, so if we
|
||||
// left a partial archive around (notably because reading from the _source_ has failed), we couldn’t retry without
|
||||
// the caller manually deleting the partial archive. So, delete it instead.
|
||||
//
|
||||
// Archives with at least one successfully created image are left around; they might still be valuable.
|
||||
//
|
||||
// Note a corner case: If there _originally_ was an empty file (which is not a valid archive anyway), this deletes it.
|
||||
// Ideally, if w.regularFile, we should write the full contents to a temporary file and use os.Rename here, only on success.
|
||||
if err2 := os.Remove(w.path); err2 != nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewReference returns an ImageReference that allows adding an image to Writer,
|
||||
// with an optional reference.
|
||||
func (w *Writer) NewReference(destinationRef reference.NamedTagged) (types.ImageReference, error) {
|
||||
return newReference(w.path, destinationRef, -1, nil, w)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue