Browse Source

Fix multiple copy from

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 years ago
parent
commit
b50ade0bfb
3 changed files with 50 additions and 2 deletions
  1. 5 2
      image/image.go
  2. 37 0
      image/image_test.go
  3. 8 0
      image/rootfs.go

+ 5 - 2
image/image.go

@@ -137,10 +137,13 @@ type ChildConfig struct {
 // NewChildImage creates a new Image as a child of this image.
 // NewChildImage creates a new Image as a child of this image.
 func NewChildImage(img *Image, child ChildConfig, platform string) *Image {
 func NewChildImage(img *Image, child ChildConfig, platform string) *Image {
 	isEmptyLayer := layer.IsEmpty(child.DiffID)
 	isEmptyLayer := layer.IsEmpty(child.DiffID)
-	rootFS := img.RootFS
-	if rootFS == nil {
+	var rootFS *RootFS
+	if img.RootFS != nil {
+		rootFS = img.RootFS.Clone()
+	} else {
 		rootFS = NewRootFS()
 		rootFS = NewRootFS()
 	}
 	}
+
 	if !isEmptyLayer {
 	if !isEmptyLayer {
 		rootFS.Append(child.DiffID)
 		rootFS.Append(child.DiffID)
 	}
 	}

+ 37 - 0
image/image_test.go

@@ -6,6 +6,8 @@ import (
 	"strings"
 	"strings"
 	"testing"
 	"testing"
 
 
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/layer"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/require"
 )
 )
@@ -51,3 +53,38 @@ func TestMarshalKeyOrder(t *testing.T) {
 		t.Fatal("invalid key order in JSON: ", string(b))
 		t.Fatal("invalid key order in JSON: ", string(b))
 	}
 	}
 }
 }
+
+func TestNewChildImageFromImageWithRootFS(t *testing.T) {
+	rootFS := NewRootFS()
+	rootFS.Append(layer.DiffID("ba5e"))
+	parent := &Image{
+		RootFS: rootFS,
+		History: []History{
+			NewHistory("a", "c", "r", false),
+		},
+	}
+	childConfig := ChildConfig{
+		DiffID:  layer.DiffID("abcdef"),
+		Author:  "author",
+		Comment: "comment",
+		ContainerConfig: &container.Config{
+			Cmd: []string{"echo", "foo"},
+		},
+		Config: &container.Config{},
+	}
+
+	newImage := NewChildImage(parent, childConfig, "platform")
+	expectedDiffIDs := []layer.DiffID{layer.DiffID("ba5e"), layer.DiffID("abcdef")}
+	assert.Equal(t, expectedDiffIDs, newImage.RootFS.DiffIDs)
+	assert.Equal(t, childConfig.Author, newImage.Author)
+	assert.Equal(t, childConfig.Config, newImage.Config)
+	assert.Equal(t, *childConfig.ContainerConfig, newImage.ContainerConfig)
+	assert.Equal(t, "platform", newImage.OS)
+	assert.Equal(t, childConfig.Config, newImage.Config)
+
+	assert.Len(t, newImage.History, 2)
+	assert.Equal(t, childConfig.Comment, newImage.History[1].Comment)
+
+	// RootFS should be copied not mutated
+	assert.NotEqual(t, parent.RootFS.DiffIDs, newImage.RootFS.DiffIDs)
+}

+ 8 - 0
image/rootfs.go

@@ -34,6 +34,14 @@ func (r *RootFS) Append(id layer.DiffID) {
 	r.DiffIDs = append(r.DiffIDs, id)
 	r.DiffIDs = append(r.DiffIDs, id)
 }
 }
 
 
+// Clone returns a copy of the RootFS
+func (r *RootFS) Clone() *RootFS {
+	newRoot := NewRootFS()
+	newRoot.Type = r.Type
+	newRoot.DiffIDs = append(r.DiffIDs)
+	return newRoot
+}
+
 // ChainID returns the ChainID for the top layer in RootFS.
 // ChainID returns the ChainID for the top layer in RootFS.
 func (r *RootFS) ChainID() layer.ChainID {
 func (r *RootFS) ChainID() layer.ChainID {
 	if runtime.GOOS == "windows" && r.Type == typeLayersWithBase {
 	if runtime.GOOS == "windows" && r.Type == typeLayersWithBase {