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:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
İşaretçi şunları içerir:
version: LFS belirtim sürümü URLoid: asıl dosya içeriğinin SHA-256 özeti (başınasha256:eklenir)size: asıl dosyanın bayt cinsinden boyutu
İşaretçileri ayrıştırma
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
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
// 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
$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
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
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);
Arka planda download() şunları yapar:
downloadişlemi için toplu istek gönderir- Sunucudan indirme URL bilgisi alır
- Dosya içeriğini bu URL konumundan getirir
İndirilen baytlar OID veya boyutla karşılaştırılarak denetlenmez.
Toplu indirme
$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
$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
$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
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
{
"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:
$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.
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:
$pointer->oid; // string: SHA-256 hash (hex)
$pointer->size; // int: file size in bytes
$pointer->version; // string: spec version URL