
# Walker plików

Każdy tryb Greph (tekstowy, AST, przepisywania, tekst z indeksem, AST z indeksem, AST z pamięci podręcznej, opakowanie `rg`, opakowanie `sg`) rozpoczyna się od przejścia po drzewie plików i utworzenia `Greph\Walker\FileList`. Walker jest współdzielony, więc te same flagi i zachowania obowiązują wszędzie.

## Domyślne działanie

Domyślnie walker:

- Rekurencyjnie przechodzi przez każdy katalog w podanych ścieżkach.
- Respektuje reguły `.gitignore` i `.grephignore` na każdym poziomie, w tym zagnieżdżone nadpisania i negacje.
- Pomija katalog `.git`.
- Pomija ukryte pliki i katalogi (wszystko, co zaczyna się od `.`).
- Pomija pliki binarne (wykrywane na podstawie bajtów zerowych w pierwszych 512 bajtach pliku).
- Pomija pliki większe niż 10 MiB.
- Nie podąża za dowiązaniami symbolicznymi.

## Flagi nadpisywania

| Flaga | Działanie |
|---|---|
| `--no-ignore` | Przestań respektować `.gitignore` i `.grephignore` |
| `--hidden` | Uwzględniaj ukryte pliki i katalogi |
| `--type NAME` | Uwzględniaj tylko pliki pasujące do nazwanego aliasu typu |
| `--type-not NAME` | Wykluczaj pliki pasujące do nazwanego aliasu typu |
| `--glob GLOB` | Uwzględniaj tylko pliki, których ścieżki pasują do GLOB. Można powtarzać. |

Te same opcje są dostępne przez `Greph\Walker\WalkOptions` do użytku programistycznego.

```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'],
));
```

## Aliasy typów plików

Greph zawiera niewielki zestaw nazwanych typów plików. Każdy alias odpowiada liście rozszerzeń:

| Alias | Rozszerzenia |
|---|---|
| `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` |

Pełna lista znajduje się w `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## Semantyka .gitignore

Greph implementuje dopasowywanie zgodne z gitignore w czystym PHP. Semantyka jest zgodna z `git check-ignore`:

- Wzorce są oceniane względem katalogu, w którym się znajdują.
- Zagnieżdżone pliki `.gitignore` nadpisują reguły nadrzędne.
- Negacja (`!pattern`) ponownie uwzględnia wcześniej wykluczoną ścieżkę.
- Końcowe `/` ogranicza wzorzec do katalogów.
- Początkowe `/` zakotwicza wzorzec w katalogu pliku `.gitignore`.
- `**` dopasowuje dowolną liczbę segmentów ścieżki.

`.grephignore` używa tej samej składni i jest nakładany na `.gitignore`. To właściwe miejsce na wykluczenia specyficzne dla narzędzia, których nie chcesz umieszczać w kontroli wersji.

Implementacja znajduje się w `Greph\Walker\GitignoreFilter`.

## Wykrywanie plików binarnych

Walker sprawdza pierwsze 512 bajtów każdego pliku pod kątem bajtów zerowych. Jeśli je znajdzie, uznaje plik za binarny i pomija go. Pozwala to wykryć typowe przypadki, gdy repozytorium zawiera obrazy, archiwa lub skompilowane artefakty w indeksowanym katalogu.

Aby mimo to wyszukiwać w plikach binarnych, ustaw `skipBinaryFiles: false` w odpowiednim obiekcie `Options`. CLI obecnie nie udostępnia flagi w tym celu; użyj fasady.

## Dowiązania symboliczne

Domyślnie dowiązania symboliczne nie są śledzone. Ustaw `followSymlinks: true` (lub przekaż `-L` / `--follow` w opakowaniu `rg`), aby za nimi podążać. Walker śledzi odwiedzone katalogi, więc pętle dowiązań symbolicznych nie powodują nieskończonej rekurencji.

## Maksymalny rozmiar pliku

Pliki większe niż `maxFileSizeBytes` (domyślnie 10 MiB) są pomijane. Chroni to skanowanie przed przypadkowym wczytaniem do pamięci pliku dziennika o rozmiarze 1 GB. Gdy trzeba uwzględnić większe pliki wejściowe, zmień limit w obiekcie `Options`.

## Dlaczego własny walker

Greph mógłby korzystać z `glob()` lub `RecursiveDirectoryIterator`, ale żadne z tych rozwiązań nie implementuje semantyki gitignore, nie rozumie `.grephignore` ani nie integruje się dobrze z pulą procesów roboczych. Napisanie jednego walkera współdzielonego przez różne tryby oznacza też, że każdy tryb stosuje dokładnie te same reguły filtrowania, co ma kluczowe znaczenie dla strategii testów opartej na oracle: porównanie z `grep`, `ripgrep` i `ast-grep` jest możliwe tylko wtedy, gdy walker przechodzi przez ten sam zestaw plików co te narzędzia.
