
# Початок роботи

## Встановлення

Установіть Pitmaster через Composer:

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

## Вимоги

- **PHP 8.2+** із readonly-класами, переліками та просуванням конструктора
- **ext-zlib** для стиснення та розпакування об’єктів (вбудований у більшість інсталяцій)
- **ext-json** для файлів стану операцій і даних Git LFS API
- **ext-mbstring**, указаний у `composer.json`, тому Composer потребує його під час установлення
- **ext-ctype** для перевірки хешів (увімкнений у більшості збірок PHP, але не вказаний у `composer.json`)

Для основних операцій із репозиторієм не потрібні двійковий файл `git`, FFI чи зовнішні допоміжні засоби. Додаткові можливості мають додаткові вимоги під час виконання: виконання хуків використовує `proc_open()`, а транспорт SSH використовує `ext-ssh2`, якщо він завантажений, інакше запускає системний двійковий файл `ssh` через `proc_open()`.

## Відкриття наявного репозиторію

```php
use Pitmaster\Pitmaster;

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

Це відкриває репозиторій за вказаним шляхом. Pitmaster знаходить каталог `.git` (або визначає файл `.git` для пов’язаних робочих дерев) та ініціалізує базу об’єктів, базу посилань і конфігурацію.

`open()`, `init()` і `clone()` приймають масив параметрів як останній аргумент:

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

За замовчуванням хуки виконуються. `Pitmaster::processFreeOptions()` повертає `['processes' => false, 'hooks' => false]`; локальне читання та запис і надалі працюють із таким дескриптором.

## Перевірка, чи є шлях репозиторієм

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

## Ініціалізація нового репозиторію

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

Це створює структуру каталогів `.git` з об’єктами, посиланнями, HEAD (що вказує на `refs/heads/main`) і типовою конфігурацією.

Щоб створити репозиторій SHA-256, передайте формат об’єктів другим аргументом:

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

Ідентифікатори об’єктів у такому репозиторії мають 64 шістнадцяткові символи, а конфігурація містить `extensions.objectformat = sha256`. Формат зчитується з цього запису конфігурації під час наступного відкриття репозиторію.

## Читання коміту HEAD

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

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

Метод `head()` визначає HEAD (переходячи за символічними посиланнями) і повертає об’єкт `Commit`.

## Перегляд гілок і тегів

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

## Перегляд історії комітів

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

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

Також можна почати з певного коміту:

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

## Перевірка стану робочого дерева

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

## Додавання файлів до індексу та створення коміту

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

Ім’я й адресу електронної пошти автора визначають у такому порядку: змінні середовища `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, змінні середовища `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, константи `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, власний `.git/config` репозиторію (`user.name` і `user.email`) і, зрештою, `Pitmaster <pitmaster@localhost>`. Читається лише файл конфігурації репозиторію (та файли, які він включає), а не `~/.gitconfig`. Дані автора коміту визначають так само, використовуючи імена `*_COMMITTER_*`, і за їх відсутності застосовують константи автора.

## Обчислення різниць

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

## Клонування віддаленого репозиторію

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

Це знаходить посилання, завантажує файл пакета, налаштовує гілки для відстеження віддалених гілок і вибирає типову гілку. URL-адреси HTTP(S) використовують розумний HTTP і переходять до простого HTTP у разі невдачі; URL-адреси SSH використовують транспорт SSH. Щоб виконати поверхневе клонування, передайте глибину третім аргументом: `Pitmaster::clone($url, $path, 1)`.

## Читання будь-якого об’єкта за хешем

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

## Конфігурація

Pitmaster використовує конфігурацію репозиторію `.git/config` для даних автора та віддалених URL-адрес. Також можна задати глобальні типові значення константами PHP, визначеними до запуску 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');
```

| Константа | Типове значення | Дія |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | немає | Дані автора (див. порядок вище) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | значення автора | Дані автора коміту |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Час очікування розумного HTTP у секундах (ціле число) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Максимальна глибина ланцюжка delta під час читання пакетів (ціле число) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Кількість об’єктів у кеші об’єктів у пам’яті |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Байтова межа кешу об’єктів |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Розпізнані об’єкти delta, кешовані для кожного пакета |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Байтова межа кешу цього пакета |
| `PITMASTER_MAX_PACK_MEMORY` | немає | Стара назва байтової межі кешу пакетів, використовується лише якщо `PITMASTER_PACK_RESOLVED_CACHE_BYTES` не визначено |

Значення байтів приймають ціле число або рядок із суфіксом `k`, `m` чи `g` (`'256M'`). Недопустимі значення замінюються типовим.

Змінні середовища мають пріоритет над константами ідентифікації: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, відповідники `PITMASTER_COMMITTER_*`, а також власні змінні `GIT_AUTHOR_*` і `GIT_COMMITTER_*` у git. Транспорт SSH читає змінні `PITMASTER_SSH_*`, описані в розділі [Протоколи](https://pitmaster.inline0.dev/uk/docs/network/protocols).

Для алгоритму хешування немає константи. Формат об’єктів вибирається під час створення репозиторію (`Pitmaster::init($path, 'sha256')` або `init --object-format=sha256` на CLI), а потім зчитується з конфігурації репозиторію.
