
# Tiedostokulkija

Jokainen Greph-tila (teksti, AST, uudelleenkirjoitus, indeksoitu teksti, indeksoitu AST, välimuistiin tallennettu AST, `rg`-kääre, `sg`-kääre) aloittaa käymällä tiedostopuun läpi ja tuottamalla `Greph\Walker\FileList`. Kulkija on yhteinen, joten samat liput ja toimintatavat koskevat kaikkialla.

## Oletustoiminta

Kulkija toimii oletusarvoisesti näin:

- Käy rekursiivisesti läpi kaikki pyydettyjen polkujen alihakemistot.
- Noudattaa `.gitignore`- ja `.grephignore`-sääntöjä jokaisella tasolla, myös sisäkkäiset ohitukset ja kieltosäännöt.
- Ohittaa hakemiston `.git`.
- Ohittaa piilotiedostot ja -hakemistot (kaikki, joiden nimi alkaa merkillä `.`).
- Ohittaa binääritiedostot (tunnistus perustuu nollatavuihin tiedoston ensimmäisten 512 tavun joukossa).
- Ohittaa yli 10 MiB:n kokoiset tiedostot.
- Ei seuraa symbolisia linkkejä.

## Ohitusliput

| Lippu | Vaikutus |
|---|---|
| `--no-ignore` | Lopeta sääntöjen `.gitignore` ja `.grephignore` noudattaminen |
| `--hidden` | Sisällytä piilotiedostot ja -hakemistot |
| `--type NAME` | Sisällytä vain tiedostot, jotka vastaavat nimettyä tyyppialiasta |
| `--type-not NAME` | Sulje pois tiedostot, jotka vastaavat nimettyä tyyppialiasta |
| `--glob GLOB` | Sisällytä vain tiedostot, joiden polku vastaa GLOB-kuviota. Voidaan toistaa. |

Samat asetukset ovat käytettävissä ohjelmallisesti `Greph\Walker\WalkOptions`:n kautta.

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

## Tiedostotyyppien aliakset

Greph sisältää pienen joukon nimettyjä tiedostotyyppejä. Kukin alias vastaa luetteloa tiedostopäätteitä:

| Alias | Tiedostopäätteet |
|---|---|
| `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` |

Koko luettelo löytyy tiedostosta `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## .gitignore-semanttiikka

Greph toteuttaa gitignore-vastaavuuden pelkällä PHP:llä. Semantiikka vastaa `git check-ignore`:n toimintaa:

- Kaavat arvioidaan suhteessa hakemistoon, jossa ne sijaitsevat.
- Sisäkkäiset `.gitignore`-tiedostot ohittavat ylemmän tason säännöt.
- Kieltosääntö (`!pattern`) ottaa aiemmin pois rajatun polun uudelleen mukaan.
- Lopussa oleva `/` rajoittaa kaavan koskemaan hakemistoja.
- Alussa oleva `/` kiinnittää kaavan `.gitignore`-hakemiston polkuun.
- `**` vastaa mitä tahansa määrää polkusegmenttejä.

`.grephignore` käyttää samaa syntaksia, ja sen säännöt lisätään `.gitignore`:n sääntöjen päälle. Sinne kannattaa lisätä työkalukohtaiset poissulut, joita et halua versionhallintaan.

Toteutus sijaitsee tiedostossa `Greph\Walker\GitignoreFilter`.

## Binääritiedostojen tunnistus

Kulkija tarkistaa jokaisen tiedoston ensimmäiset 512 tavua nollatavujen varalta. Jos niitä löytyy, tiedosto käsitellään binääritiedostona ja ohitetaan. Näin havaitaan yleinen tapaus, jossa arkiston indeksoituun hakemistoon sisältyy kuvia, arkistoja tai käännettyjä tiedostoja.

Jos haluat hakea myös binääritiedostoista, aseta `skipBinaryFiles: false` kyseisen `Options`-objektin arvoksi. CLI ei tällä hetkellä tarjoa tätä lippua; käytä julkista rajapintaa.

## Symboliset linkit

Symbolisia linkkejä ei oletusarvoisesti seurata. Aseta `followSymlinks: true` (tai välitä `-L` / `--follow` `rg`-kääreelle) seurataksesi niitä. Kulkija pitää kirjaa käydyistä hakemistoista, joten symbolisten linkkien silmukat eivät aiheuta ääretöntä rekursiota.

## Tiedoston enimmäiskoko

Yli `maxFileSizeBytes`:n kokoiset tiedostot (oletus 10 MiB) ohitetaan. Näin skannaukseen ei vahingossa lueta 1 Gt:n lokitiedostoa muistiin. Voit muuttaa rajaa `Options`-objektissa, kun haluat käsitellä suurempia syötteitä.

## Miksi oma tiedostokulkija

Greph voisi käyttää apunaan `glob()`:tä tai `RecursiveDirectoryIterator`:ta, mutta kumpikaan ei toteuta gitignore-semanttiikkaa, kumpikaan ei tue `.grephignore`:ta eikä kumpikaan integroidu sujuvasti työntekijäpooliin. Kulkijan toteuttaminen kerran ja sen jakaminen eri tilojen kesken tarkoittaa myös, että kaikki tilat käyttävät täsmälleen samoja suodatussääntöjä. Tämä on olennaista oraakkeliohjatussa testausstrategiassa: vertailu kohteisiin `grep`, `ripgrep` ja `ast-grep` onnistuu vain, jos läpikäydään sama tiedostojoukko kuin näissä työkaluissa.
