apply include/exclude globs in search.replace (T-364)

computeReplacements accepted the query's glob filters and silently
dropped them — replace could rewrite files the equivalent search
would never have matched. The grep engine's glob helpers are now
public and shared, so search and replace can't disagree on scope;
both the preview and the apply path go through the filtered list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 00:34:47 +02:00
co-authored by Claude Fable 5
parent 8477e302ef
commit 88d72789f4
6 changed files with 51 additions and 5 deletions
+6
View File
@@ -16,6 +16,7 @@ import 'dart:io';
import '../files/ignore.dart';
import '../files/listing.dart';
import 'grep_engine.dart' show acceptGlobs, globToRegExp;
import 'match.dart';
/// One changed line within a file.
@@ -133,9 +134,14 @@ Future<List<FileReplacement>> computeReplacements({
final walk = await walkFiles(root: root, ignore: ignore);
final rootPath = root.absolute.path;
// Same compiled glob filters as the grep engine — replace must never
// touch a file the equivalent search wouldn't have matched (T-364).
final includes = [for (final g in query.include) globToRegExp(g)];
final excludes = [for (final g in query.exclude) globToRegExp(g)];
final out = <FileReplacement>[];
for (final entry in walk.files) {
if (out.length >= maxFiles) break;
if (!acceptGlobs(entry.path, includes, excludes)) continue;
final fr = _replaceInFile(rootPath, entry.path, query, replacement);
if (fr != null) out.add(fr);
}