github.com/paketoio/libpak@v1.3.1/build.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 "os" 22 "path/filepath" 23 "strings" 24 25 "github.com/buildpacks/libcnb" 26 "github.com/heroku/color" 27 "github.com/imdario/mergo" 28 "github.com/paketoio/libpak/bard" 29 "github.com/paketoio/libpak/internal" 30 ) 31 32 // Build is called by the main function of a buildpack, for build. 33 func Build(f libcnb.BuildFunc, options ...libcnb.Option) { 34 logger := bard.NewLogger(os.Stdout) 35 36 libcnb.Build( 37 func(context libcnb.BuildContext) (libcnb.BuildResult, error) { 38 39 // TODO: Remove once pack supports bindings natively 40 bindings, err := libcnb.NewBindingsFromEnvironment("CNB_BINDINGS") 41 if err != nil { 42 return libcnb.BuildResult{}, fmt.Errorf("unable to get bindings from $CNB_BINDINGS: %w", err) 43 } 44 if err = mergo.Merge(&context.Platform.Bindings, bindings); err != nil { 45 return libcnb.BuildResult{}, fmt.Errorf("unable to merge bindings %+v and %+v: %w", context.Platform.Bindings, bindings, err) 46 } 47 48 result, err := f(context) 49 if err != nil { 50 return result, bard.IdentifiableError{ 51 Name: context.Buildpack.Info.Name, 52 Description: context.Buildpack.Info.Version, 53 Err: err, 54 } 55 } 56 57 file := filepath.Join(context.Layers.Path, "*.toml") 58 existing, err := filepath.Glob(file) 59 if err != nil { 60 return libcnb.BuildResult{}, fmt.Errorf("unable to list files in %s: %w", file, err) 61 } 62 63 var contrib []string 64 for _, l := range result.Layers { 65 contrib = append(contrib, l.Name()) 66 } 67 68 var remove []string 69 for _, e := range existing { 70 if !strings.HasSuffix(e, "store.toml") && !contains(contrib, strings.TrimSuffix(filepath.Base(e), ".toml")) { 71 remove = append(remove, e) 72 } 73 } 74 75 if len(remove) > 0 { 76 logger.Header("%s unused layers", color.YellowString("Removing")) 77 78 for _, r := range remove { 79 logger.Body(strings.TrimSuffix(filepath.Base(r), ".toml")) 80 if err = os.RemoveAll(r); err != nil { 81 return libcnb.BuildResult{}, fmt.Errorf("unable to remove file %s: %w", r, err) 82 } 83 } 84 } 85 86 return result, nil 87 }, 88 append([]libcnb.Option{ 89 libcnb.WithEnvironmentWriter(internal.NewEnvironmentWriter()), 90 libcnb.WithExitHandler(internal.NewExitHandler()), 91 libcnb.WithTOMLWriter(internal.NewTOMLWriter()), 92 }, options...)..., 93 ) 94 } 95 96 func contains(candidates []string, value string) bool { 97 for _, c := range candidates { 98 if c == value { 99 return true 100 } 101 } 102 103 return false 104 }