
# Parcurgător de fișiere

Fiecare mod Greph (text, AST, rescriere, text indexat, AST indexat, AST memorat în cache, wrapper-ul `rg`, wrapper-ul `sg`) începe prin parcurgerea arborelui de fișiere și generarea unui `Greph\Walker\FileList`. Parcurgătorul este partajat, astfel că aceleași flaguri și comportamente se aplică peste tot.

## Comportamentul implicit

Implicit, parcurgătorul:

- Parcurge recursiv fiecare director din căile solicitate.
- Respectă regulile `.gitignore` și `.grephignore` la fiecare nivel, inclusiv suprascrierile și negările imbricate.
- Omite directorul `.git`.
- Omite fișierele și directoarele ascunse (cele al căror nume începe cu `.`).
- Omite fișierele binare (detectate prin octeți nuli în primii 512 octeți ai fișierului).
- Omite fișierele mai mari de 10 MiB.
- Nu urmează legăturile simbolice.

## Flaguri de suprascriere

| Flag | Efect |
|---|---|
| `--no-ignore` | Nu mai respectă `.gitignore` și `.grephignore` |
| `--hidden` | Include fișierele și directoarele ascunse |
| `--type NAME` | Include doar fișierele care corespund aliasului de tip numit |
| `--type-not NAME` | Exclude fișierele care corespund aliasului de tip numit |
| `--glob GLOB` | Include doar fișierele ale căror căi corespund cu GLOB. Poate fi repetat. |

Aceleași opțiuni sunt expuse prin `Greph\Walker\WalkOptions` pentru utilizare programatică.

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

## Aliasuri pentru tipuri de fișiere

Greph include un set restrâns de tipuri de fișiere denumite. Fiecare alias corespunde unei liste de extensii:

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

Lista completă se află în `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## Semantica .gitignore

Greph implementează potrivirea gitignore în PHP pur. Semantica este aliniată cu `git check-ignore`:

- Tiparele sunt evaluate în raport cu directorul în care se află.
- Fișierele `.gitignore` imbricate suprascriu regulile părinte.
- Negarea (`!pattern`) reinclude o cale exclusă anterior.
- `/` la final restricționează un tipar la directoare.
- `/` la început ancorează un tipar în directorul fișierului `.gitignore`.
- `**` corespunde oricărui număr de segmente de cale.

`.grephignore` folosește aceeași sintaxă și se suprapune peste `.gitignore`. Acesta este locul potrivit pentru excluderi specifice instrumentului pe care nu doriți să le includeți în controlul versiunilor.

Implementarea se află în `Greph\Walker\GitignoreFilter`.

## Detectarea fișierelor binare

Parcurgătorul verifică primii 512 octeți din fiecare fișier pentru octeți nuli. Dacă găsește vreunul, fișierul este tratat ca binar și omis. Astfel este detectat cazul obișnuit în care un depozit conține imagini, arhive sau artefacte compilate într-un director indexat.

Pentru a căuta și în fișierele binare, setați `skipBinaryFiles: false` în obiectul `Options` relevant. CLI nu expune momentan un flag pentru acest lucru; folosiți fațada.

## Legături simbolice

Legăturile simbolice nu sunt urmate implicit. Setați `followSymlinks: true` (sau transmiteți `-L` / `--follow` wrapper-ului `rg`) pentru a le urma. Parcurgătorul ține evidența directoarelor vizitate, astfel încât buclele de legături simbolice să nu provoace recursie infinită.

## Dimensiunea maximă a fișierului

Fișierele mai mari de `maxFileSizeBytes` (implicit 10 MiB) sunt omise. Astfel, scanările nu încarcă accidental în memorie un fișier jurnal de 1 GB. Suprascrieți limita în obiectul `Options` când trebuie să procesați intrări mai mari.

## De ce un parcurgător personalizat

Greph ar putea folosi `glob()` sau `RecursiveDirectoryIterator`, dar niciuna nu implementează semantica gitignore, niciuna nu înțelege `.grephignore` și niciuna nu se integrează bine cu pool-ul de workeri. Scrierea parcurgătorului o singură dată și partajarea lui între moduri înseamnă, de asemenea, că fiecare mod aplică exact aceleași reguli de filtrare, ceea ce este esențial pentru strategia de testare bazată pe oracle: singura modalitate de a compara cu `grep`, `ripgrep` și `ast-grep` este să parcurgem același set de fișiere ca acele instrumente.
