
# Primii pași

## Instalare

Instalați Pitmaster prin Composer:

```bash
composer require pitmaster/pitmaster
```

## Cerințe

- **PHP 8.2+** cu clase doar pentru citire, enum-uri și promovarea constructorilor
- **ext-zlib** pentru comprimarea/decomprimarea obiectelor (inclus în majoritatea instalărilor)
- **ext-json** pentru fișierele de stare ale operațiunilor și payloadurile Git LFS API
- **ext-mbstring**, declarat în `composer.json`, astfel încât Composer îl solicită la instalare
- **ext-ctype** pentru validarea hashurilor (activat în majoritatea buildurilor PHP, dar nedeclarat în `composer.json`)

Operațiunile de bază ale depozitului nu necesită binarul `git`, FFI sau instrumente externe. Funcțiile opționale au cerințe suplimentare la rulare: execuția hook-urilor folosește `proc_open()`, iar transportul SSH folosește `ext-ssh2` când acesta este încărcat; în caz contrar, pornește binarul de sistem `ssh` prin `proc_open()`.

## Deschideți un depozit existent

```php
use Pitmaster\Pitmaster;

$repo = Pitmaster::open('/path/to/project');
```

Aceasta deschide depozitul de la calea indicată. Pitmaster localizează directorul `.git` (sau rezolvă un fișier `.git` pentru worktree-uri asociate) și inițializează baza de date a obiectelor, baza de date a referințelor și configurația.

`open()`, `init()` și `clone()` acceptă un tablou de opțiuni ca ultim argument:

```php
// Do not run .git/hooks scripts for this handle
$repo = Pitmaster::open('/path/to/project', ['hooks' => false]);

// Do not start any process: no hooks, no fsmonitor hook, no clone/fetch/push, no SSH
$repo = Pitmaster::open('/path/to/project', Pitmaster::processFreeOptions());
```

Hook-urile rulează în mod implicit. `Pitmaster::processFreeOptions()` returnează `['processes' => false, 'hooks' => false]`; citirile și scrierile locale continuă să funcționeze prin acest handle.

## Verificați dacă o cale este un depozit

```php
if (Pitmaster::isRepository('/path/to/project')) {
    $repo = Pitmaster::open('/path/to/project');
}
```

## Inițializați un depozit nou

```php
$repo = Pitmaster::init('/path/to/new-project');
```

Aceasta creează structura de directoare `.git` cu obiecte, referințe, HEAD (care indică spre `refs/heads/main`) și o configurație implicită.

Pentru a crea un depozit SHA-256, transmiteți formatul obiectelor ca al doilea argument:

```php
$repo = Pitmaster::init('/path/to/new-project', 'sha256');
```

ID-urile obiectelor din acel depozit au 64 de caractere hexazecimale, iar configurația înregistrează `extensions.objectformat = sha256`. Depozitele deschise ulterior preiau formatul din acea intrare de configurare.

## Citiți commitul HEAD

```php
$head = $repo->head();

echo "Commit: {$head->id->hex}\n";
echo "Author: {$head->author}\n";
echo "Message: {$head->message}\n";
```

Metoda `head()` rezolvă HEAD (urmărind referințele simbolice) și returnează un obiect `Commit`.

## Listați ramurile și tagurile

```php
// All branch names
$branches = $repo->branches();
// ['main', 'feature/login', 'bugfix/typo']

// Current branch name (null if detached)
$current = $repo->branch();
// 'main'

// All tag names
$tags = $repo->tags();
// ['v1.0.0', 'v1.1.0']
```

## Parcurgeți istoricul commiturilor

```php
// Last 20 commits from HEAD
$commits = $repo->log(20);

foreach ($commits as $commit) {
    echo substr($commit->id->hex, 0, 7) . " {$commit->message}\n";
}
```

Puteți începe și de la un commit specific:

```php
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
```

## Verificați starea arborelui de lucru

```php
use Pitmaster\Status\FileStatus;

$entries = $repo->status();

foreach ($entries as $entry) {
    if ($entry->index === FileStatus::Untracked) {
        echo "?? {$entry->path}\n";
    } elseif ($entry->index === FileStatus::Modified) {
        echo "M  {$entry->path}\n";
    } elseif ($entry->worktree === FileStatus::Modified) {
        echo " M {$entry->path}\n";
    }
}
```

