diff --git a/image/store.go b/image/store.go index 302be2f380..1279f59b66 100644 --- a/image/store.go +++ b/image/store.go @@ -231,6 +231,9 @@ func (is *store) SetParent(id, parent ID) error { if parentMeta == nil { return fmt.Errorf("unknown parent image ID %s", parent.String()) } + if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil { + delete(is.images[parent].children, id) + } parentMeta.children[id] = struct{}{} return is.fs.SetMetadata(id, "parent", []byte(parent)) } diff --git a/image/store_test.go b/image/store_test.go index 279708fcba..50f8aa8b84 100644 --- a/image/store_test.go +++ b/image/store_test.go @@ -233,6 +233,62 @@ func TestSearchAfterDelete(t *testing.T) { } } +func TestParentReset(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "images-fs-store") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + fs, err := NewFSStoreBackend(tmpdir) + if err != nil { + t.Fatal(err) + } + + is, err := NewImageStore(fs, &mockLayerGetReleaser{}) + if err != nil { + t.Fatal(err) + } + + id, err := is.Create([]byte(`{"comment": "abc1", "rootfs": {"type": "layers"}}`)) + if err != nil { + t.Fatal(err) + } + + id2, err := is.Create([]byte(`{"comment": "abc2", "rootfs": {"type": "layers"}}`)) + if err != nil { + t.Fatal(err) + } + + id3, err := is.Create([]byte(`{"comment": "abc3", "rootfs": {"type": "layers"}}`)) + if err != nil { + t.Fatal(err) + } + + if err := is.SetParent(id, id2); err != nil { + t.Fatal(err) + } + + ids := is.Children(id2) + if actual, expected := len(ids), 1; expected != actual { + t.Fatalf("wrong number of children: %d, got %d", expected, actual) + } + + if err := is.SetParent(id, id3); err != nil { + t.Fatal(err) + } + + ids = is.Children(id2) + if actual, expected := len(ids), 0; expected != actual { + t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual) + } + + ids = is.Children(id3) + if actual, expected := len(ids), 1; expected != actual { + t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual) + } + +} + type mockLayerGetReleaser struct{} func (ls *mockLayerGetReleaser) Get(layer.ChainID) (layer.Layer, error) {