From 37272dd0195bab86237a4976e340af68a7a3b87f Mon Sep 17 00:00:00 2001 From: Patrick D'appollonio <930925+patrickdappollonio@users.noreply.github.com> Date: Tue, 19 Mar 2024 23:18:48 -0400 Subject: [PATCH] Allow pruning of target directory's contents (#113) --- README.md | 1 + app.go | 1 + slice/execute.go | 12 ++++++++++++ slice/split.go | 1 + slice/utils.go | 21 +++++++++++++++++++++ 5 files changed, 36 insertions(+) diff --git a/README.md b/README.md index bc4bc07..bf70d52 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ Flags: --include-triple-dash if enabled, the typical "---" YAML separator is included at the beginning of resources sliced -f, --input-file string the input file used to read the initial macro YAML file; if empty or "-", stdin is used -o, --output-dir string the output directory used to output the splitted files + --prune if enabled, the output directory will be pruned before writing the files -q, --quiet if true, no output is written to stdout/err -s, --skip-non-k8s if enabled, any YAMLs that don't contain at least an "apiVersion", "kind" and "metadata.name" will be excluded from the split --sort-by-kind if enabled, resources are sorted by Kind, a la Helm, before saving them to disk diff --git a/app.go b/app.go index 598b938..cf0292e 100644 --- a/app.go +++ b/app.go @@ -113,6 +113,7 @@ func root() *cobra.Command { rootCommand.Flags().BoolVar(&opts.AllowEmptyKinds, "allow-empty-kinds", false, "if enabled, resources with empty kinds don't produce an error when filtering") rootCommand.Flags().BoolVar(&opts.AllowEmptyNames, "allow-empty-names", false, "if enabled, resources with empty names don't produce an error when filtering") rootCommand.Flags().BoolVar(&opts.IncludeTripleDash, "include-triple-dash", false, "if enabled, the typical \"---\" YAML separator is included at the beginning of resources sliced") + rootCommand.Flags().BoolVar(&opts.PruneOutputDir, "prune", false, "if enabled, the output directory will be pruned before writing the files") _ = rootCommand.Flags().MarkHidden("debug") return rootCommand diff --git a/slice/execute.go b/slice/execute.go index c61d7b1..de7af6a 100644 --- a/slice/execute.go +++ b/slice/execute.go @@ -155,6 +155,18 @@ func (s *Split) store() error { s.opts.OutputDirectory = "." } + // If the user wants to prune the output directory, do it + if s.opts.PruneOutputDir && !s.opts.OutputToStdout && !s.opts.DryRun { + // Check if the directory exists and if it does, prune it + if _, err := os.Stat(s.opts.OutputDirectory); !os.IsNotExist(err) { + s.log.Printf("Pruning output directory %q", s.opts.OutputDirectory) + if err := deleteFolderContents(s.opts.OutputDirectory); err != nil { + return fmt.Errorf("unable to prune output directory %q: %w", s.opts.OutputDirectory, err) + } + s.log.Printf("Output directory %q pruned", s.opts.OutputDirectory) + } + } + // Now save those files to disk (or if dry-run is on, print what it would // save). Files will be overwritten. s.fileCount = 0 diff --git a/slice/split.go b/slice/split.go index afa7c3e..5359aaf 100644 --- a/slice/split.go +++ b/slice/split.go @@ -65,6 +65,7 @@ type Options struct { InputFile string // the name of the input file to be read OutputDirectory string // the path to the directory where the files will be stored + PruneOutputDir bool // if true, the output directory will be pruned before writing the files OutputToStdout bool // if true, the output will be written to stdout instead of a file GoTemplate string // the go template code to render the file names DryRun bool // if true, no files are created diff --git a/slice/utils.go b/slice/utils.go index f9799f7..0885cee 100644 --- a/slice/utils.go +++ b/slice/utils.go @@ -38,3 +38,24 @@ func openFile(fp string) (*os.File, error) { return f, nil } + +func deleteFolderContents(location string) error { + f, err := os.Open(location) + if err != nil { + return fmt.Errorf("unable to open folder %q: %s", location, err.Error()) + } + defer f.Close() + + names, err := f.Readdirnames(-1) + if err != nil { + return fmt.Errorf("unable to read folder %q: %s", location, err.Error()) + } + + for _, name := range names { + if err := os.RemoveAll(location + "/" + name); err != nil { + return fmt.Errorf("unable to remove %q: %s", name, err.Error()) + } + } + + return nil +}