diff --git a/cmd/skopeo/sync.go b/cmd/skopeo/sync.go index 161b178c..990c5798 100644 --- a/cmd/skopeo/sync.go +++ b/cmd/skopeo/sync.go @@ -166,7 +166,7 @@ func parseRepositoryReference(input string) (reference.Named, error) { // destinationReference creates an image reference using the provided transport. // It returns a image reference to be used as destination of an image copy and // any error encountered. -func destinationReference(destination string, transport string) (types.ImageReference, error) { +func destinationReference(destination string, transport string, dryRun bool) (types.ImageReference, error) { var imageTransport types.ImageTransport switch transport { @@ -181,9 +181,11 @@ func destinationReference(destination string, transport string) (types.ImageRefe if !os.IsNotExist(err) { return nil, fmt.Errorf("Destination directory could not be used: %w", err) } - // the directory holding the image must be created here - if err = os.MkdirAll(destination, 0755); err != nil { - return nil, fmt.Errorf("Error creating directory for image %s: %w", destination, err) + if !dryRun { + // the directory holding the image must be created here + if err = os.MkdirAll(destination, 0755); err != nil { + return nil, fmt.Errorf("Error creating directory for image %s: %w", destination, err) + } } imageTransport = directory.Transport default: @@ -697,7 +699,7 @@ func (opts *syncOptions) run(args []string, stdout io.Writer) (retErr error) { destSuffix = path.Base(destSuffix) } - destRef, err := destinationReference(path.Join(destination, destSuffix)+opts.appendSuffix, opts.destination) + destRef, err := destinationReference(path.Join(destination, destSuffix)+opts.appendSuffix, opts.destination, opts.dryRun) if err != nil { return err } diff --git a/integration/sync_test.go b/integration/sync_test.go index 4e7a0fd1..79f8694d 100644 --- a/integration/sync_test.go +++ b/integration/sync_test.go @@ -266,6 +266,31 @@ func (s *syncSuite) TestDocker2DirUntagged() { assert.Len(t, nManifests, len(tags)) } +func (s *syncSuite) TestDocker2DirDryRun() { + t := s.T() + tmpDir := t.TempDir() + + // FIXME: It would be nice to use one of the local Docker registries instead of needing an Internet connection. + image := pullableRepo + imageRef, err := docker.ParseReference(fmt.Sprintf("//%s", image)) + require.NoError(t, err) + + require.NoError(t, err) + assertSkopeoSucceeds(t, "", "sync", "--scoped", "--dry-run", "--src", "docker", "--dest", "dir", image, tmpDir) + + sysCtx := types.SystemContext{} + tags, err := docker.GetRepositoryTags(context.Background(), &sysCtx, imageRef) + require.NoError(t, err) + assert.NotZero(t, len(tags)) + + d, err := os.Open(tmpDir) + require.NoError(t, err) + defer d.Close() + nDirEntries, err := d.ReadDir(1) + require.NoError(t, err) + assert.Equal(t, 0, len(nDirEntries)) +} + func (s *syncSuite) TestYamlUntagged() { t := s.T() tmpDir := t.TempDir()