
# Git Nesneleri

git deposundaki her şey bir nesne olarak saklanır. Dört tür vardır: blob'lar (dosya içeriği), tree'ler (dizin listeleri), commit'ler (üst verili anlık görüntüler) ve tag'ler (açıklamalı referanslar). Her nesne, içeriğinin SHA-1 özetiyle tanımlanır.

## Nesne türleri

### Blob

Bir blob, üst veri olmadan ham dosya içeriğini tutar (dosya adı veya izinler içermez).

```php
use Pitmaster\Object\Blob;

// Create from content
$blob = Blob::fromContent('Hello, world!');
echo $blob->content;    // 'Hello, world!'
echo $blob->size();     // 13
echo $blob->id->hex;    // SHA-1 hash
echo $blob->type->value; // 'blob' (the property is ObjectType::Blob)
```

### Tree

Bir tree, dizin listesidir. Her girdide bir mod, ad ve bir blob'a ya da alt tree'ye işaret eden özet bulunur.

```php
use Pitmaster\Object\Tree;
use Pitmaster\Object\TreeEntry;

// Read a tree
$tree = $repo->readObject($treeHash);

foreach ($tree->entries as $entry) {
    echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
}

// Look up a specific entry
$entry = $tree->entry('README.md');

// Create a tree (entries already in git's sort order)
$entries = [
    new TreeEntry('100644', 'README.md', $blobId),
    new TreeEntry('100755', 'deploy.sh', $execBlobId),
    new TreeEntry('40000', 'src', $subtreeId),
];

$tree = Tree::fromEntries($entries);
```

`Tree::fromEntries()` girdileri verilen sırayla ve mod dizelerini tam olarak belirtildiği gibi yazar; bu nedenle önce sıralayın ve dizin modlarını `40000` olarak yazın. `040000` ile veya başka bir sırada yazılan tree, git'ünkinden farklı bir özete sahip olur; `git fsck --strict` ise modu başında sıfırlar olacak şekilde bildirir.

#### TreeEntry

`TreeEntry` salt okunur bir değer nesnesidir:

```php
use Pitmaster\Object\TreeEntry;

$entry->mode;   // '100644', '100755', '40000', '120000', '160000'
$entry->name;   // Filename
$entry->hash;   // ObjectId

// Type checks
$entry->isBlob();        // regular or executable file (mode 10xxxx)
$entry->isExecutable();  // mode 100755
$entry->isTree();        // mode 40000 (also accepts 040000)
$entry->isSymlink();     // mode 120000
$entry->isGitlink();     // mode 160000 (submodule)
```

Mod değerleri:
| Mod | Anlamı |
|------|---------|
| `100644` | Normal dosya |
| `100755` | Çalıştırılabilir dosya |
| `40000` | Dizin (tree); `git ls-tree` tarafından `040000` olarak gösterilir |
| `120000` | Sembolik bağlantı |
| `160000` | Gitlink (alt modül) |

Tree girdileri ada göre sıralanır; karşılaştırma yapılırken dizin adlarının sonunda `/` varmış gibi değerlendirilir.

### Commit

Bir commit, bir tree'yi geçmişine ve üst verilerine bağlar.

```php
use Pitmaster\Object\Commit;

$commit = $repo->head();

$commit->id;         // ObjectId
$commit->tree;       // ObjectId of the tree
$commit->parents;    // array of ObjectId (zero for root, one for normal, two+ for merge)
$commit->author;     // 'Name <email> timestamp timezone'
$commit->committer;  // 'Name <email> timestamp timezone'
$commit->message;    // Full commit message

$commit->isMerge();  // true if two or more parents
```

#### Commit içeriğini oluşturma

```php
$content = Commit::buildContent(
    tree: $treeId,
    parents: [$parentId],
    author: 'Jane <jane@example.com> 1700000000 +0000',
    committer: 'Jane <jane@example.com> 1700000000 +0000',
    message: "Add feature\n",
);
```

Ham commit biçimi:

```
tree <hex hash>\n
parent <hex hash>\n       (zero or more)
author <name> <<email>> <timestamp> <tz>\n
committer <name> <<email>> <timestamp> <tz>\n
\n
<message>
```

### Tag

Açıklamalı tag'ler, üst veri içeren nesnelerdir.

```php
use Pitmaster\Object\Tag;

$tag = $repo->readObject($tagHash);

$tag->object;        // ObjectId of the target
$tag->objectType;    // ObjectType enum (ObjectType::Commit, ...)
$tag->name;          // Tag name
$tag->tagger;        // 'Name <email> timestamp timezone'
$tag->message;       // Tag message
```

Ham tag biçimi:

```
object <hex hash>\n
type commit\n
tag <name>\n
tagger <name> <<email>> <timestamp> <tz>\n
\n
<message>
```

## ObjectId

`ObjectId`, bir SHA-1 (veya SHA-256) özetini temsil eden salt okunur bir değer nesnesidir.

```php
use Pitmaster\Object\ObjectId;
use Pitmaster\Object\ObjectType;

// From hex string
$id = ObjectId::fromHex('a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2');

// From binary (20 bytes for SHA-1, 32 for SHA-256)
$id = ObjectId::fromBinary($rawBytes);

// Compute from content
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!');
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!', 'sha256');

// Zero hash
$id = ObjectId::zero();
$id = ObjectId::zero('sha256');

// Properties
$id->hex;      // 40-character hex string (64 for SHA-256)
$id->binary;   // 20-byte raw binary (32 for SHA-256)
$id->algo;     // 'sha1' or 'sha256'
$id->isSha256();
$id->isZero();

// Comparison
$id->equals($otherId);
```

