From 3ce066a91a56cd715f3f89f40ac23bba3a7ba486 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Thu, 30 Jan 2020 15:31:55 -0800 Subject: [PATCH] Add DeepCopy function to Blueprint struct The Blueprint struct is complex, deep, and full of references. This means that any changes to it in memory will persist. Sometimes you need an actual copy of it, so this adds DeepCopy which uses the json.Marshal and Unmarshal functions to create a deep copy with no references to the original. This is not very efficient, but the alternative is adding Copy functions to all the member structs and then calling them to build the copy. --- internal/blueprint/blueprint.go | 20 +++++++++++++++ internal/blueprint/blueprint_test.go | 38 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 internal/blueprint/blueprint_test.go diff --git a/internal/blueprint/blueprint.go b/internal/blueprint/blueprint.go index 6c70731fb..dbe392371 100644 --- a/internal/blueprint/blueprint.go +++ b/internal/blueprint/blueprint.go @@ -1,6 +1,10 @@ // Package blueprint contains primitives for representing weldr blueprints package blueprint +import ( + "encoding/json" +) + // A Blueprint is a high-level description of an image. type Blueprint struct { Name string `json:"name" toml:"name"` @@ -31,6 +35,22 @@ type Group struct { Name string `json:"name" toml:"name"` } +// DeepCopy returns a deep copy of the blueprint +// This uses json.Marshal and Unmarshal which are not very efficient +func (b *Blueprint) DeepCopy() (Blueprint, error) { + bpJSON, err := json.Marshal(b) + if err != nil { + return Blueprint{}, err + } + + var bp Blueprint + err = json.Unmarshal(bpJSON, &bp) + if err != nil { + return Blueprint{}, err + } + return bp, nil +} + // packages, modules, and groups all resolve to rpm packages right now. This // function returns a combined list of "name-version" strings. func (b *Blueprint) GetPackages() []string { diff --git a/internal/blueprint/blueprint_test.go b/internal/blueprint/blueprint_test.go new file mode 100644 index 000000000..76b663448 --- /dev/null +++ b/internal/blueprint/blueprint_test.go @@ -0,0 +1,38 @@ +package blueprint + +import ( + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestDeepCopy(t *testing.T) { + bpOrig := Blueprint{ + Name: "deepcopy-test", + Description: "Testing DeepCopy function", + Version: "0.0.1", + Packages: []Package{ + {Name: "dep-package1", Version: "*"}}, + Modules: []Package{ + {Name: "dep-package2", Version: "*"}}, + } + + bpCopy, err := bpOrig.DeepCopy() + if err != nil { + t.Fatalf("Blueprint.DeepCopy failure: %s", err.Error()) + } + if diff := cmp.Diff(bpOrig, bpCopy); diff != "" { + t.Fatalf("Blueprint.DeepCopy is different from original\ndiff: %s", diff) + } + + // Modify the copy + bpCopy.Packages[0].Version = "1.2.3" + if bpOrig.Packages[0].Version != "*" { + t.Fatalf("Blueprint.DeepCopy failed, original modified") + } + + // Modify the original + bpOrig.Packages[0].Version = "42.0" + if bpCopy.Packages[0].Version != "1.2.3" { + t.Fatalf("Blueprint.DeepCopy failed, copy modified") + } +}