Skip to content

Commit 140d714

Browse files
committed
potentially fix bobs code
1 parent 90e4fdb commit 140d714

File tree

1 file changed

+59
-61
lines changed

1 file changed

+59
-61
lines changed

src/main/java/com/dtsx/docs/core/planner/TestPlanBuilder.java

Lines changed: 59 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
import com.dtsx.docs.core.runner.tests.strategies.test.CompilesTestStrategy;
1313
import com.dtsx.docs.core.runner.tests.strategies.test.SnapshotTestStrategy;
1414
import com.dtsx.docs.lib.CliLogger;
15+
import lombok.SneakyThrows;
1516
import lombok.val;
1617
import org.apache.commons.lang3.tuple.Pair;
1718

1819
import java.io.IOException;
20+
import java.nio.file.FileSystems;
1921
import java.nio.file.Files;
2022
import java.nio.file.Path;
23+
import java.nio.file.PathMatcher;
2124
import java.util.*;
2225
import java.util.function.Predicate;
2326
import java.util.regex.Pattern;
@@ -66,10 +69,8 @@ public static TestPlan buildPlan(TestCtx ctx) {
6669
CliLogger.println(true, "@|bold Building test plan...|@");
6770
CliLogger.println(true, "@!->!@ Found " + testRoots.size() + " test roots");
6871

69-
// Build gitignore predicate once at the start
70-
val gitignorePredicate = buildGitignorePredicate(ctx.examplesFolder());
71-
7272
val builder = new Builder();
73+
val gitignorePredicate = buildGitignorePredicate(ctx.examplesFolder());
7374

7475
for (val rootPath : testRoots) {
7576
mkTestRoot(ctx, rootPath, gitignorePredicate).ifPresent(builder::addRoot);
@@ -137,72 +138,70 @@ private static List<Path> findTestRoots(Path examplesFolder) {
137138
/// - `**/obj/*` - matches obj directory at any depth
138139
/// - `target/*` - matches target directory at root level
139140
///
140-
/// @param examplesFolder the examples folder to look for .gitignore
141141
/// @return a predicate that returns true if a path should be ignored
142-
private static Predicate<Path> buildGitignorePredicate(Path examplesFolder) {
143-
val gitignorePath = examplesFolder.resolve(".gitignore");
142+
@SneakyThrows
143+
private static Predicate<Path> buildGitignorePredicate(Path rootFolder) {
144+
val gitignorePath = rootFolder.resolve(".gitignore");
144145

145146
if (!Files.exists(gitignorePath)) {
146-
// No .gitignore file, don't ignore anything
147-
return path -> false;
147+
return _ -> false;
148148
}
149149

150-
try {
151-
val patterns = Files.readAllLines(gitignorePath).stream()
152-
.map(String::trim)
153-
.filter(line -> !line.isEmpty() && !line.startsWith("#"))
154-
.map(TestPlanBuilder::gitignorePatternToRegex)
155-
.map(Pattern::compile)
156-
.collect(Collectors.toList());
157-
158-
return path -> {
159-
val pathStr = path.toString();
160-
return patterns.stream().anyMatch(pattern -> pattern.matcher(pathStr).find());
161-
};
162-
} catch (IOException e) {
163-
CliLogger.println(false, "@|yellow Warning: Failed to read .gitignore file, ignoring it|@");
164-
return path -> false;
150+
val lines = Files.readAllLines(gitignorePath);
151+
152+
val fs = FileSystems.getDefault();
153+
154+
val excludeMatchers = new ArrayList<PathMatcher>();
155+
val includeMatchers = new ArrayList<PathMatcher>();
156+
157+
for (var line : lines) {
158+
line = line.trim();
159+
160+
if (line.isEmpty() || line.startsWith("#")) {
161+
continue;
162+
}
163+
164+
val negated = line.startsWith("!");
165+
166+
if (negated) {
167+
line = line.substring(1);
168+
}
169+
170+
if (line.endsWith("/")) {
171+
line = line + "**";
172+
}
173+
174+
if (!line.startsWith("/")) {
175+
line = "**/" + line;
176+
} else {
177+
line = line.substring(1);
178+
}
179+
180+
val matcher = fs.getPathMatcher("glob:" + line);
181+
182+
if (negated) {
183+
includeMatchers.add(matcher);
184+
} else {
185+
excludeMatchers.add(matcher);
186+
}
165187
}
166-
}
167188

168-
/// Converts a gitignore pattern to a regex pattern.
169-
///
170-
/// Handles common gitignore patterns:
171-
/// - `**` matches any number of directories
172-
/// - `*` matches any characters except directory separator
173-
/// - Literal directory separators
174-
///
175-
/// @param gitignorePattern the gitignore pattern (e.g., "**/bin/*")
176-
/// @return a regex pattern string
177-
private static String gitignorePatternToRegex(String gitignorePattern) {
178-
// Escape special regex characters except * and /
179-
String regex = gitignorePattern
180-
.replace("\\", "\\\\")
181-
.replace(".", "\\.")
182-
.replace("+", "\\+")
183-
.replace("?", "\\?")
184-
.replace("|", "\\|")
185-
.replace("(", "\\(")
186-
.replace(")", "\\)")
187-
.replace("[", "\\[")
188-
.replace("]", "\\]")
189-
.replace("{", "\\{")
190-
.replace("}", "\\}")
191-
.replace("^", "\\^")
192-
.replace("$", "\\$");
193-
194-
// Convert gitignore wildcards to regex
195-
regex = regex.replace("**/", "(.*/)?"); // ** matches any number of directories
196-
regex = regex.replace("**", ".*"); // ** at end matches anything
197-
regex = regex.replace("*", "[^/\\\\]*"); // * matches anything except path separator
198-
199-
// Handle both forward and backward slashes
200-
regex = regex.replace("/", "[/\\\\]");
201-
202-
return regex;
189+
return (path) -> {
190+
val relative = rootFolder.relativize(path);
191+
var ignored = false;
192+
193+
for (val matcher : excludeMatchers) {
194+
ignored = ignored || matcher.matches(relative);
195+
}
196+
197+
for (val matcher : includeMatchers) {
198+
ignored = ignored && !matcher.matches(relative);
199+
}
200+
201+
return ignored;
202+
};
203203
}
204204

205-
/// Creates a test root from a directory containing a `meta.yml` file.
206205
///
207206
/// Steps:
208207
/// 1. Parse `meta.yml` configuration
@@ -271,7 +270,6 @@ private static TreeMap<ClientLanguage, Set<Path>> findFilesToTestInRoot(Path roo
271270
return;
272271
}
273272

274-
// Skip files matching .gitignore patterns
275273
if (gitignorePredicate.test(child)) {
276274
return;
277275
}

0 commit comments

Comments
 (0)