Özet, sıkıştırılmamış veri üzerinden hesaplanır: `sha1("{type} {size}\0{content}")` veya aynı baytların SHA-256 biçimi. `fromHex()` ve `fromBinary()` algoritmayı uzunluğa göre seçer.

## ObjectType enum'u

```php
use Pitmaster\Object\ObjectType;

ObjectType::Blob;    // 'blob'
ObjectType::Tree;    // 'tree'
ObjectType::Commit;  // 'commit'
ObjectType::Tag;     // 'tag'
```

## Gevşek nesne biçimi

Gevşek nesneler, `.git/objects/` içinde, özetlerinin ilk iki onaltılık karakterine göre düzenlenmiş ayrı dosyalar olarak saklanır.

```
.git/objects/a1/b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
```

Dosya içeriği zlib ile sıkıştırılır. Sıkıştırılmamış içerik şöyledir:

```
<type> <decimal size>\0<raw content>
```

Örneğin, "Hello" içeren bir blob şu şekilde saklanır:

```
zlib_encode("blob 5\0Hello")
```

### Gevşek nesneleri okuma

```php
use Pitmaster\Storage\LooseObjectStore;

$store = new LooseObjectStore('/path/to/.git/objects');
$object = $store->read($objectId);
```

`LooseObjectStore`:
1. Dosya yolunu özetten hesaplar
2. Dosyayı okur ve zlib sıkıştırmasını açar
3. Türü ve boyutu çıkarmak için başlığı ayrıştırır
4. Uygun ayrıştırıcıya devreder (`Blob`, `Tree`, `Commit`, `Tag`)

### Gevşek nesneleri yazma

```php
$store->write($object);
```

Yazma işlemi:
1. Serileştir: `"{type} {size}\0{content}"`
2. Nesne oluşturulurken hesaplanan `id` değerini kullan (okumalar özeti doğrular)
3. Sıkıştır: `zlib_encode(serialized)`
4. `.git/objects/{hash[0..1]}/{rest of hash}` konumuna yaz
5. Atomik yazma (geçici dosyaya yaz, ardından yeniden adlandır)

## ObjectSerializer

`ObjectSerializer`, nesne kablo biçiminin kodlanmasını ve çözülmesini yönetir.

```php
use Pitmaster\Storage\ObjectSerializer;

// Encode
$raw = ObjectSerializer::encodeRaw($object);
// "blob 5\0Hello"
$compressed = ObjectSerializer::encode($object);
// zlib-compressed form, as stored in a loose object file

// Decode
$object = ObjectSerializer::decodeRaw($raw);
$object = ObjectSerializer::decode($compressed, $expectedHex); // throws CorruptObjectException on a hash mismatch
```

## ObjectDatabase

`ObjectDatabase`, önce gevşek nesneleri, ardından paket dosyalarını arayan bileşik bir depodur.

```php
use Pitmaster\Storage\ObjectDatabase;

$db = new ObjectDatabase('/path/to/.git/objects');

$object = $db->read($objectId);    // Search loose, then packs
$db->write($object);               // Always writes to loose
$exists = $db->exists($objectId);  // Check loose, then packs
$all = $db->listAll();             // All hashes from loose + packs
```

Gevşek depoya doğrudan yazma bilinçli bir tercihtir. Paket dosyalarına yeniden paketleme işini `git gc`'e bırakın.

## SHA-256 desteği

Pitmaster, özet algoritmasını `ObjectId` üzerinden soyutlar. Varsayılan SHA-1'dir. SHA-256, depo oluşturulurken depo başına seçilir:

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

```bash
./vendor/bin/pitmaster init --object-format=sha256
```

Bu işlem `extensions.objectformat = sha256` değerini yapılandırmaya yazar. Daha sonra açılan depolar biçimi bu girdiden okur; tüm nesne, tree, dizin ve ref işlemleri artık 64 karakterlik onaltılık dizeler ve 32 baytlık ikili özetler kullanır. Algoritma için genel bir anahtar veya sabit yoktur.

Nesneleri kendiniz oluşturduğunuzda nesne sınıfları algoritmayı bağımsız değişken olarak alır: `Blob::fromContent($content, 'sha256')`, `Tree::fromEntries($entries, 'sha256')`, `ObjectId::compute($type, $content, 'sha256')`. `Pitmaster::clone()`, SHA-1 depolar oluşturur.

## Tree girdisinin ikili biçimi

Bir tree nesnesinin içeriğinde her girdi şu şekilde kodlanır:

```
<octal mode as ASCII> <space> <filename> \0 <binary hash: 20 bytes SHA-1, 32 bytes SHA-256>
```

Not: commit ve tag nesnelerindeki onaltılık özetlerin aksine, özet ham ikili biçimdedir.

Girdiler, dizin adlarının sonunda `/` varmış gibi adlar karşılaştırılarak sıralanır. Tree özetinin git'in hesaplamasıyla eşleşmesi için bu sıralama tam olarak uygulanmalıdır.
