diff --git a/cli/pack/common.go b/cli/pack/common.go index 3f352da37..eae84ebc7 100644 --- a/cli/pack/common.go +++ b/cli/pack/common.go @@ -277,14 +277,30 @@ func getDestAppDir(bundleEnvPath, appName string, // copyApplications copies applications from current env to the result bundle. func copyApplications(bundleEnvPath string, packCtx *PackCtx, - cliOpts, newOpts *config.CliOpts) error { - var err error + cliOpts, newOpts *config.CliOpts, toIgnore map[string]struct{}) error { for appName, instances := range packCtx.AppsInfo { if len(instances) == 0 { return fmt.Errorf("application %q does not have any instances", appName) } inst := instances[0] appPath := inst.AppDir + + projectPath := filepath.Dir(packCtx.configFilePath) + relAppPath, err := filepath.Rel(projectPath, appPath) + if err != nil { + return err + } + relAppPathUnix := filepath.ToSlash(relAppPath) + + ignore, err := shouldIgnore(relAppPathUnix, toIgnore) + if err != nil { + return err + } + if ignore { + log.Infof("Application %s found in .packignore, skipping it...", appName) + continue + } + if inst.IsFileApp { appPath = inst.InstanceScript resolvedAppPath, err := filepath.EvalSymlinks(appPath) @@ -363,6 +379,12 @@ func prepareBundle(cmdCtx *cmdcontext.CmdCtx, packCtx *PackCtx, packCtx.AppList = getAppNamesToPack(packCtx) log.Infof("Apps to pack: %s", strings.Join(packCtx.AppList, " ")) + projectPath := filepath.Dir(packCtx.configFilePath) + ignorePatterns, err := readPackIgnore(projectPath) + if err != nil { + return "", fmt.Errorf("failed to read .packignore: %v", err) + } + if bundleEnvPath, err = updateEnvPath(bundleEnvPath, packCtx, cliOpts); err != nil { return "", err } @@ -373,12 +395,12 @@ func prepareBundle(cmdCtx *cmdcontext.CmdCtx, packCtx *PackCtx, return "", fmt.Errorf("error copying binaries: %s", err) } - if err = copyApplications(bundleEnvPath, packCtx, cliOpts, newOpts); err != nil { + if err = copyApplications(bundleEnvPath, packCtx, cliOpts, newOpts, ignorePatterns); err != nil { return "", fmt.Errorf("error copying applications: %s", err) } if packCtx.Archive.All { - if err = copyArtifacts(*packCtx, bundleEnvPath, newOpts, packCtx.AppsInfo); err != nil { + if err = copyArtifacts(*packCtx, bundleEnvPath, newOpts, packCtx.AppsInfo, ignorePatterns); err != nil { return "", fmt.Errorf("failed copying artifacts: %s", err) } } @@ -425,7 +447,7 @@ func copyAppSrc(packCtx *PackCtx, cliOpts *config.CliOpts, srcAppPath, dstAppPat // copyArtifacts copies all artifacts from the current bundle configuration // to the passed package structure from the passed path. func copyArtifacts(packCtx PackCtx, basePath string, newOpts *config.CliOpts, - appsInfo map[string][]running.InstanceCtx) error { + appsInfo map[string][]running.InstanceCtx, toIgnore map[string]struct{}) error { for _, appName := range packCtx.AppList { for _, inst := range appsInfo[appName] { diff --git a/cli/pack/ignore.go b/cli/pack/ignore.go new file mode 100644 index 000000000..82139d7c8 --- /dev/null +++ b/cli/pack/ignore.go @@ -0,0 +1,61 @@ +package pack + +import ( + "bufio" + "os" + "path/filepath" + "strings" +) + +// readPackIgnore reads the .packignore file and returns a slice of ignore patterns. +func readPackIgnore(projectPath string) (map[string]struct{}, error) { + ignoreFilePath := filepath.Join(projectPath, ".packignore") + file, err := os.Open(ignoreFilePath) + if err != nil { + if os.IsNotExist(err) { + return map[string]struct{}{}, nil + } + return nil, err + } + defer file.Close() + + patterns := make(map[string]struct{}) + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + patterns[line] = struct{}{} + } + + if err := scanner.Err(); err != nil { + return nil, err + } + return patterns, nil +} + +// shouldIgnore checks if the given file path matches any of the ignore patterns. +func shouldIgnore(path string, patterns map[string]struct{}) (bool, error) { + for pattern := range patterns { + pattern = filepath.ToSlash(pattern) + filePath := filepath.ToSlash(path) + + if strings.HasSuffix(pattern, "/") { + if strings.HasPrefix(filePath, pattern) { + return true, nil + } + continue + } + + match, err := filepath.Match(pattern, filePath) + if err != nil { + return false, err + } + if match { + return true, nil + } + } + return false, nil +} diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/.packignore b/test/integration/pack/test_bundles/bundle_with_packignore/.packignore new file mode 100644 index 000000000..c967c2c79 --- /dev/null +++ b/test/integration/pack/test_bundles/bundle_with_packignore/.packignore @@ -0,0 +1,3 @@ +app.lua +instances_enabled/app1.lua +instances_enabled/app1 \ No newline at end of file diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/app.lua b/test/integration/pack/test_bundles/bundle_with_packignore/app.lua new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/app2 b/test/integration/pack/test_bundles/bundle_with_packignore/app2 new file mode 120000 index 000000000..6ecb93242 --- /dev/null +++ b/test/integration/pack/test_bundles/bundle_with_packignore/app2 @@ -0,0 +1 @@ +../bundle1/app2 \ No newline at end of file diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/instances_enabled b/test/integration/pack/test_bundles/bundle_with_packignore/instances_enabled new file mode 120000 index 000000000..09f8b996f --- /dev/null +++ b/test/integration/pack/test_bundles/bundle_with_packignore/instances_enabled @@ -0,0 +1 @@ +../bundle1/instances_enabled \ No newline at end of file diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/modules b/test/integration/pack/test_bundles/bundle_with_packignore/modules new file mode 120000 index 000000000..363353b32 --- /dev/null +++ b/test/integration/pack/test_bundles/bundle_with_packignore/modules @@ -0,0 +1 @@ +../bundle1/modules \ No newline at end of file diff --git a/test/integration/pack/test_bundles/bundle_with_packignore/tt.yaml b/test/integration/pack/test_bundles/bundle_with_packignore/tt.yaml new file mode 120000 index 000000000..409358505 --- /dev/null +++ b/test/integration/pack/test_bundles/bundle_with_packignore/tt.yaml @@ -0,0 +1 @@ +../bundle1/tt.yaml \ No newline at end of file