diff --git a/docs/content/usage.md b/docs/content/usage.md index 3fdd67319..341877fbd 100644 --- a/docs/content/usage.md +++ b/docs/content/usage.md @@ -43,6 +43,21 @@ Example: gomplate --input-dir=templates --output-dir=config --datasource config=config.yaml ``` +### `--exclude` + +To prevent certain files from being processed, you can use `--exclude`. It takes a glob, and any files matching that glob will not be included. + +Example: + +``` +gomplate --exclude example/** \ + --exclude *.png +``` + +This will stop all files in the example folder from being processed, as well as all .png files in the root folder. + +You can also chain the exclude flag to build up a series of globs to be excluded + ## `--datasource`/`-d` Add a data source in `name=URL` form. Specify multiple times to add multiple sources. The data can then be used by the [`datasource`](../functions/#datasource) and [`include`](../functions/#include) functions. diff --git a/gomplate.go b/gomplate.go index fcc5792f8..d1c6bb682 100644 --- a/gomplate.go +++ b/gomplate.go @@ -2,6 +2,7 @@ package main import ( "io" + "path/filepath" "text/template" "github.com/hairyhenderson/gomplate/data" @@ -45,11 +46,16 @@ func runTemplate(o *GomplateOpts) error { g := NewGomplate(d, o.lDelim, o.rDelim) + excludeList, err := executeCombinedGlob(o.excludeGlob) + if err != nil { + return err + } + if o.inputDir != "" { - return processInputDir(o.inputDir, o.outputDir, g) + return processInputDir(o.inputDir, o.outputDir, excludeList, g) } - return processInputFiles(o.input, o.inputFiles, o.outputFiles, g) + return processInputFiles(o.input, o.inputFiles, o.outputFiles, excludeList, g) } // Called from process.go ... @@ -63,3 +69,19 @@ func renderTemplate(g *Gomplate, inString string, outPath string) error { err = g.RunTemplate(inString, outFile) return err } + +// takes an array of glob strings and executes it as a whole, +// returning a merged list of globbed files +func executeCombinedGlob(globArray []string) ([]string, error) { + var combinedExcludes []string + for _, glob := range globArray { + excludeList, err := filepath.Glob(glob) + if err != nil { + return nil, err + } + + combinedExcludes = append(combinedExcludes, excludeList...) + } + + return combinedExcludes, nil +} diff --git a/main.go b/main.go index 12690f301..f5f340112 100644 --- a/main.go +++ b/main.go @@ -23,6 +23,7 @@ type GomplateOpts struct { inputDir string outputFiles []string outputDir string + excludeGlob []string } var opts GomplateOpts @@ -79,6 +80,7 @@ func initFlags(command *cobra.Command) { command.Flags().StringArrayVarP(&opts.inputFiles, "file", "f", []string{"-"}, "Template `file` to process. Omit to use standard input, or use --in or --input-dir") command.Flags().StringVarP(&opts.input, "in", "i", "", "Template `string` to process (alternative to --file and --input-dir)") command.Flags().StringVar(&opts.inputDir, "input-dir", "", "`directory` which is examined recursively for templates (alternative to --file and --in)") + command.Flags().StringArrayVar(&opts.excludeGlob, "exclude", []string{}, "glob of files to not parse") command.Flags().StringArrayVarP(&opts.outputFiles, "out", "o", []string{"-"}, "output `file` name. Omit to use standard output.") command.Flags().StringVar(&opts.outputDir, "output-dir", ".", "`directory` to store the processed templates. Only used for --input-dir") diff --git a/process.go b/process.go index 85235a523..7df938195 100644 --- a/process.go +++ b/process.go @@ -9,7 +9,7 @@ import ( // == Direct input processing ======================================== -func processInputFiles(stringTemplate string, input []string, output []string, g *Gomplate) error { +func processInputFiles(stringTemplate string, input []string, output []string, excludeList []string, g *Gomplate) error { input, err := readInputs(stringTemplate, input) if err != nil { return err @@ -29,7 +29,7 @@ func processInputFiles(stringTemplate string, input []string, output []string, g // == Recursive input dir processing ====================================== -func processInputDir(input string, output string, g *Gomplate) error { +func processInputDir(input string, output string, excludeList []string, g *Gomplate) error { input = filepath.Clean(input) output = filepath.Clean(output) @@ -55,8 +55,12 @@ func processInputDir(input string, output string, g *Gomplate) error { nextInPath := filepath.Join(input, entry.Name()) nextOutPath := filepath.Join(output, entry.Name()) + if inList(excludeList, nextInPath) { + continue + } + if entry.IsDir() { - err := processInputDir(nextInPath, nextOutPath, g) + err := processInputDir(nextInPath, nextOutPath, excludeList, g) if err != nil { return err } @@ -73,6 +77,16 @@ func processInputDir(input string, output string, g *Gomplate) error { return nil } +func inList(list []string, entry string) bool { + for _, file := range list { + if file == entry { + return true + } + } + + return false +} + // == File handling ================================================ func readInputs(input string, files []string) ([]string, error) { diff --git a/process_test.go b/process_test.go index b63ad6eb7..161518a43 100644 --- a/process_test.go +++ b/process_test.go @@ -48,7 +48,7 @@ func TestInputDir(t *testing.T) { Sources: map[string]*data.Source{"config": src}, } gomplate := NewGomplate(d, "{{", "}}") - err = processInputDir(filepath.Join("test", "files", "input-dir", "in"), outDir, gomplate) + err = processInputDir(filepath.Join("test", "files", "input-dir", "in"), outDir, []string{"**/*.exclude.txt"}, gomplate) assert.Nil(t, err) top, err := ioutil.ReadFile(filepath.Join(outDir, "top.txt")) @@ -58,4 +58,8 @@ func TestInputDir(t *testing.T) { inner, err := ioutil.ReadFile(filepath.Join(outDir, "inner/nested.txt")) assert.Nil(t, err) assert.Equal(t, "zwei", string(inner)) + + // excluded file should not exist in out dir + _, err = ioutil.ReadFile(filepath.Join(outDir, "inner/exclude.txt")) + assert.NotEmpty(t, err) } diff --git a/test/files/input-dir/in/exclude.txt b/test/files/input-dir/in/exclude.txt new file mode 100644 index 000000000..d9cfae16d --- /dev/null +++ b/test/files/input-dir/in/exclude.txt @@ -0,0 +1 @@ +Should not be included