
# Datei-Walker

Jeder Modus von Greph (Text, AST, Rewrite, indizierter Text, indizierter AST, zwischengespeicherter AST, Wrapper für `rg` und Wrapper für `sg`) beginnt damit, den Dateibaum zu durchlaufen und ein `Greph\Walker\FileList` zu erstellen. Der Walker wird gemeinsam verwendet, daher gelten überall dieselben Flags und Verhaltensweisen.

## Standardverhalten

Standardmäßig führt der Walker Folgendes aus:

- Durchläuft rekursiv jedes Verzeichnis unterhalb der angegebenen Pfade.
- Berücksichtigt Regeln aus `.gitignore` und `.grephignore` auf jeder Ebene, einschließlich verschachtelter Überschreibungen und Negationen.
- Überspringt das Verzeichnis `.git`.
- Überspringt versteckte Dateien und Verzeichnisse (alles, was mit `.` beginnt).
- Überspringt Binärdateien (erkannt anhand von Null-Bytes in den ersten 512 Bytes der Datei).
- Überspringt Dateien, die größer als 10 MiB sind.
- Folgt keinen symbolischen Links.

## Überschreibungs-Flags

| Flag | Wirkung |
|---|---|
| `--no-ignore` | Regeln aus `.gitignore` und `.grephignore` ignorieren |
| `--hidden` | Versteckte Dateien und Verzeichnisse einschließen |
| `--type NAME` | Nur Dateien einschließen, die zum angegebenen Typalias passen |
| `--type-not NAME` | Dateien ausschließen, die zum angegebenen Typalias passen |
| `--glob GLOB` | Nur Dateien einschließen, deren Pfade auf GLOB passen. Wiederholbar. |

Dieselben Optionen stehen für die programmatische Nutzung über `Greph\Walker\WalkOptions` zur Verfügung.

```php
use Greph\Greph;
use Greph\Walker\FileTypeFilter;
use Greph\Walker\WalkOptions;

$files = Greph::walk('src', new WalkOptions(
    respectIgnore: false,
    includeHidden: true,
    fileTypeFilter: new FileTypeFilter(['php']),
    globPatterns: ['src/**/*.php'],
));
```

## Dateityp-Aliase

Greph enthält eine kleine Auswahl benannter Dateitypen. Jeder Alias wird in eine Liste von Erweiterungen aufgelöst:

| Alias | Erweiterungen |
|---|---|
| `css` | `css`, `sass`, `scss` |
| `html` | `htm`, `html`, `phtml` |
| `js` | `cjs`, `js`, `mjs` |
| `json` | `json` |
| `md` | `markdown`, `md` |
| `php` | `inc`, `php`, `php3`, `php4`, `php5`, `php7`, `php8`, `phpt`, `phtml` |
| `txt` | `txt` |
| `ts` | `ts`, `tsx` |
| `xml` | `xml` |
| `yaml` | `yaml`, `yml` |

Die vollständige Liste steht in `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## .gitignore-Semantik

Greph implementiert die gitignore-Abgleichregeln in reinem PHP. Die Semantik entspricht `git check-ignore`:

- Muster werden relativ zum Verzeichnis ausgewertet, in dem sie stehen.
- Verschachtelte Dateien `.gitignore` überschreiben übergeordnete Regeln.
- Eine Negation (`!pattern`) nimmt einen zuvor ausgeschlossenen Pfad wieder auf.
- Ein abschließendes `/` beschränkt ein Muster auf Verzeichnisse.
- Ein führendes `/` verankert ein Muster im Verzeichnis des `.gitignore`.
- `**` entspricht beliebig vielen Pfadsegmenten.

`.grephignore` verwendet dieselbe Syntax und baut auf `.gitignore` auf. Hier legst du werkzeugspezifische Ausschlüsse fest, die nicht in die Versionsverwaltung gehören.

Die Implementierung liegt in `Greph\Walker\GitignoreFilter`.

## Binärerkennung

Der Walker prüft die ersten 512 Bytes jeder Datei auf Null-Bytes. Enthält eine Datei solche Bytes, wird sie als Binärdatei behandelt und übersprungen. So werden häufige Fälle erkannt, in denen ein Repository Bild-, Archiv- oder kompilierte Dateien in einem indizierten Verzeichnis enthält.

Um trotzdem Binärdateien zu durchsuchen, setze `skipBinaryFiles: false` für das betreffende Objekt `Options`. CLI bietet derzeit kein Flag dafür; verwende die Fassade.

## Symbolische Links

Symbolischen Links wird standardmäßig nicht gefolgt. Setze `followSymlinks: true` (oder übergib `-L` / `--follow` für den Wrapper `rg`), um ihnen zu folgen. Der Walker erfasst besuchte Verzeichnisse, damit Schleifen durch symbolische Links keine Endlosrekursion verursachen.

## Maximale Dateigröße

Dateien, die größer als `maxFileSizeBytes` sind (standardmäßig 10 MiB), werden übersprungen. So wird verhindert, dass versehentlich eine 1-GB-Protokolldatei in den Arbeitsspeicher geladen wird. Du kannst den Grenzwert im Objekt `Options` anpassen, wenn du größere Eingaben abdecken musst.

## Warum ein eigener Walker

Greph könnte sich auf `glob()` oder `RecursiveDirectoryIterator` stützen, aber keines der beiden Werkzeuge setzt die gitignore-Semantik um, versteht `.grephignore` oder lässt sich sauber in den Worker-Pool integrieren. Ein einmal geschriebener und für alle Modi gemeinsam verwendeter Walker stellt außerdem sicher, dass jeder Modus exakt dieselben Filterregeln anwendet. Das ist für die Oracle-gesteuerte Teststrategie entscheidend: Ein Vergleich mit `grep`, `ripgrep` und `ast-grep` ist nur möglich, wenn dieselbe Dateimenge durchlaufen wird wie bei diesen Werkzeugen.
