pkg/clearsource/clearsource.go (70 lines of code) (raw):

// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package clearsource contains tools to delete source code. package clearsource import ( "fmt" "os" "path/filepath" "strconv" "time" "github.com/GoogleCloudPlatform/buildpacks/pkg/appstart" "github.com/GoogleCloudPlatform/buildpacks/pkg/buildererror" "github.com/GoogleCloudPlatform/buildpacks/pkg/devmode" "github.com/GoogleCloudPlatform/buildpacks/pkg/env" gcp "github.com/GoogleCloudPlatform/buildpacks/pkg/gcpbuildpack" ) var ( defaultExclusions = []string{appstart.ConfigDir} ) // DetectFn detemines if clear source buildpacks should opt out. // In case the buildpack shouldn't opt out, the function does not make a // determination and instead returns a nil result. func DetectFn(ctx *gcp.Context) (gcp.DetectResult, error) { if devmode.Enabled(ctx) { return gcp.OptOut("development mode enabled"), nil } if clearSource, ok := os.LookupEnv(env.ClearSource); ok { clear, err := strconv.ParseBool(clearSource) if err != nil { return nil, gcp.UserErrorf("parsing %q: %v", env.ClearSource, err) } if clear { // It is up to the buildpack to determine if clear source has any effect // and if it should opt in, e.g. Java only opts in for Gradle/Maven builds. return nil, nil } } return gcp.OptOutEnvNotSet(env.ClearSource), nil } // BuildFn clears the workspace while leaving exclusion patterns untouched. // exclusions is a list of pattern strings relative to the user application directory. func BuildFn(ctx *gcp.Context, exclusions []string) error { ctx.Logf("Clearing source") defer func(now time.Time) { ctx.Span("Clear source", now, buildererror.StatusOk) }(time.Now()) exclusions = append(exclusions, defaultExclusions...) paths, err := pathsToRemove(ctx, ctx.ApplicationRoot(), exclusions) if err != nil { return fmt.Errorf("filtering paths: %w", err) } for _, path := range paths { if err := ctx.RemoveAll(path); err != nil { return err } } return nil } // pathsToRemove returns a list of entries in dir, filtering entries that match any in exclusions. exclusions should be a partial path relative to dir. func pathsToRemove(ctx *gcp.Context, dir string, exclusions []string) ([]string, error) { paths, err := ctx.Glob(filepath.Join(dir, "*")) if err != nil { return nil, fmt.Errorf("finding paths: %w", err) } var filteredPaths []string for _, path := range paths { remove := true for _, exclusion := range exclusions { if match, err := filepath.Match(path, filepath.Join(dir, exclusion)); err != nil { return nil, fmt.Errorf("matching pattern %q with path %q: %v", filepath.Join(dir, exclusion), path, err) } else if match { remove = false break } } if remove { filteredPaths = append(filteredPaths, path) } } return filteredPaths, nil }