github.com/YousefHaggyHeroku/pack@v1.5.5/internal/stack/merge.go (about) 1 package stack 2 3 import ( 4 "sort" 5 6 "github.com/YousefHaggyHeroku/pack/internal/dist" 7 "github.com/YousefHaggyHeroku/pack/internal/stringset" 8 ) 9 10 // MergeCompatible determines the allowable set of stacks that a combination of buildpacks may run on, given each 11 // buildpack's set of stacks. Compatibility between the two sets of buildpack stacks is defined by the following rules: 12 // 13 // 1. The stack must be supported by both buildpacks. That is, any resulting stack ID must appear in both input sets. 14 // 2. For each supported stack ID, all required mixins for all buildpacks must be provided by the result. That is, 15 // mixins for the stack ID in both input sets are unioned. 16 // 17 // --- 18 // 19 // Examples: 20 // 21 // stacksA = [{ID: "stack1", mixins: ["build:mixinA", "mixinB", "run:mixinC"]}}] 22 // stacksB = [{ID: "stack1", mixins: ["build:mixinA", "run:mixinC"]}}] 23 // result = [{ID: "stack1", mixins: ["build:mixinA", "mixinB", "run:mixinC"]}}] 24 // 25 // stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}, {ID: "stack2", mixins: ["mixinA"]}}] 26 // stacksB = [{ID: "stack1", mixins: ["run:mixinC"]}}, {ID: "stack2", mixins: ["mixinA"]}}] 27 // result = [{ID: "stack1", mixins: ["build:mixinA", "run:mixinC"]}}, {ID: "stack2", mixins: ["mixinA"]}}] 28 // 29 // stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}, {ID: "stack2", mixins: ["mixinA"]}}] 30 // stacksB = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] 31 // result = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] 32 // 33 // stacksA = [{ID: "stack1", mixins: ["build:mixinA"]}}] 34 // stacksB = [{ID: "stack2", mixins: ["mixinA", "run:mixinB"]}}] 35 // result = [] 36 // 37 func MergeCompatible(stacksA []dist.Stack, stacksB []dist.Stack) []dist.Stack { 38 set := map[string][]string{} 39 40 for _, s := range stacksA { 41 set[s.ID] = s.Mixins 42 } 43 44 var results []dist.Stack 45 for _, s := range stacksB { 46 if stackMixins, ok := set[s.ID]; ok { 47 mixinsSet := stringset.FromSlice(append(stackMixins, s.Mixins...)) 48 var mixins []string 49 for s := range mixinsSet { 50 mixins = append(mixins, s) 51 } 52 sort.Strings(mixins) 53 54 results = append(results, dist.Stack{ 55 ID: s.ID, 56 Mixins: mixins, 57 }) 58 } 59 } 60 61 return results 62 }