This is an automated email from the ASF dual-hosted git repository.
claude pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
The following commit(s) were added to refs/heads/master by this push:
new 08d67164 RAT-98: Converted to FileProcessorBuilder design (#439)
08d67164 is described below
commit 08d671640d3cf40de34942438fc6537bb8e2d927
Author: Claude Warren <[email protected]>
AuthorDate: Fri Feb 7 18:44:47 2025 +0100
RAT-98: Converted to FileProcessorBuilder design (#439)
* Converted to FileProcessorBuilder design
* Minor changes during review
* removed unused method
---------
Co-authored-by: P. Ottlinger <[email protected]>
---
.../rat/config/exclusion/ExclusionProcessor.java | 15 +-
.../rat/config/exclusion/StandardCollection.java | 37 ++--
.../AbstractFileProcessorBuilder.java | 232 +++++++++++++++++++++
...noreProcessor.java => BazaarIgnoreBuilder.java} | 16 +-
...CVSFileProcessor.java => CVSIgnoreBuilder.java} | 24 ++-
.../fileProcessors/DescendingFileProcessor.java | 121 -----------
.../exclusion/fileProcessors/GitFileProcessor.java | 70 -------
.../exclusion/fileProcessors/GitIgnoreBuilder.java | 105 ++++++++++
...HgIgnoreProcessor.java => HgIgnoreBuilder.java} | 34 ++-
.../src/main/java/org/apache/rat/help/Help.java | 2 +-
.../config/exclusion/StandardCollectionTest.java | 2 +-
.../fileProcessors/AbstractIgnoreBuilderTest.java | 118 +++++++++++
.../AbstractIgnoreProcessorTest.java | 62 ------
...essorTest.java => BazaarIgnoreBuilderTest.java} | 22 +-
...rocessorTest.java => CVSIgnoreBuilderTest.java} | 21 +-
.../DescendingFileProcessorTest.java | 70 -------
.../fileProcessors/GitFileProcessorTest.java | 118 -----------
.../fileProcessors/GitIgnoreBuilderTest.java | 138 ++++++++++++
...ProcessorTest.java => HgIgnoreBuilderTest.java} | 32 +--
.../commandLine.txt | 0
.../expected-message.txt | 0
.../{RAT_355 => GitIgnoreBuilderTest}/pom.xml | 0
.../resources/GitIgnoreBuilderTest/src/.gitignore | 7 +
.../src/README.txt | 0
.../GitIgnoreBuilderTest/src/dir1/.gitignore | 3 +
.../src/dir1/dir1.md | 0
.../src/dir1/dir1.txt} | 0
.../src/dir1/file1.log} | 0
.../src/dir2/dir2.md} | 0
.../src/dir2/dir2.txt | 0
.../src/dir3/dir3.log} | 0
.../src/dir3/file3.log | 0
.../src/invoker.properties | 0
.../dir1.md => GitIgnoreBuilderTest/src/root.md} | 0
.../verify.groovy | 0
35 files changed, 705 insertions(+), 544 deletions(-)
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
index d5b3ebe4..7f908750 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
@@ -209,15 +209,12 @@ public class ExclusionProcessor {
private List<MatcherSet> extractFileProcessors(final DocumentName basedir)
{
final List<MatcherSet> fileProcessorList = new ArrayList<>();
for (StandardCollection sc : fileProcessors) {
- final Set<String> names = new HashSet<>();
- sc.fileProcessor().map(fp -> fp.apply(basedir)).forEachRemaining(n
-> n.forEach(names::add));
- MatcherSet.Builder builder = new MatcherSet.Builder();
- Set<String> matching = new HashSet<>();
- Set<String> notMatching = new HashSet<>();
- MatcherSet.Builder.segregateList(matching, notMatching, names);
- builder.addIncluded(basedir.resolve(sc.name()), notMatching);
- builder.addExcluded(basedir.resolve(sc.name()), matching);
- fileProcessorList.add(builder.build());
+ ExtendedIterator<List<MatcherSet>> iter =
sc.fileProcessorBuilder().map(builder -> builder.build(basedir));
+ if (iter.hasNext()) {
+ iter.forEachRemaining(fileProcessorList::addAll);
+ } else {
+ DefaultLog.getInstance().debug(String.format("%s does not have
a fileProcessor.", sc));
+ }
}
return fileProcessorList;
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
index d2c59707..62c17972 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
@@ -28,10 +28,11 @@ import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
-import org.apache.rat.config.exclusion.fileProcessors.BazaarIgnoreProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.CVSFileProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.GitFileProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.HgIgnoreProcessor;
+import
org.apache.rat.config.exclusion.fileProcessors.AbstractFileProcessorBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.BazaarIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.CVSIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.GitIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.HgIgnoreBuilder;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.utils.ExtendedIterator;
@@ -55,7 +56,7 @@ public enum StandardCollection {
* The files and directories created by a Bazaar source code control based
tool.
*/
BAZAAR("The files and directories created by a Bazaar source code control
based tool.",
- Arrays.asList("**/.bzr/**", "**/.bzrignore"), null, new
BazaarIgnoreProcessor()),
+ Arrays.asList("**/.bzr/**", "**/.bzrignore"), null, new
BazaarIgnoreBuilder()),
/**
* The files and directories created by a Bitkeeper source code control
based tool.
*/
@@ -74,7 +75,7 @@ public enum StandardCollection {
"**/*.orig", "**/*.rej", "**/.del-*",
"**/*.a", "**/*.old", "**/*.o", "**/*.obj", "**/*.so",
"**/*.exe",
"**/*.Z", "**/*.elc", "**/*.ln", "**/core"),
- null, new CVSFileProcessor()),
+ null, new CVSIgnoreBuilder()),
/**
* The files and directories created by a DARCS source code control based
tool.
*/
@@ -93,7 +94,7 @@ public enum StandardCollection {
GIT("The files and directories created by GIT source code control to
support GIT, also processes files listed in '.gitignore'.",
Arrays.asList("**/.git/**", "**/.gitignore"),
null,
- new GitFileProcessor()
+ new GitIgnoreBuilder()
),
/**
* The hidden directories. Directories with names that start with {@code .}
@@ -135,9 +136,9 @@ public enum StandardCollection {
IDEA("The files and directories created by an IDEA IDE based tool.",
Arrays.asList("**/*.iml", "**/*.ipr", "**/*.iws", "**/.idea/**"),
null, null),
/**
- * The .DS_Store files on Mac computers.
+ * The {@code .DS_Store} files on Mac computers.
*/
- MAC("The .DS_Store files Mac computers.",
+ MAC("The .DS_Store files on Mac computers.",
Collections.singletonList("**/.DS_Store"), null, null),
/**
* The files and directories created by Maven build system based project.
@@ -156,7 +157,7 @@ public enum StandardCollection {
* The files and directories created by a Mercurial source code control
based tool.
*/
MERCURIAL("The files and directories created by a Mercurial source code
control based tool.",
- Arrays.asList("**/.hg/**", "**/.hgignore"), null, new
HgIgnoreProcessor()),
+ Arrays.asList("**/.hg/**", "**/.hgignore"), null, new
HgIgnoreBuilder()),
/**
* The set of miscellaneous files generally left by editors and the like.
*/
@@ -213,17 +214,17 @@ public enum StandardCollection {
private final Collection<String> patterns;
/** A document name matcher supplier to create a document name matcher.
May be null */
private final DocumentNameMatcher staticDocumentNameMatcher;
- /** The FileProcessor to process the exclude file associated with this
exclusion. May be null. */
- private final FileProcessor fileProcessor;
+ /** The AbstractFileProcessorBuilder to process the exclude file
associated with this exclusion. May be {@code null}. */
+ private final AbstractFileProcessorBuilder fileProcessorBuilder;
/** The description of this collection */
private final String desc;
StandardCollection(final String desc, final Collection<String> patterns,
final DocumentNameMatcher documentNameMatcher,
- final FileProcessor fileProcessor) {
+ final AbstractFileProcessorBuilder
fileProcessorBuilder) {
this.desc = desc;
this.patterns = patterns == null ? Collections.emptyList() : new
HashSet<>(patterns);
this.staticDocumentNameMatcher = documentNameMatcher;
- this.fileProcessor = fileProcessor;
+ this.fileProcessorBuilder = fileProcessorBuilder;
}
/**
@@ -277,11 +278,11 @@ public enum StandardCollection {
*
* @return the fileProcessor if it exists, {@code null} otherwise.
*/
- public ExtendedIterator<FileProcessor> fileProcessor() {
- List<FileProcessor> lst = new ArrayList<>();
+ public ExtendedIterator<AbstractFileProcessorBuilder>
fileProcessorBuilder() {
+ List<AbstractFileProcessorBuilder> lst = new ArrayList<>();
for (StandardCollection sc : getCollections()) {
- if (sc.fileProcessor != null) {
- lst.add(sc.fileProcessor);
+ if (sc.fileProcessorBuilder != null) {
+ lst.add(sc.fileProcessorBuilder);
}
}
return ExtendedIterator.create(lst.iterator());
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
new file mode 100644
index 00000000..9e33aeab
--- /dev/null
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.rat.config.exclusion.fileProcessors;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.NameFileFilter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.MatchPattern;
+import org.apache.rat.config.exclusion.plexus.MatchPatterns;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+
+/**
+ * Creates a List of {@link MatcherSet}s that represent the inclusions and
exclusions of this file processor.
+ * <p>
+ * By default this processor:
+ * </p>
+ * <ul>
+ * <li>Creates a list of levels that correspond to the depth of the
directories where the specific include/exclude file is located.
+ * Directory depth is relative to the initially discovered include/exclude
file.</li>
+ * <li>A MatcherSet is created for each include/exclude file located, and
the MatcherSet is added to the proper level.</li>
+ * <li>During the build:
+ * <ul>
+ * <li>Each level creates a MatcherSet for the level.</li>
+ * <li>The MatcherSet for each level is returned in reverse order
(deepest first). This ensures that most include/exclude
+ * files will be properly handled.</li>
+ * </ul></li>
+ * </ul>
+ */
+public abstract class AbstractFileProcessorBuilder {
+ /** A String format pattern to print a regex string */
+ protected static final String REGEX_FMT = "%%regex[%s]";
+ /** The name of the file being processed */
+ protected final String fileName;
+ /** The predicate that will return {@code false} for any comment line in
the file. */
+ protected final Predicate<String> commentFilter;
+ /** the collection of level builders */
+ private final SortedMap<Integer, LevelBuilder> levelBuilders;
+ /** If {@code true} then the processor file name will be included in the
list of files to ignore */
+ private final boolean includeProcessorFile;
+
+ /**
+ * Constructor for multiple comment prefixes.
+ * @param fileName The name of the file being read.
+ * @param commentPrefixes the collection of comment prefixes.
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final
Iterable<String> commentPrefixes, final boolean includeProcessorFile) {
+ this(fileName, commentPrefixes == null ? StringUtils::isNotBlank :
ExclusionUtils.commentFilter(commentPrefixes), includeProcessorFile);
+ }
+
+ /**
+ * Constructor for single comment prefix
+ * @param fileName The name of the file to process.
+ * @param commentPrefix the comment prefix
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final String
commentPrefix, final boolean includeProcessorFile) {
+ this(fileName, commentPrefix == null ? null :
Collections.singletonList(commentPrefix), includeProcessorFile);
+ }
+
+ /**
+ * Constructor for single comment prefix
+ * @param fileName The name of the file to process.
+ * @param commentFilter the comment prefix filter.
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final
Predicate<String> commentFilter, final boolean includeProcessorFile) {
+ this.levelBuilders = new TreeMap<>();
+ this.fileName = fileName;
+ this.commentFilter = commentFilter;
+ this.includeProcessorFile = includeProcessorFile;
+ }
+
+ /**
+ * Creates the MatcherSet from each level and returns them in a list in
reverse order.
+ * @return a list of MatcherSet
+ */
+
+ private List<MatcherSet> createMatcherSetList() {
+ List<Integer> keys = new ArrayList<>(levelBuilders.keySet());
+ keys.sort((a, b) -> -1 * Integer.compare(a, b));
+ return keys.stream().map(key ->
levelBuilders.get(key).asMatcherSet()).collect(Collectors.toList());
+ }
+
+ /**
+ * Builder the list of MatcherSet that define the inclusions/exclusions
for the file processor.
+ * @param root the directory against which name resolution should be made.
+ * @return the List of MatcherSet that represent this file processor.
+ */
+ public final List<MatcherSet> build(final DocumentName root) {
+ if (includeProcessorFile) {
+ String name = String.format("**/%s", fileName);
+ String pattern = ExclusionUtils.qualifyPattern(root, name);
+ MatcherSet matcherSet = new MatcherSet.Builder()
+ .addExcluded(new DocumentNameMatcher(name,
MatchPatterns.from(root.getDirectorySeparator(),
Collections.singletonList(pattern)), root))
+ .build();
+ LevelBuilder levelBuilder = levelBuilders.computeIfAbsent(0, k ->
new LevelBuilder());
+ levelBuilder.add(matcherSet);
+ }
+
+ checkDirectory(0, root, root, new NameFileFilter(fileName));
+
+ List<MatcherSet> result = levelBuilders.size() == 1 ?
Collections.singletonList(levelBuilders.get(0).asMatcherSet())
+ : createMatcherSetList();
+ levelBuilders.clear();
+ return result;
+ }
+
+ /**
+ * Process by reading the file, creating a MatcherSet, and adding it to the
+ * matcherSets.
+ * @param matcherSetConsumer the consumer to add the custom matcher sets
to.
+ * @param root The root against which to resolve names.
+ * @param documentName the file to read.
+ * @return A matcher set based on the strings in the file.
+ */
+ protected MatcherSet process(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
+ final MatcherSet.Builder matcherSetBuilder = new MatcherSet.Builder();
+ final List<String> iterable = new ArrayList<>();
+ ExclusionUtils.asIterator(documentName.asFile(), commentFilter)
+ .map(entry -> modifyEntry(matcherSetConsumer, documentName,
entry).orElse(null))
+ .filter(Objects::nonNull)
+ .map(entry -> ExclusionUtils.qualifyPattern(documentName,
entry))
+ .forEachRemaining(iterable::add);
+
+ Set<String> included = new HashSet<>();
+ Set<String> excluded = new HashSet<>();
+ MatcherSet.Builder.segregateList(excluded, included, iterable);
+ DocumentName displayName =
DocumentName.builder(root).setName(documentName.getName()).build();
+ matcherSetBuilder.addExcluded(displayName, excluded);
+ matcherSetBuilder.addIncluded(displayName, included);
+ return matcherSetBuilder.build();
+ }
+
+ /**
+ * Process the directory tree looking for files that match the filter.
Call {@link #process} on any matching file.
+ * @param level the level being precessed
+ * @param root the directory against which names should be resolved.
+ * @param directory The name of the directory to process.
+ * @param fileFilter the filter to detect processable files with.
+ */
+ private void checkDirectory(final int level, final DocumentName root,
final DocumentName directory, final FileFilter fileFilter) {
+ File dirFile = directory.asFile();
+ for (File file : listFiles(dirFile, fileFilter)) {
+ LevelBuilder levelBuilder = levelBuilders.computeIfAbsent(level, k
-> new LevelBuilder());
+ levelBuilder.add(process(levelBuilder::add, root,
DocumentName.builder(file).build()));
+ }
+ for (File dir : listFiles(dirFile, DirectoryFileFilter.DIRECTORY)) {
+ checkDirectory(level + 1, root,
DocumentName.builder(dir).setBaseName(directory.getBaseName()).build(),
fileFilter);
+ }
+ }
+
+ /**
+ * Allows modification of the file entry to match the {@link MatchPattern}
format.
+ * Default implementation returns the @{code entry} argument.
+ * @param documentName the name of the document that the file was read
from.
+ * @param entry the entry from that document.
+ * @return the modified string or an empty Optional to skip the string.
+ */
+ protected Optional<String> modifyEntry(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName documentName, final String entry) {
+ return Optional.of(entry);
+ }
+
+ /**
+ * Create a list of files by applying the filter to the specified
directory.
+ * @param dir the directory.
+ * @param filter the filter.
+ * @return an array of files. May be empty but will not be null.
+ */
+ protected File[] listFiles(final File dir, final FileFilter filter) {
+ File[] result = dir.listFiles(filter);
+ return result == null ? new File[0] : result;
+ }
+
+ /**
+ * Manages the merging of {@link MatcherSet}s for the specified level.
+ */
+ private static class LevelBuilder {
+ /**
+ * The list of MatcherSets that this builder produced.
+ */
+ private final MatcherSet.Builder builder = new MatcherSet.Builder();
+
+ /**
+ * Adds a MatcherSet to this level.
+ * @param matcherSet the matcher set to add.
+ */
+ public void add(final MatcherSet matcherSet) {
+ matcherSet.includes().ifPresent(builder::addIncluded);
+ matcherSet.excludes().ifPresent(builder::addExcluded);
+ }
+
+ /**
+ * Constructs the MatcherSet for this level.
+ * @return the MatcherSet.
+ */
+ public MatcherSet asMatcherSet() {
+ return builder.build();
+ }
+ }
+}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
similarity index 71%
rename from
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java
rename to
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
index 65217c37..2be97f98 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
@@ -18,6 +18,10 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
import static java.lang.String.format;
@@ -25,21 +29,21 @@ import static java.lang.String.format;
/**
* A processor for {@code .bzrignore} files.
*/
-public final class BazaarIgnoreProcessor extends DescendingFileProcessor {
+public final class BazaarIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* Constructor.
*/
- public BazaarIgnoreProcessor() {
- super(".bzrignore", "#");
+ public BazaarIgnoreBuilder() {
+ super(".bzrignore", "#", true);
}
@Override
- public String modifyEntry(final DocumentName baseName, final String entry)
{
+ public Optional<String> modifyEntry(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName baseName, final String entry) {
if (entry.startsWith("RE:")) {
String line = entry.substring("RE:".length()).trim();
String pattern = line.startsWith("^") ? line.substring(1) : line;
- return format(REGEX_FMT, pattern);
+ return Optional.of(format(REGEX_FMT, pattern));
}
- return entry;
+ return Optional.of(entry);
}
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
similarity index 63%
rename from
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java
rename to
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
index a1f6582c..8f0fc5ef 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
@@ -19,39 +19,45 @@
package org.apache.rat.config.exclusion.fileProcessors;
import java.io.File;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
/**
* A file processor for the {@code .csvignore} file.
+ * @see <a
href="https://www.gnu.org/software/trans-coord/manual/cvs/html_node/cvsignore.html#cvsignore">Ignoring
files via cvsignore</a>
+ * <p>
+ * The patterns found in {@code .csvignore} are only valid for the
directory that contains them, not for any subdirectories.
+ * </p>
*/
-public class CVSFileProcessor extends DescendingFileProcessor {
+public class CVSIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* The constructor.
*/
- public CVSFileProcessor() {
- super(".cvsignore", (String) null);
+ public CVSIgnoreBuilder() {
+ super(".cvsignore", (String) null, true);
}
@Override
- protected List<String> process(final DocumentName documentName) {
+ protected MatcherSet process(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
final File dir = new File(documentName.getName());
- List<String> result = new ArrayList<>();
+ Set<String> result = new HashSet<>();
Iterator<String> iter = ExclusionUtils.asIterator(dir,
StringUtils::isNotBlank);
while (iter.hasNext()) {
String line = iter.next();
String[] parts = line.split("\\s+");
for (String part : parts) {
if (!part.isEmpty()) {
- result.add(this.localizePattern(documentName, part));
+ result.add(ExclusionUtils.qualifyPattern(documentName,
part));
}
}
}
- return result;
+ return new MatcherSet.Builder().addExcluded(documentName,
result).build();
}
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
deleted file mode 100644
index 438f0075..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.rat.config.exclusion.fileProcessors;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Predicate;
-
-import org.apache.commons.io.filefilter.DirectoryFileFilter;
-import org.apache.commons.io.filefilter.NameFileFilter;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.rat.config.exclusion.ExclusionUtils;
-import org.apache.rat.config.exclusion.FileProcessor;
-import org.apache.rat.document.DocumentName;
-
-/**
- * A FileProcessor that assumes the files contain the already formatted
strings and just need to be
- * localized for the fileName.
- */
-public class DescendingFileProcessor extends FileProcessor {
- /** The name of the file being processed */
- private final String fileName;
- /** The predicate that will return {@code false} for any comment line in
the file. */
- protected final Predicate<String> commentFilter;
-
- /**
- * Constructor.
- * @param fileName The name of the file to process.
- * @param commentPrefix the comment prefix
- */
- public DescendingFileProcessor(final String fileName, final String
commentPrefix) {
- this(fileName, commentPrefix == null ? null :
Collections.singletonList(commentPrefix));
- }
-
- /**
- * Constructor.
- * @param fileName name of the file to process
- * @param commentPrefixes a collection of comment prefixes.
- */
- public DescendingFileProcessor(final String fileName, final
Iterable<String> commentPrefixes) {
- super();
- this.fileName = fileName;
- // null prefixes = check prefix may not be blank.
- this.commentFilter = commentPrefixes == null ? StringUtils::isNotBlank
: ExclusionUtils.commentFilter(commentPrefixes);
- }
-
- /**
- * Process by reading the file and return a list of properly formatted
patterns.
- * The default implementation does the following:
- * <ul>
- * <li>reads lines from the file specified by documentName</li>
- * <li>modifies those entries by calling {@link
FileProcessor#modifyEntry(DocumentName, String)}</li>
- * <li>further modifies the entry by calling {@link
FileProcessor#localizePattern(DocumentName, String)}</li>
- * <li>retrieving the name from the resulting DocumentName</li>
- * </ul>
- * @param documentName the file to read.
- * @return the list of properly formatted patterns
- */
- protected List<String> process(final DocumentName documentName) {
- return ExclusionUtils.asIterator(new File(documentName.getName()),
commentFilter)
- .map(entry -> this.modifyEntry(documentName, entry))
- .filter(Objects::nonNull)
- .map(entry -> this.localizePattern(documentName, entry))
- .addTo(new ArrayList<>());
- }
-
- /**
- * Create a list of files by applying the filter to the specified
directory.
- * @param dir the directory.
- * @param filter the filter.
- * @return an array of files. May be empty but will not be null.
- */
- private File[] listFiles(final File dir, final FileFilter filter) {
- File[] result = dir.listFiles(filter);
- return result == null ? new File[0] : result;
- }
-
- /**
- * Process the directory tree looking for files that match the filter.
Process any matching file and return
- * a list of fully qualified patterns.
- * @param directory The name of the directory to process.
- * @param fileFilter the filter to detect processable files with.
- * @return the list of fully qualified file patterns.
- */
- protected List<String> checkDirectory(final DocumentName directory, final
FileFilter fileFilter) {
- List<String> fileNames = new ArrayList<>();
- File dirFile = new File(directory.getName());
- for (File f : listFiles(dirFile, fileFilter)) {
-
fileNames.addAll(process(DocumentName.builder(f).setBaseName(directory.getBaseName()).build()));
- }
- for (File dir : listFiles(dirFile, DirectoryFileFilter.DIRECTORY)) {
- fileNames.addAll(checkDirectory(DocumentName.builder(dir).build(),
fileFilter));
- }
- return fileNames;
- }
-
- @Override
- public List<String> apply(final DocumentName dir) {
- return checkDirectory(dir, new NameFileFilter(fileName));
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
deleted file mode 100644
index 8cf2d096..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.rat.config.exclusion.fileProcessors;
-
-import java.io.File;
-
-import org.apache.rat.config.exclusion.plexus.MatchPatterns;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.document.DocumentNameMatcher;
-
-/**
- * Processes the .gitignore file.
- * @see <a href='https://git-scm.com/docs/gitignore'>.gitignore
documentation</a>
- */
-public class GitFileProcessor extends DescendingFileProcessor {
-
- /**
- * Constructs a file processor that processes a .gitignore file and
ignores any lines starting with "#".
- */
- public GitFileProcessor() {
- super(".gitignore", "#");
- }
-
- @Override
- public String modifyEntry(final DocumentName documentName, final String
entry) {
- // An optional prefix "!" which negates the pattern;
- boolean prefix = entry.startsWith("!");
- String pattern = prefix || entry.startsWith("\\#") ||
entry.startsWith("\\!") ? entry.substring(1) : entry;
-
- // If there is a separator at the beginning or middle (or both) of the
pattern, then
- // the pattern is relative to the directory level of the particular
.gitignore file itself.
- // Otherwise, the pattern may also match at any level below the
.gitignore level.
- int slashPos = pattern.indexOf("/");
- // no slash or at end already
- if (slashPos == -1 || slashPos == pattern.length() - 1) {
- pattern = "**/" + pattern;
- }
- if (slashPos == 0) {
- pattern = pattern.substring(1);
- }
- // If there is a separator at the end of the pattern then the pattern
will only match directories,
- // otherwise the pattern can match both files and directories.
- if (pattern.endsWith("/")) {
- pattern = pattern.substring(0, pattern.length() - 1);
- String name = prefix ? "!" + pattern : pattern;
- DocumentName matcherPattern =
DocumentName.builder(documentName).setName(name.replace("/",
documentName.getDirectorySeparator()))
- .build();
- customMatchers.add(DocumentNameMatcher.and(new
DocumentNameMatcher("isDirectory", File::isDirectory),
- new DocumentNameMatcher(name,
MatchPatterns.from(matcherPattern.localized("/")))));
- return null;
- }
- return prefix ? "!" + pattern : pattern;
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
new file mode 100644
index 00000000..cf4e9fb9
--- /dev/null
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.rat.config.exclusion.fileProcessors;
+
+import java.io.File;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.MatchPatterns;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+
+import static org.apache.rat.config.exclusion.ExclusionUtils.NEGATION_PREFIX;
+
+/**
+ * Processes the {@code .gitignore} file.
+ * @see <a href='https://git-scm.com/docs/gitignore'>.gitignore
documentation</a>
+ */
+public class GitIgnoreBuilder extends AbstractFileProcessorBuilder {
+ /** The name of the file we read from */
+ private static final String IGNORE_FILE = ".gitignore";
+ /** The comment prefix */
+ private static final String COMMENT_PREFIX = "#";
+ /** An escaped comment in the .gitignore file. (Not a comment) */
+ private static final String ESCAPED_COMMENT = "\\#";
+ /** An escaped negation in the .gitignore file. (Not a negation) */
+ private static final String ESCAPED_NEGATION = "\\!";
+ /** The slash string */
+ private static final String SLASH = "/";
+
+ /**
+ * Constructs a file processor that processes a {@code .gitignore} file
and ignores any lines starting with {@value #COMMENT_PREFIX}.
+ */
+ public GitIgnoreBuilder() {
+ super(IGNORE_FILE, COMMENT_PREFIX, true);
+ }
+
+ /**
+ * Convert the string entry.
+ * If the string ends with a slash an {@link DocumentNameMatcher#and} is
constructed from a directory check and the file
+ * name matcher. In this case an empty Optional is returned.
+ * If the string starts with {@value ExclusionUtils#NEGATION_PREFIX} then
the entry is placed in the include list, otherwise
+ * the entry is placed in the exclude list and the name of the check
returned.
+ * @param documentName The name of the document being processed.
+ * @param entry The entry from the document
+ * @return and Optional containing the name of the matcher.
+ */
+ @Override
+ protected Optional<String> modifyEntry(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName documentName, final String entry) {
+ // An optional prefix "!" which negates the pattern;
+ boolean prefix = entry.startsWith(NEGATION_PREFIX);
+ String pattern = prefix || entry.startsWith(ESCAPED_COMMENT) ||
entry.startsWith(ESCAPED_NEGATION) ?
+ entry.substring(1) : entry;
+
+ // If there is a separator at the beginning or middle (or both) of the
pattern, then
+ // the pattern is relative to the directory level of the particular
.gitignore file itself.
+ // Otherwise, the pattern may also match at any level below the
.gitignore level.
+ int slashPos = pattern.indexOf(SLASH);
+ // no slash or at end already
+ if (slashPos == -1 || slashPos == pattern.length() - 1) {
+ pattern = "**/" + pattern;
+ }
+ if (slashPos == 0) {
+ pattern = pattern.substring(1);
+ }
+ // If there is a separator at the end of the pattern then the pattern
will only match directories,
+ // otherwise the pattern can match both files and directories.
+ if (pattern.endsWith(SLASH)) {
+ pattern = pattern.substring(0, pattern.length() - 1);
+ String name = prefix ? NEGATION_PREFIX + pattern : pattern;
+ DocumentName matcherPattern =
DocumentName.builder(documentName).setName(name.replace(SLASH,
documentName.getDirectorySeparator()))
+ .build();
+ DocumentNameMatcher matcher = DocumentNameMatcher.and(new
DocumentNameMatcher("isDirectory", File::isDirectory),
+ new DocumentNameMatcher(name,
MatchPatterns.from(matcherPattern.localized(documentName.getDirectorySeparator()))));
+
+ MatcherSet.Builder builder = new MatcherSet.Builder();
+ if (prefix) {
+ builder.addIncluded(matcher);
+ } else {
+ builder.addExcluded(matcher);
+ }
+ matcherSetConsumer.accept(builder.build());
+ return Optional.empty();
+ }
+ return Optional.of(prefix ? NEGATION_PREFIX + pattern : pattern);
+ }
+}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
similarity index 59%
rename from
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java
rename to
apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
index d88e60c5..1698d85b 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
@@ -18,19 +18,23 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.List;
import java.util.Locale;
+import java.util.Optional;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
import static java.lang.String.format;
/**
* A processor for the {@code .hgignore} files.
+ * @see <a href="https://wiki.mercurial-scm.org/.hgignore">Mecurial how to
ignore files</a>
+ * @see <a href="https://www.selenic.com/mercurial/hgignore.5.html">syntax for
Mercurial ignore files</a>
*/
-public final class HgIgnoreProcessor extends DescendingFileProcessor {
+public final class HgIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* The state enumeration for the processor. When processing the file the
processor changes
* syntax state depending on the input.
@@ -48,30 +52,38 @@ public final class HgIgnoreProcessor extends
DescendingFileProcessor {
private Syntax state;
/**
- * Constructs the .hgignore processor.
+ * Constructs the {@code .hgignore} processor.
*/
- public HgIgnoreProcessor() {
- super(".hgignore", "#");
+ public HgIgnoreBuilder() {
+ super(".hgignore", "#", true);
state = Syntax.REGEXP;
}
@Override
- protected List<String> process(final DocumentName baseName) {
+ protected MatcherSet process(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
state = Syntax.REGEXP;
- return super.process(baseName);
+ return super.process(matcherSetConsumer, root, documentName);
}
@Override
- public String modifyEntry(final DocumentName baseName, final String entry)
{
+ public Optional<String> modifyEntry(final Consumer<MatcherSet>
matcherSetConsumer, final DocumentName documentName, final String entry) {
Matcher m = SYNTAX_CHECK.matcher(entry.toLowerCase(Locale.ROOT));
if (m.matches()) {
state = Syntax.valueOf(m.group(1).toUpperCase());
- return null;
+ return Optional.empty();
}
+ /*
+ Neither glob nor regexp patterns are rooted. A glob-syntax pattern of
the form *.c will match a file ending in .c
+ in any directory, and a regexp pattern of the form \.c$ will do the
same. To root a regexp pattern, start it with ^.
+ */
if (state == Syntax.REGEXP) {
String pattern = entry.startsWith("^") ? entry.substring(1) : ".*"
+ entry;
- return format(REGEX_FMT, pattern);
+ return Optional.of(format(REGEX_FMT, pattern));
+ } else {
+ if (entry.startsWith("*")) {
+ return Optional.of("**/" + entry);
+ }
}
- return entry;
+ return Optional.of(entry);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
b/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
index 06202375..8623c175 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
@@ -85,7 +85,7 @@ public final class Help extends AbstractHelp {
helpFormatter.printWrapped(writer, helpFormatter.getWidth(),
helpFormatter.getLeftPadding() + HELP_PADDING + HELP_PADDING,
argumentPadding + "Provides a path matcher: " +
sc.hasStaticDocumentNameMatcher());
helpFormatter.printWrapped(writer, helpFormatter.getWidth(),
helpFormatter.getLeftPadding() + HELP_PADDING + HELP_PADDING,
- argumentPadding + "Provides a file processor: " +
sc.fileProcessor().hasNext());
+ argumentPadding + "Provides a file processor: " +
sc.fileProcessorBuilder().hasNext());
}
writer.println("\nA path matcher will match specific information about
the file.");
writer.println("\nA file processor will process the associated
\"ignore\" file for include and exclude directives");
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
index 5a9186f8..9f62c6fc 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
@@ -36,7 +36,7 @@ public class StandardCollectionTest {
@ParameterizedTest
@MethodSource("collectionData")
public void testState(StandardCollection scm, boolean hasFileProcessor,
boolean hasPathMatchSupplier, boolean hasPatterns) {
- assertEquals(hasFileProcessor, scm.fileProcessor().hasNext(), () ->
scm.name() + " FileProcessor state wrong.");
+ assertEquals(hasFileProcessor, scm.fileProcessorBuilder().hasNext(),
() -> scm.name() + " MatcherSet state wrong.");
assertEquals(hasPathMatchSupplier, scm.hasStaticDocumentNameMatcher(),
() -> scm.name() + " PathMatcherSupplier state wrong.");
assertEquals(hasPatterns, !scm.patterns().isEmpty(), () -> scm.name()
+ " patterns state wrong.");
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java
new file mode 100644
index 00000000..09c330f8
--- /dev/null
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.rat.config.exclusion.fileProcessors;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.SelectorUtils;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+import org.apache.rat.document.DocumentNameMatcherTest;
+import org.apache.rat.document.FSInfoTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.junit.jupiter.params.provider.Arguments;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The base class for FileProcessor builder tests.
+ * Provides supporting methods for creating test files and for validating
results.
+ */
+public class AbstractIgnoreBuilderTest {
+
+ @TempDir
+ protected Path tmpPath;
+ protected DocumentName baseName;
+
+ @BeforeEach
+ protected void setup() throws IOException {
+ baseName = DocumentName.builder(tmpPath.toFile()).build();
+ }
+
+ @AfterEach
+ @EnabledOnOs(OS.WINDOWS)
+ void reset() {
+ baseName = null;
+ }
+
+ /**
+ * This method is a known workaround for
+ * {@link <a href="https://github.com/junit-team/junit5/issues/2811">junit
5 issue #2811</a> }.
+ */
+ @AfterEach
+ @EnabledOnOs(OS.WINDOWS)
+ void cleanUp() {
+ System.gc();
+ }
+
+ /**
+ * Writes a text file to the baseDir directory.
+ * @param name the name of the file.
+ * @param lines the lines to write to the file.
+ * @return the File that was written.
+ * @throws IOException if file cannot be created.
+ */
+ protected File writeFile(String name, Iterable<String> lines) throws
IOException {
+ File file = new File(tmpPath.toFile(), name);
+ try (PrintWriter writer = new PrintWriter(new FileWriter(file))) {
+ lines.forEach(writer::println);
+ }
+ return file;
+ }
+
+ /**
+ * Asserts the correctness of the excluder. An excluder returns false if
the document name is matched.
+ * @param builder An FileProcessorBuilder that will create the excluder.
+ * @param matching the matching strings.
+ * @param notMatching the non-matching strings.
+ */
+ protected void assertCorrect(AbstractFileProcessorBuilder builder,
Iterable<String> matching, Iterable<String> notMatching) {
+ assertCorrect(builder.build(baseName), baseName, matching,
notMatching);
+ }
+
+ /**
+ * Asserts the correctness of the excluder. An excluder returns false if
the document name is matched.
+ * @param matcherSets the list of matchers to create the
DocumentNameMatcher from.
+ * @param baseDir the base directory for the excluder test.
+ * @param matching the matching strings.
+ * @param notMatching the non-matching strings.
+ */
+ protected void assertCorrect(List<MatcherSet> matcherSets, DocumentName
baseDir, Iterable<String> matching, Iterable<String> notMatching) {
+ DocumentNameMatcher excluder =
MatcherSet.merge(matcherSets).createMatcher();
+ for (String name : matching) {
+ DocumentName docName =
baseDir.resolve(SelectorUtils.extractPattern(name,
baseDir.getDirectorySeparator()));
+ assertThat(excluder.matches(docName)).as(() ->
DocumentNameMatcherTest.processDecompose(excluder, docName)).isFalse();
+ }
+ for (String name : notMatching) {
+ DocumentName docName =
baseDir.resolve(SelectorUtils.extractPattern(name,
baseDir.getDirectorySeparator()));
+ assertThat(excluder.matches(docName)).as(() ->
DocumentNameMatcherTest.processDecompose(excluder, docName)).isTrue();
+ }
+ }
+}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
deleted file mode 100644
index 741a1ab4..00000000
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.rat.config.exclusion.fileProcessors;
-
-import org.apache.rat.document.DocumentName;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.condition.EnabledOnOs;
-import org.junit.jupiter.api.condition.OS;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-public class AbstractIgnoreProcessorTest {
-
- @TempDir
- protected File baseDir;
- protected DocumentName baseName;
-
- @BeforeEach
- public void setup() {
- baseName = DocumentName.builder(baseDir).build();
- }
-
- /**
- * This method is a known workaround for
- * {@link <a href="https://github.com/junit-team/junit5/issues/2811">junit
5 issue #2811</a> }.
- */
- @AfterEach
- @EnabledOnOs(OS.WINDOWS)
- void cleanUp() {
- System.gc();
- }
-
- protected File writeFile(String name, Iterable<String> lines) throws
IOException {
- File file = new File(baseDir, name);
- try (PrintWriter writer = new PrintWriter(new FileWriter(file))) {
- lines.forEach(writer::println);
- }
- return file;
- }
-
-}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
similarity index 58%
copy from
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
copy to
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
index 7900fd7e..dc3c352c 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
@@ -18,32 +18,26 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.ArrayList;
-
-import org.apache.rat.utils.ExtendedIterator;
import org.junit.jupiter.api.Test;
-import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class CVSFileProcessorTest extends AbstractIgnoreProcessorTest {
+public class BazaarIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
@Test
public void processExampleFileTest() throws IOException {
String[] lines = {
- "thingone thingtwo", System.lineSeparator(), "one_fish",
"two_fish", "", "red_* blue_*"};
+ "# a comment", "*.elc", "*.pyc", "*~", System.lineSeparator(),
+ "# switch to regexp syntax.", "RE:^\\.pc" };
- List<String> expected =
ExtendedIterator.create(Arrays.asList("thingone", "thingtwo", "one_fish",
"two_fish", "red_*", "blue_*").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
+ List<String> matching = Arrays.asList("test.elc", "test.pyc",
"test.thing~", ".pc");
+ List<String> notMatching = Arrays.asList("test.foo", ".pc/stuff",
"subidr/test.elc");
- writeFile(".cvsignore", Arrays.asList(lines));
+ writeFile(".bzrignore", Arrays.asList(lines));
- CVSFileProcessor processor = new CVSFileProcessor();
- List<String> actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ assertCorrect(new BazaarIgnoreBuilder(), matching, notMatching);
}
+
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
similarity index 65%
rename from
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
rename to
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
index 7900fd7e..7a0d37dc 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
@@ -18,32 +18,29 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.ArrayList;
-
-import org.apache.rat.utils.ExtendedIterator;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.document.DocumentNameMatcher;
import org.junit.jupiter.api.Test;
-import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class CVSFileProcessorTest extends AbstractIgnoreProcessorTest {
+public class CVSIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
@Test
public void processExampleFileTest() throws IOException {
String[] lines = {
"thingone thingtwo", System.lineSeparator(), "one_fish",
"two_fish", "", "red_* blue_*"};
- List<String> expected =
ExtendedIterator.create(Arrays.asList("thingone", "thingtwo", "one_fish",
"two_fish", "red_*", "blue_*").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
+ List<String> matching = Arrays.asList("thingone", "thingtwo",
"one_fish", "two_fish", "red_fish", "blue_fish");
+ List<String> notMatching = Arrays.asList("thing", "two", "fish_red",
"subdir/two_fish", "subdir/red_fish", "subdir/blue_fish");
writeFile(".cvsignore", Arrays.asList(lines));
- CVSFileProcessor processor = new CVSFileProcessor();
- List<String> actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ CVSIgnoreBuilder processor = new CVSIgnoreBuilder();
+ DocumentNameMatcher matcher =
MatcherSet.merge(processor.build(baseName)).createMatcher();
+
+ assertCorrect(new CVSIgnoreBuilder(), matching, notMatching);
}
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
deleted file mode 100644
index e3343c1d..00000000
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.rat.config.exclusion.fileProcessors;
-
-import java.util.ArrayList;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.utils.ExtendedIterator;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DescendingFileProcessorTest extends AbstractIgnoreProcessorTest {
-
- @Test
- public void singleDirectoryTest() throws IOException {
- String[] lines = {"*.ext", "fname.*", "**/fname.ext"};
-
- List<String> expected =
ExtendedIterator.create(Arrays.asList(lines).iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
-
- writeFile("test.txt", Arrays.asList(lines));
- DocumentName documentName = DocumentName.builder(baseDir).build();
-
- DescendingFileProcessor processor = new
DescendingFileProcessor("test.txt", "#");
- List<String> actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
- }
-
- @Test
- public void layeredDirectoryTest() throws IOException {
- String[] lines = {"*.ext", "fname.*", "**/fname.ext"};
-
- List<String> expected =
ExtendedIterator.create(Arrays.asList(lines).iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
-
- writeFile("test.txt", Arrays.asList(lines));
-
- File subdir = new File(baseDir, "subdir");
- assertThat(subdir.mkdirs()).as("Could not make subdirectory").isTrue();
-
- writeFile("subdir/test.txt", Collections.singletonList("foo.*"));
- expected.add(new File(subdir, "foo.*").getPath());
-
- DescendingFileProcessor processor = new
DescendingFileProcessor("test.txt", "#");
- List<String> actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
- }
-}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
deleted file mode 100644
index 3166b4ca..00000000
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.rat.config.exclusion.fileProcessors;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.stream.Stream;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.document.DocumentNameMatcher;
-import org.apache.rat.utils.ExtendedIterator;
-import org.junit.Ignore;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class GitFileProcessorTest extends AbstractIgnoreProcessorTest {
-
- @Test
- public void processExampleFileTest() throws IOException {
- String[] lines = {
- "# somethings",
- "!thingone", "thing*", System.lineSeparator(),
- "# some fish",
- "**/fish", "*_fish",
- "# some colorful directories",
- "red/", "blue/*/"};
-
- List<String> expected =
ExtendedIterator.create(Arrays.asList("**/thing*", "**/fish",
"**/*_fish").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
- expected.add(0, "!"+new File(baseDir, "**/thingone").getPath());
- // "thingone",
- writeFile(".gitignore", Arrays.asList(lines));
-
- GitFileProcessor processor = new GitFileProcessor();
- List<String> actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
-
- actual.clear();
- processor.customDocumentNameMatchers().forEach(x ->
actual.add(x.toString()));
- expected.clear();
- ExtendedIterator.create(Arrays.asList("**/red", "blue/*").iterator())
- .map(s -> String.format("and(isDirectory, %s)", s))
- .forEachRemaining(expected::add);
- assertThat(actual).isEqualTo(expected);
- }
-
- // see https://git-scm.com/docs/gitignore
- @ParameterizedTest
- @MethodSource("modifyEntryData")
- public void modifyEntryTest(String source, String expected) {
- GitFileProcessor underTest = new GitFileProcessor();
- DocumentName testName =
DocumentName.builder().setName("GitFileProcessorTest").setBaseName("testDir").build();
- if (source.endsWith("/")) {
- assertThat(underTest.modifyEntry(testName,
source)).isEqualTo(null);
- Iterator<DocumentNameMatcher> iter =
underTest.customDocumentNameMatchers().iterator();
- assertThat(iter).hasNext();
-
assertThat(iter.next().toString()).isEqualTo(String.format("and(isDirectory,
%s)", expected));
- } else {
- assertThat(underTest.modifyEntry(testName,
source)).isEqualTo(expected);
-
assertThat(underTest.customDocumentNameMatchers().iterator().hasNext()).isFalse();
- }
- }
-
- private static Stream<Arguments> modifyEntryData() {
- List<Arguments> lst = new ArrayList<>();
-
- lst.add(Arguments.of("\\#filename", "**/#filename"));
-
- lst.add(Arguments.of("!#filename", "!**/#filename"));
- lst.add(Arguments.of("\\#filename", "**/#filename"));
- lst.add(Arguments.of("!#filename", "!**/#filename"));
- lst.add(Arguments.of("/filename", "filename"));
- lst.add(Arguments.of("file/name", "file/name"));
- lst.add(Arguments.of("/file/name", "file/name"));
- lst.add(Arguments.of("filename", "**/filename"));
- lst.add(Arguments.of("filename/", "**/filename"));
- lst.add(Arguments.of("/filename/", "filename"));
-
- return lst.stream();
- }
-
- @Test
- @Ignore("RAT-335 ")
- public void test_RAT_335() {
- GitFileProcessor underTest = new GitFileProcessor();
- URL url =
GitFileProcessorTest.class.getClassLoader().getResource("RAT_355/src/");
- File file = new File(url.getFile());
-
- DocumentName documentName =
DocumentName.builder(file).setBaseName(File.separator).build();
- List<String> lst = underTest.apply(documentName);
- System.out.println(lst);
- }
-}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
new file mode 100644
index 00000000..60f73442
--- /dev/null
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.rat.config.exclusion.fileProcessors;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+import org.apache.rat.document.FSInfoTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GitIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
+
+ @Test
+ public void processExampleFileTest() throws IOException {
+ try {
+ String[] lines = {
+ "# somethings",
+ "!thingone", "thing*", System.lineSeparator(),
+ "# some fish",
+ "**/fish", "*_fish",
+ "# some colorful directories",
+ "red/", "blue/*/"};
+ List<String> matches = Arrays.asList("some/things", "some/fish",
"another/red_fish");
+
+ List<String> notMatches = Arrays.asList("some/thingone",
"thingone");
+
+ writeFile(".gitignore", Arrays.asList(lines));
+
+ assertCorrect(new GitIgnoreBuilder(), matches, notMatches);
+ } finally {
+ System.getProperties().remove("FSInfo");
+ }
+ }
+
+ // see https://git-scm.com/docs/gitignore
+ @ParameterizedTest
+ @MethodSource("modifyEntryData")
+ public void modifyEntryTest(DocumentName.FSInfo fsInfo, String source,
String expected) {
+ GitIgnoreBuilder underTest = new GitIgnoreBuilder();
+ DocumentName testName =
DocumentName.builder(fsInfo).setName("GitIgnoreBuilderTest").setBaseName("testDir").build();
+ List<MatcherSet> matcherSets = new ArrayList<>();
+ Optional<String> entry = underTest.modifyEntry(matcherSets::add,
testName, source);
+
+ if (source.endsWith("/")) {
+ assertThat(entry).isNotPresent();
+ assertThat(matcherSets).hasSize(1);
+ DocumentNameMatcher matcher = matcherSets.get(0).createMatcher();
+ assertThat(matcher.toString()).isEqualTo(expected);
+ } else {
+ assertThat(entry.get()).isEqualTo(expected);
+ }
+ }
+
+ private static Stream<Arguments> modifyEntryData() {
+ List<Arguments> lst = new ArrayList<>();
+ for (DocumentName.FSInfo fsInfo : FSInfoTest.TEST_SUITE) {
+ lst.add(Arguments.of(fsInfo, "\\#filename", "**/#filename"));
+
+ lst.add(Arguments.of(fsInfo, "!#filename", "!**/#filename"));
+ lst.add(Arguments.of(fsInfo, "\\#filename", "**/#filename"));
+ lst.add(Arguments.of(fsInfo, "!#filename", "!**/#filename"));
+ lst.add(Arguments.of(fsInfo, "/filename", "filename"));
+ lst.add(Arguments.of(fsInfo, "file/name", "file/name"));
+ lst.add(Arguments.of(fsInfo, "/file/name", "file/name"));
+ lst.add(Arguments.of(fsInfo, "filename", "**/filename"));
+ lst.add(Arguments.of(fsInfo, "filename/", "not(and(isDirectory,
**/filename))"));
+ lst.add(Arguments.of(fsInfo, "/filename/", "not(and(isDirectory,
filename))"));
+ // inclusion by itself becomes nothing.
+ lst.add(Arguments.of(fsInfo, "!filename/", "TRUE"));
+ }
+ return lst.stream();
+ }
+
+ private void assertMatches(DocumentName documentName, DocumentNameMatcher
matcher, String[] matching, String[] notMatching) {
+ for (String test : matching) {
+ DocumentName name = documentName.resolve(test);
+ assertThat(matcher.matches(name)).as(test).isTrue();
+ }
+ for (String test: notMatching) {
+ DocumentName name = documentName.resolve(test);
+ assertThat(matcher.matches(name)).as(test).isFalse();
+ }
+ }
+
+ @Test
+ public void test_RAT_335() {
+ GitIgnoreBuilder underTest = new GitIgnoreBuilder();
+ URL url =
GitIgnoreBuilderTest.class.getClassLoader().getResource("GitIgnoreBuilderTest/src/");
+ File file = new File(url.getFile());
+
+ DocumentName documentName = DocumentName.builder(file).build();
+ List<MatcherSet> matcherSets = underTest.build(documentName);
+ DocumentNameMatcher matcher =
MatcherSet.merge(matcherSets).createMatcher();
+
+ DocumentName candidate = DocumentName.builder()
+
.setName("/home/claude/apache/creadur-rat/apache-rat-core/target/test-classes/GitIgnoreBuilderTest/src/dir1/file1.log")
+
.setBaseName("home/claude/apache/creadur-rat/apache-rat-core/target/test-classes/GitIgnoreBuilderTest/src/").build();
+ System.out.println("Decomposition for "+candidate);
+
+ assertThat(matcher.toString()).isEqualTo("matcherSet(or('included
dir1/.gitignore', 'included .gitignore'), or('excluded dir1/.gitignore',
**/.gitignore, 'excluded .gitignore'))");
+
+ List<String> notMatching = Arrays.asList("README.txt", "dir1/dir1.md",
"dir2/dir2.txt", "dir3/file3.log", "dir1/file1.log");
+
+ List<String> matching = Arrays.asList(".gitignore", "root.md",
"dir1/.gitignore", "dir1/dir1.txt", "dir2/dir2.md", "dir3/dir3.log");
+
+ assertCorrect(matcherSets, documentName.getBaseDocumentName(),
matching, notMatching);
+ }
+}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
similarity index 53%
rename from
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java
rename to
apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
index 3085792c..d91a157e 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
@@ -18,49 +18,37 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.ArrayList;
-import org.apache.rat.utils.ExtendedIterator;
import org.junit.jupiter.api.Test;
-import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static java.lang.String.format;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class HgIgnoreProcessorTest extends AbstractIgnoreProcessorTest {
+public class HgIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
@Test
public void processExampleFileTest() throws IOException {
String[] lines = {
- "# use glob syntax.", "syntax: glob", "*.elc", "*.pyc", "*~",
System.lineSeparator(),
- "# switch to regexp syntax.", "syntax: regexp", "^\\.pc/" };
+ "# use glob syntax.", "syntax: glob", "*.elc", "*.pyc", "*~", "*.c",
System.lineSeparator(),
+ "# switch to regexp syntax.", "syntax: regexp", "^\\.pc" };
- List<String> expected = ExtendedIterator.create(Arrays.asList("*.elc",
"*.pyc", "*~").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new
ArrayList<>());
- expected.add(format("%%regex[\\Q%s%s\\E%s]", baseDir.getPath(),
File.separatorChar, "\\.pc/"));
+ List<String> matching = Arrays.asList("test.elc", "test.pyc",
"subdir/test.pyc", "test.thing~", ".pc", "foo.c", "/subdir/foo.c" );
+ List<String> notMatching = Arrays.asList("test.foo",
"test.thing~/subdir", ".pc/subdir");
writeFile(".hgignore", Arrays.asList(lines));
- HgIgnoreProcessor processor = new HgIgnoreProcessor();
- List<String> actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ assertCorrect(new HgIgnoreBuilder(), matching, notMatching);
}
@Test
public void processDefaultFileTest() throws IOException {
- String[] lines = {"^[A-Z]*\\.txt", "[0-9]*\\.txt"};
+ String[] lines = {"^[A-Z]*\\.txt", "[0-9]+\\.txt"};
- List<String> expected =
ExtendedIterator.create(Arrays.asList("[A-Z]*\\.txt",
".*[0-9]*\\.txt").iterator())
- .map(s -> format("%%regex[\\Q%s%s\\E%s]", baseDir.getPath(),
File.separatorChar, s))
- .addTo(new ArrayList<>());
+ List<String> matching = Arrays.asList("ABIGNAME.txt", "endsIn9.txt");
+ List<String> notMatching = Arrays.asList("asmallName.txt",
"endsin.doc");
writeFile(".hgignore", Arrays.asList(lines));
- HgIgnoreProcessor processor = new HgIgnoreProcessor();
- List<String> actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ assertCorrect(new HgIgnoreBuilder(), matching, notMatching);
}
}
diff --git a/apache-rat-core/src/test/resources/RAT_355/commandLine.txt
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/commandLine.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/commandLine.txt
rename to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/commandLine.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/expected-message.txt
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/expected-message.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/expected-message.txt
rename to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/expected-message.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/pom.xml
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/pom.xml
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/pom.xml
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/pom.xml
diff --git
a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
new file mode 100644
index 00000000..8855fa80
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
@@ -0,0 +1,7 @@
+*.md
+
+# This makes it ignore dir3/dir3.log and dir3/file3.log
+*.log
+
+# This makes it "unignore" dir3/file3.log
+!file*.log
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/README.txt
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/README.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/README.txt
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/README.txt
diff --git
a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
new file mode 100644
index 00000000..26fd5c95
--- /dev/null
+++
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+!dir1.md
+file1.log
\ No newline at end of file
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.md
similarity index 100%
copy from apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
copy to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.md
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.txt
similarity index 100%
copy from apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt
copy to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/file1.log
similarity index 100%
copy from apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log
copy to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/file1.log
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md
similarity index 100%
copy from apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
copy to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt
rename to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log
similarity index 100%
copy from apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
copy to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log
rename to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/invoker.properties
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/invoker.properties
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/invoker.properties
rename to
apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/invoker.properties
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md
diff --git a/apache-rat-core/src/test/resources/RAT_355/verify.groovy
b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/verify.groovy
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/verify.groovy
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/verify.groovy