
# Pierwsze kroki

## Instalacja

Zainstaluj Pitmaster za pomocą Composer:

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

## Wymagania

- **PHP 8.2+** z klasami tylko do odczytu, typami wyliczeniowymi i promocją parametrów konstruktora
- **ext-zlib** do kompresji i dekompresji obiektów (wbudowane w większość instalacji)
- **ext-json** do plików stanu operacji i ładunków Git LFS API
- **ext-mbstring**, zadeklarowane w `composer.json`, dlatego Composer wymaga go podczas instalacji
- **ext-ctype** do walidacji skrótów (włączone w większości kompilacji PHP, ale niezadeklarowane w `composer.json`)

Podstawowe operacje na repozytorium nie wymagają pliku binarnego `git`, FFI ani zewnętrznych narzędzi pomocniczych. Funkcje opcjonalne mają dodatkowe wymagania środowiska uruchomieniowego: wykonywanie hooków używa `proc_open()`, a transport SSH używa `ext-ssh2`, jeśli jest załadowane; w przeciwnym razie uruchamia systemowy plik binarny `ssh` za pośrednictwem `proc_open()`.

## Otwieranie istniejącego repozytorium

```php
use Pitmaster\Pitmaster;

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

Otwiera repozytorium pod podaną ścieżką. Pitmaster lokalizuje katalog `.git` (lub rozwiązuje plik `.git` w przypadku połączonych drzew roboczych) i inicjuje bazę obiektów, bazę odwołań oraz konfigurację.

`open()`, `init()` i `clone()` przyjmują tablicę opcji jako ostatni 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());
```

Hooki są domyślnie uruchamiane. `Pitmaster::processFreeOptions()` zwraca `['processes' => false, 'hooks' => false]`; lokalne odczyty i zapisy nadal działają na takim uchwycie.

## Sprawdzanie, czy ścieżka prowadzi do repozytorium

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

## Inicjowanie nowego repozytorium

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

Tworzy strukturę katalogów `.git` z obiektami, odwołaniami, HEAD (wskazującym na `refs/heads/main`) i domyślną konfiguracją.

Aby utworzyć repozytorium SHA-256, przekaż format obiektów jako drugi argument:

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

Identyfikatory obiektów w tym repozytorium mają 64 znaki szesnastkowe, a konfiguracja zapisuje `extensions.objectformat = sha256`. Później otwierane repozytoria pobierają format z tego wpisu konfiguracji.

## Odczytywanie commita HEAD

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

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

Metoda `head()` rozwiązuje HEAD (podążając za odwołaniami symbolicznymi) i zwraca obiekt `Commit`.

## Wyświetlanie gałęzi i tagów

```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']
```

## Przeglądanie historii commitów

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

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

Możesz też rozpocząć od konkretnego commita:

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

## Sprawdzanie stanu drzewa roboczego

```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";
    }
}
```

## Przygotowywanie plików do commita i zatwierdzanie zmian

```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";
```

Nazwa i adres e-mail autora są określane w następującej kolejności: zmienne środowiskowe `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, zmienne środowiskowe `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, stałe `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, własna konfiguracja repozytorium `.git/config` (`user.name` i `user.email`), a na końcu `Pitmaster <pitmaster@localhost>`. Odczytywany jest tylko plik konfiguracji repozytorium (i pliki, które dołącza), a nie `~/.gitconfig`. Dane committera są określane w ten sam sposób na podstawie nazw `*_COMMITTER_*`, a w razie braku używane są stałe autora.

## Obliczanie różnic

```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();
```

## Klonowanie zdalnego repozytorium

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

Wykrywa odwołania, pobiera plik pakietu, konfiguruje zdalne gałęzie śledzące i pobiera domyślną gałąź. HTTP(S) Adresy URL używają HTTP i w razie potrzeby przechodzą na HTTP; adresy URL SSH korzystają z transportu SSH. Aby wykonać płytkie klonowanie, przekaż głębokość jako trzeci argument: `Pitmaster::clone($url, $path, 1)`.

## Odczyt dowolnego obiektu na podstawie skrótu

```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;
}
```

## Konfiguracja

Pitmaster korzysta z ustawień `.git/config` repozytorium dotyczących informacji o autorze i zdalnych adresów URL. Możesz też ustawić domyślne wartości globalne za pomocą stałych PHP, zdefiniowanych przed uruchomieniem Pitmaster:

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

| Stała | Domyślna wartość | Działanie |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | brak | Tożsamość autora (zob. kolejność powyżej) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | wartości autora | Tożsamość osoby zatwierdzającej |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Limit czasu inteligentnego HTTP w sekundach (liczba całkowita) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Maksymalna głębokość łańcucha delt podczas odczytu pakietów (liczba całkowita) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Obiekty przechowywane w pamięci podręcznej obiektów |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Limit bajtów pamięci podręcznej obiektów |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Rozwiązane obiekty delt przechowywane w pamięci podręcznej danego pakietu |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Limit bajtów tej pamięci podręcznej pakietu |
| `PITMASTER_MAX_PACK_MEMORY` | brak | Starsza nazwa limitu bajtów pamięci podręcznej pakietu, używana tylko wtedy, gdy nie zdefiniowano `PITMASTER_PACK_RESOLVED_CACHE_BYTES` |

Wartości bajtów mogą być liczbą całkowitą lub ciągiem znaków z przyrostkiem `k`, `m` albo `g` (`'256M'`). Nieprawidłowe wartości powodują użycie wartości domyślnej.

Zmienne środowiskowe nadpisują stałe tożsamości: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, ich odpowiedniki `PITMASTER_COMMITTER_*` oraz własne zmienne gita `GIT_AUTHOR_*` i `GIT_COMMITTER_*`. Transport SSH odczytuje zmienne `PITMASTER_SSH_*` opisane w sekcji [Protokoły](https://pitmaster.inline0.dev/pl/docs/network/protocols).

Nie ma stałej określającej algorytm skrótu. Format obiektów wybiera się podczas tworzenia repozytorium (`Pitmaster::init($path, 'sha256')` lub `init --object-format=sha256` w CLI), a później odczytuje z konfiguracji repozytorium.
