3434@ EqualsAndHashCode (callSuper = false )
3535public class AppendToTextFile extends ScanningRecipe <AtomicBoolean > {
3636 @ Option (displayName = "Relative file name" ,
37- description = "File name, using a relative path. If a non-plaintext file already exists at this location, then this recipe will do nothing." ,
37+ description = "File name, using a relative path. May also be a glob expression (e.g. `**/*.txt`) to match one or more existing files; " +
38+ "when a glob is supplied no new file is created. If a non-plaintext file matches, that file is left unchanged." ,
3839 example = "foo/bar/baz.txt" )
3940 String relativeFileName ;
4041
@@ -93,7 +94,7 @@ public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean fileExists) {
9394 @ Override
9495 public Tree visit (@ Nullable Tree tree , ExecutionContext ctx ) {
9596 SourceFile sourceFile = (SourceFile ) requireNonNull (tree );
96- if (!fileExists .get () && sourceFile .getSourcePath (). toString (). equals ( Paths . get ( relativeFileName ). toString ())) {
97+ if (!fileExists .get () && matchesTarget ( sourceFile .getSourcePath ())) {
9798 fileExists .set (true );
9899 }
99100 return sourceFile ;
@@ -103,6 +104,11 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
103104
104105 @ Override
105106 public Collection <PlainText > generate (AtomicBoolean fileExists , Collection <SourceFile > generatedInThisCycle , ExecutionContext ctx ) {
107+ // A glob can match multiple existing files but doesn't specify a concrete path to create.
108+ if (relativeFileName .matches (".*[*?\\ [{].*" )) {
109+ return emptyList ();
110+ }
111+
106112 String maybeNewline = !Boolean .FALSE .equals (appendNewline ) ? "\n " : "" ;
107113 String content = this .content + maybeNewline ;
108114 String preamble = this .preamble != null ? this .preamble + maybeNewline : "" ;
@@ -132,7 +138,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor(AtomicBoolean fileExists) {
132138 @ Override
133139 public Tree visit (@ Nullable Tree tree , ExecutionContext ctx ) {
134140 SourceFile sourceFile = (SourceFile ) requireNonNull (tree );
135- if (sourceFile . getSourcePath (). toString (). equals ( Paths . get ( relativeFileName ). toString ())) {
141+ if (sourceFile instanceof PlainText && matchesTarget ( sourceFile . getSourcePath ())) {
136142 String maybeNewline = !Boolean .FALSE .equals (appendNewline ) ? "\n " : "" ;
137143 String content = AppendToTextFile .this .content + maybeNewline ;
138144 String preamble = AppendToTextFile .this .preamble != null ? AppendToTextFile .this .preamble + maybeNewline : "" ;
@@ -155,6 +161,10 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
155161 });
156162 }
157163
164+ private boolean matchesTarget (Path sourcePath ) {
165+ return sourcePath .getFileSystem ().getPathMatcher ("glob:" + relativeFileName ).matches (sourcePath );
166+ }
167+
158168 /**
159169 * Merges new content with existing content by appending only lines that are not already present.
160170 * Lines are compared after trimming whitespace.
0 commit comments