
# Memulai

## Instalasi

Instal Pitmaster melalui Composer:

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

## Persyaratan

- **PHP 8.2+** dengan kelas readonly, enum, dan promosi konstruktor
- **ext-zlib** untuk kompresi/dekompresi objek (bawaan di sebagian besar instalasi)
- **ext-json** untuk file status operasi dan payload Git LFS API
- **ext-mbstring**, dideklarasikan di `composer.json`, sehingga Composer memerlukannya saat instalasi
- **ext-ctype** untuk validasi hash (diaktifkan di sebagian besar build PHP, tetapi tidak dideklarasikan di `composer.json`)

Operasi inti repositori tidak memerlukan biner `git`, FFI, atau helper eksternal. Fitur opsional memiliki persyaratan runtime tambahan: eksekusi hook menggunakan `proc_open()`, dan transport SSH menggunakan `ext-ssh2` saat dimuat, atau menjalankan biner sistem `ssh` melalui `proc_open()` jika tidak.

## Membuka repositori yang sudah ada

```php
use Pitmaster\Pitmaster;

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

Ini membuka repositori di jalur yang diberikan. Pitmaster menemukan direktori `.git` (atau me-resolve file `.git` untuk worktree tertaut) lalu menginisialisasi basis data objek, basis data ref, dan konfigurasi.

`open()`, `init()`, dan `clone()` menerima array opsi sebagai argumen terakhir:

```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 dijalankan secara default. `Pitmaster::processFreeOptions()` mengembalikan `['processes' => false, 'hooks' => false]`; operasi baca dan tulis lokal tetap berfungsi pada handle seperti itu.

## Memeriksa apakah jalur merupakan repositori

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

## Menginisialisasi repositori baru

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

Ini membuat struktur direktori `.git` dengan objek, refs, HEAD (menunjuk ke `refs/heads/main`), dan konfigurasi default.

Untuk membuat repositori SHA-256, berikan format objek sebagai argumen kedua:

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

ID objek di repositori itu terdiri dari 64 karakter heksadesimal, dan konfigurasi mencatat `extensions.objectformat = sha256`. Repositori yang dibuka kemudian mengambil format tersebut dari entri konfigurasi itu.

## Membaca commit HEAD

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

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

Metode `head()` me-resolve HEAD (mengikuti ref simbolis) dan mengembalikan objek `Commit`.

## Mencantumkan branch dan tag

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

## Menelusuri riwayat commit

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

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

Anda juga dapat memulai dari commit tertentu:

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

## Memeriksa status pohon kerja

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

## Menyiapkan file dan membuat 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";
```

Nama dan email penulis ditentukan dengan urutan berikut: variabel lingkungan `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, variabel lingkungan `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, konstanta `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, `.git/config` milik repositori (`user.name` dan `user.email`), lalu `Pitmaster <pitmaster@localhost>`. Hanya file konfigurasi repositori (beserta file yang disertakannya) yang dibaca, bukan `~/.gitconfig`. Identitas committer ditentukan dengan cara yang sama dari nama `*_COMMITTER_*` dan menggunakan konstanta penulis sebagai nilai cadangan.

## Menghitung diff

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

## Mengklon repositori remote

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

Ini menemukan refs, mengambil file pack, menyiapkan branch pelacakan remote, dan melakukan checkout branch default. URL HTTP(S) menggunakan HTTP pintar dan beralih ke HTTP biasa jika perlu; URL SSH menggunakan transport SSH. Berikan kedalaman sebagai argumen ketiga untuk klon dangkal: `Pitmaster::clone($url, $path, 1)`.

## Membaca objek apa pun berdasarkan 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;
}
```

## Konfigurasi

Pitmaster menggunakan `.git/config` repositori untuk informasi penulis dan URL remote. Anda juga dapat menetapkan nilai default global dengan konstanta PHP, yang didefinisikan sebelum Pitmaster dijalankan:

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

| Konstanta | Default | Dampak |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | none | Identitas penulis (lihat urutan di atas) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | nilai penulis | Identitas committer |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Batas waktu HTTP pintar dalam detik (bilangan bulat) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Kedalaman rantai delta maksimum saat membaca pack (bilangan bulat) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Jumlah objek yang disimpan dalam cache objek di memori |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Batas byte cache objek |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Objek delta yang telah di-resolve dan di-cache per pack |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Batas byte cache pack tersebut |
| `PITMASTER_MAX_PACK_MEMORY` | none | Nama lama untuk batas byte cache pack, hanya digunakan jika `PITMASTER_PACK_RESOLVED_CACHE_BYTES` tidak ditentukan |

Nilai byte menerima bilangan bulat atau string dengan akhiran `k`, `m`, atau `g` (`'256M'`). Nilai yang tidak valid akan menggunakan nilai default.

Variabel lingkungan mengesampingkan konstanta identitas: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, padanannya `PITMASTER_COMMITTER_*`, serta variabel `GIT_AUTHOR_*` dan `GIT_COMMITTER_*` milik git. Transport SSH membaca variabel `PITMASTER_SSH_*`, yang dijelaskan di [Protokol](https://pitmaster.inline0.dev/id/docs/network/protocols).

Tidak ada konstanta untuk algoritma hash. Format objek dipilih saat repositori dibuat (`Pitmaster::init($path, 'sha256')` atau `init --object-format=sha256` pada CLI), lalu dibaca dari konfigurasi repositori setelahnya.
