github.com/paketo-buildpacks/libpak/v2@v2.0.0-alpha.3.0.20231023030503-8365f81de65a/buildpack_plan.go (about) 1 /* 2 * Copyright 2018-2020 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libpak 18 19 import ( 20 "fmt" 21 "reflect" 22 23 "dario.cat/mergo" 24 "github.com/buildpacks/libcnb/v2" 25 ) 26 27 // PlanEntryResolver provides functionality for resolving a Buildpack Plan Entry given a name. 28 type PlanEntryResolver struct { 29 30 // Plan is the BuildpackPlan to resolve against. 31 Plan libcnb.BuildpackPlan 32 } 33 34 // MergeFunc takes two BuildpackPlanEntry's and returns a merged entry. 35 type MergeFunc func(a, b libcnb.BuildpackPlanEntry) (libcnb.BuildpackPlanEntry, error) 36 37 // ResolveWithMerge returns a single BuildpackPlanEntry that is a merged version of all entries that have a given name. 38 // A merge function is used to describe how two entries are merged together. 39 func (p *PlanEntryResolver) ResolveWithMerge(name string, f MergeFunc) (libcnb.BuildpackPlanEntry, bool, error) { 40 m := libcnb.BuildpackPlanEntry{} 41 42 var err error 43 for _, e := range p.Plan.Entries { 44 if e.Name == name { 45 if m, err = f(m, e); err != nil { 46 return libcnb.BuildpackPlanEntry{}, false, fmt.Errorf("error merging %+v and %+v\n%w", m, e, err) 47 } 48 } 49 } 50 51 if reflect.DeepEqual(m, libcnb.BuildpackPlanEntry{}) { 52 return libcnb.BuildpackPlanEntry{}, false, nil 53 } 54 55 return m, true, nil 56 } 57 58 // ShallowMerge merges two BuildpackPlanEntry's together. Declared versions are combined with a comma delimiter and 59 // metadata is combined with the values for b taking priority over the values of a when the keys are duplicated. 60 func ShallowMerge(a, b libcnb.BuildpackPlanEntry) (libcnb.BuildpackPlanEntry, error) { 61 if err := mergo.Merge(&b, a); err != nil { 62 return libcnb.BuildpackPlanEntry{}, fmt.Errorf("unable to merge %+v and %+v\n%w", a, b, err) 63 } 64 65 return b, nil 66 } 67 68 // Resolve calls ResolveWithMerge function passing in the ShallowMerge function as the merge strategy. 69 func (p *PlanEntryResolver) Resolve(name string) (libcnb.BuildpackPlanEntry, bool, error) { 70 return p.ResolveWithMerge(name, ShallowMerge) 71 }