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.
This commit is contained in:
Brian C. Lane 2020-01-30 15:31:55 -08:00 committed by Tom Gundersen
parent a84593645b
commit 3ce066a91a
2 changed files with 58 additions and 0 deletions

View file

@ -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 {

View file

@ -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")
}
}