İçeriğe geç

Git LFS

Git Büyük Dosya Depolama (LFS), deponuzdaki büyük dosyaları küçük işaretçi dosyalarıyla değiştirir. Asıl dosya içeriği ayrı bir LFS sunucusunda saklanır. Pitmaster, LFS işaretçilerini ayrıştırıp oluşturabilir ve toplu API üzerinden LFS sunucularıyla iletişim kurabilir. .gitattributes dosyasını okumaz veya LFS temizleme ve leke bırakma filtrelerini çalıştırmaz: add() dosyaları olduğu gibi saklar, checkout() ise işaretçi dosyaları yazar. Gerçek içeriği getirme işi aşağıda gösterildiği gibi kodunuza aittir.

LFS İşaretçi Dosyaları

Bir dosya LFS tarafından izlendiğinde git, asıl içerik yerine bir işaretçi dosyası saklar:

Kod
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345

İşaretçi şunları içerir:

  • version: LFS belirtim sürümü URL
  • oid: asıl dosya içeriğinin SHA-256 özeti (başına sha256: eklenir)
  • size: asıl dosyanın bayt cinsinden boyutu

İşaretçileri ayrıştırma

PHP
use Pitmaster\Lfs\LfsPointer;

$content = file_get_contents('.git-lfs-tracked-file');
$pointer = LfsPointer::parse($content);

if ($pointer !== null) {
    echo "OID: {$pointer->oid}\n";
    echo "Size: {$pointer->size}\n";
    echo "Version: {$pointer->version}\n";
}

parse(), version, oid sha256: veya size satırı eksikse null döndürür. Değerleri doğrulamaz (onaltılık olmayan bir OID veya sayısal olmayan bir boyut kabul edilir).

İşaretçileri algılama

PHP
if (LfsPointer::isPointer($blobContent)) {
    // This blob is an LFS pointer, not actual file content
    $pointer = LfsPointer::parse($blobContent);
}

isPointer(), sürüm URL, oid sha256: ve size alanlarının mevcut olup olmadığını tümüyle ayrıştırmadan denetler.

İşaretçi oluşturma

PHP
// From known OID and size
$pointer = new LfsPointer(
    oid: '4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393',
    size: 12345,
);

// From file content (computes SHA-256 hash)
$pointer = LfsPointer::forContent($actualFileContent);

echo $pointer->oid;   // SHA-256 hash
echo $pointer->size;  // Content length

İşaretçileri serileştirme

PHP
$content = $pointer->serialize();
// "version https://git-lfs.github.com/spec/v1\noid sha256:4d7a21...\nsize 12345\n"

LFS İstemcisi

LfsClient, toplu API kullanarak LFS sunucularıyla iletişim kurar (<url>/objects/batch adresine POST isteği gönderir).

İstemci oluşturma

PHP
use Pitmaster\Lfs\LfsClient;

// From a git remote URL (appends /info/lfs)
$client = LfsClient::fromRemoteUrl('https://github.com/user/repo.git');
// LFS URL: https://github.com/user/repo.git/info/lfs

// Direct URL
$client = new LfsClient('https://lfs.example.com/repo', timeout: 60);

fromRemoteUrl() yöntemi standart kuralı izler: git URL değerine /info/lfs ekler (yoksa .git ekleyerek). Yalnızca HTTP(S) uzak depo URL'leri kullanılabilir bir LFS URL değeri sağlar; SCP tarzı SSH uzak depoları (git@host:repo.git) sağlamaz.

LfsClient, PHP öğesinin HTTP akış sarmalayıcısını kullanır (allow_url_fopen etkin olmalıdır). Kimlik bilgisi göndermez ve her eylemle döndürülen header eşlemesini yok sayar; bu nedenle yalnızca kimlik doğrulaması gerektirmeyen LFS sunucuları ve depolama URL'leriyle çalışır. Bir depo tanıtıcısına bağlı olmadığından, Pitmaster::processFreeOptions() ile açılmış bir depoda çalışırken bile ağ istekleri yapar.

Dosyaları indirme

PHP
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);

Arka planda download() şunları yapar:

  1. download işlemi için toplu istek gönderir
  2. Sunucudan indirme URL bilgisi alır
  3. Dosya içeriğini bu URL konumundan getirir

İndirilen baytlar OID veya boyutla karşılaştırılarak denetlenmez.

Toplu indirme

PHP
$results = $client->batchDownload([
    ['oid' => 'abc123...', 'size' => 12345],
    ['oid' => 'def456...', 'size' => 67890],
]);

foreach ($results as $result) {
    if ($result['error'] !== null) {
        echo "Error: {$result['error']}\n";
        continue;
    }

    if ($result['href'] !== null) {
        // Download from $result['href']
    }
}

Dosyaları yükleme

PHP
$client->upload($pointer->oid, $pointer->size, $fileContent);

Yükleme, upload işlemi için toplu istek gönderir. Sunucuda nesne zaten varsa yükleme URL bilgisi döndürmez ve işlem hiçbir şey yapmaz. Yükleme isteğinin sonucu denetlenmediğinden başarısız yükleme bildirilmez ve verify eylemi çağrılmaz.

Toplu yükleme

PHP
$results = $client->batchUpload([
    ['oid' => 'abc123...', 'size' => 12345],
]);

foreach ($results as $result) {
    if ($result['href'] !== null) {
        // Server needs this object, upload to $result['href']
    }
    // No href means server already has it
}

Toplu API protokolü

LFS toplu API, HTTP üzerinden JSON kullanır:

İstek

Kod
POST <lfs-url>/objects/batch
Content-Type: application/vnd.git-lfs+json
Accept: application/vnd.git-lfs+json

{
    "operation": "download",
    "transfers": ["basic"],
    "objects": [
        {"oid": "abc123...", "size": 12345}
    ]
}

Yanıt

JSON
{
    "objects": [
        {
            "oid": "abc123...",
            "size": 12345,
            "actions": {
                "download": {
                    "href": "https://storage.example.com/abc123...",
                    "header": {
                        "Authorization": "Bearer token"
                    }
                }
            }
        }
    ]
}

LFS'yi depo işlemleriyle tümleştirme

LFS kullanan bir depoyu okurken blob içeriği gerçek dosya verisi yerine LFS işaretçileri olabilir. Gerçek içeriği almak için:

PHP
$blob = $repo->readObject($hash);

if (LfsPointer::isPointer($blob->content)) {
    $pointer = LfsPointer::parse($blob->content);
    $remoteUrl = $repo->config()->get('remote.origin.url');
    $client = LfsClient::fromRemoteUrl($remoteUrl);
    $realContent = $client->download($pointer->oid, $pointer->size);
} else {
    $realContent = $blob->content;
}

Hata işleme

Başarısız veya geçersiz bir toplu istek ya da başarısız bir indirme isteği ProtocolException hatasını fırlatır. Nesne için sunucu indirme URL bilgisi döndürmezse download() de sunucunun hata iletisini içermeden hata fırlatır. batchDownload() ve batchUpload() nesne başına hatalarda hata fırlatmaz; bunları error alanında döndürür.

PHP
use Pitmaster\Exceptions\ProtocolException;

try {
    $content = $client->download($oid, $size);
} catch (ProtocolException $e) {
    // Server unreachable, invalid response, no download URL
    echo "LFS error: {$e->getMessage()}\n";
}

LFS işaretçisi özellikleri

LfsPointer sınıfı salt okunurdur:

PHP
$pointer->oid;      // string: SHA-256 hash (hex)
$pointer->size;     // int: file size in bytes
$pointer->version;  // string: spec version URL