## Adăugați fișiere în index și creați un commit

```php
// Stage specific files
$repo->add('src/Feature.php', 'tests/FeatureTest.php');

// Create a commit
$commitId = $repo->commit('Add new feature with tests');

echo "Created commit: {$commitId->hex}\n";
```

Numele și adresa de e-mail ale autorului sunt rezolvate în această ordine: variabilele de mediu `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, variabilele de mediu `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, constantele `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, `.git/config` propriu-zis al depozitului (`user.name` și `user.email`), iar în final `Pitmaster <pitmaster@localhost>`. Se citește doar fișierul de configurare al depozitului (și fișierele incluse de acesta), nu `~/.gitconfig`. Identitatea comitentului este rezolvată în același mod din numele `*_COMMITTER_*` și revine la constantele autorului dacă nu este găsită.

## Calculați diferențele

```php
// Unstaged changes (worktree vs index)
$diffs = $repo->diff();

foreach ($diffs as $diff) {
    echo $diff->format(); // Unified diff output
}

// Staged changes (index vs HEAD)
$staged = $repo->diffStaged();
```

## Clonați un depozit la distanță

```php
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/path/to/destination');
```

Acesta descoperă referințele, preia fișierul pack, configurează ramurile de urmărire la distanță și face checkout la ramura implicită. HTTP(S) URL-urile folosesc HTTP smart și revin la HTTP dumb; URL-urile SSH folosesc transportul SSH. Pentru o clonare superficială, transmiteți adâncimea ca al treilea argument: `Pitmaster::clone($url, $path, 1)`.

## Citește orice obiect după hash

```php
$object = $repo->readObject($fullHash); // full 40-character (or 64 for SHA-256) hex hash

if ($object instanceof \Pitmaster\Object\Blob) {
    echo $object->content;
} elseif ($object instanceof \Pitmaster\Object\Commit) {
    echo $object->message;
}
```

## Configurare

Pitmaster respectă `.git/config` din depozit pentru informațiile despre autor și URL-urile la distanță. Puteți seta și valori implicite globale cu constantele PHP, definite înainte ca Pitmaster să ruleze:

```php
define('PITMASTER_AUTHOR_NAME', 'Your Name');
define('PITMASTER_AUTHOR_EMAIL', 'you@example.com');
define('PITMASTER_HTTP_TIMEOUT', 60);        // Seconds
define('PITMASTER_MAX_DELTA_CHAIN', 50);     // Max delta chain depth
define('PITMASTER_OBJECT_CACHE_BYTES', '64M');
```

| Constantă | Valoare implicită | Efect |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | none | Identitatea autorului (consultați ordinea de mai sus) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | valorile autorului | Identitatea persoanei care face commit-ul |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Timeout pentru smart HTTP, în secunde (număr întreg) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Adâncimea maximă a lanțului delta la citirea fișierelor pack (număr întreg) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Obiecte păstrate în memoria cache a obiectelor |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Bugetul în octeți al memoriei cache a obiectelor |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Obiecte delta rezolvate, memorate în cache per fișier pack |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Bugetul în octeți al memoriei cache pentru acel fișier pack |
| `PITMASTER_MAX_PACK_MEMORY` | none | Nume mai vechi pentru bugetul în octeți al memoriei cache pentru fișiere pack; este folosit numai dacă `PITMASTER_PACK_RESOLVED_CACHE_BYTES` nu este definită |

Valorile în octeți acceptă un număr întreg sau un șir cu sufixul `k`, `m` sau `g` (`'256M'`). Valorile nevalide revin la valoarea implicită.

Variabilele de mediu înlocuiesc constantele de identitate: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, echivalentele `PITMASTER_COMMITTER_*` și propriile variabile `GIT_AUTHOR_*` și `GIT_COMMITTER_*` ale git. Transportul SSH citește variabilele `PITMASTER_SSH_*`, descrise în [Protocoale](https://pitmaster.inline0.dev/ro/docs/network/protocols).

Nu există nicio constantă pentru algoritmul hash. Formatul obiectelor este ales la crearea depozitului (`Pitmaster::init($path, 'sha256')` sau `init --object-format=sha256` pe CLI) și apoi este citit din configurația depozitului.
