Git LFS
Git Large File Storage (LFS) mengganti file besar di repositori Anda dengan file pointer kecil. Konten file sebenarnya disimpan di server LFS terpisah. Pitmaster dapat mengurai dan membuat pointer LFS serta berkomunikasi dengan server LFS melalui API batch .gitattributes dan tidak membaca add() atau menjalankan filter clean dan smudge LFS: checkout() menyimpan file apa adanya, dan menulis file pointer. Pengambilan konten sebenarnya menjadi tanggung jawab kode Anda, seperti yang ditunjukkan di bawah.
File Pointer LFS
Saat file dilacak oleh LFS, git menyimpan file pointer sebagai pengganti konten sebenarnya:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
Pointer berisi:
version: versi spesifikasi LFS URLoid: hash SHA-256 dari konten file sebenarnya (diawali dengansha256:)size: ukuran file sebenarnya dalam byte
Mengurai pointer
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() mengembalikan null jika baris version, oid sha256:, atau size tidak ada. Nilainya tidak divalidasi (OID non-heksadesimal atau ukuran nonnumerik tetap diterima).
Mendeteksi pointer
if (LfsPointer::isPointer($blobContent)) {
// This blob is an LFS pointer, not actual file content
$pointer = LfsPointer::parse($blobContent);
}
isPointer() memeriksa keberadaan field version URL, oid sha256:, dan size tanpa parsing lengkap.
Membuat pointer
// 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
Membuat serialisasi pointer
$content = $pointer->serialize();
// "version https://git-lfs.github.com/spec/v1\noid sha256:4d7a21...\nsize 12345\n"
Klien LFS
LfsClient berkomunikasi dengan server LFS menggunakan API batch (POST ke <url>/objects/batch).
Membuat klien
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);
Metode fromRemoteUrl() mengikuti konvensi standar: menambahkan /info/lfs ke URL git (menambahkan .git jika belum ada). Hanya URL remote HTTP(S) yang menghasilkan URL LFS yang dapat digunakan; remote SSH bergaya SCP (git@host:repo.git) tidak bisa digunakan.
LfsClient menggunakan wrapper stream HTTP milik PHP (allow_url_fopen harus diaktifkan). Wrapper ini tidak mengirim kredensial dan mengabaikan peta header yang dikembalikan bersama setiap tindakan, sehingga hanya berfungsi dengan server LFS dan URL penyimpanan yang tidak memerlukan autentikasi. Wrapper ini tidak terikat pada handle repositori, sehingga tetap membuat permintaan jaringan saat Anda bekerja dengan repositori yang dibuka menggunakan Pitmaster::processFreeOptions().
Mengunduh file
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);
Di balik layar, download():
- Mengirim permintaan batch untuk operasi
download - Menerima URL unduhan dari server
- Mengambil konten file dari URL tersebut
Byte yang diunduh tidak diperiksa terhadap OID atau ukuran.
Unduhan batch
$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']
}
}
Mengunggah file
$client->upload($pointer->oid, $pointer->size, $fileContent);
Pengunggahan mengirim permintaan batch untuk operasi upload. Jika server sudah memiliki objek tersebut, server tidak mengembalikan URL unggahan sehingga operasi tidak melakukan apa pun. Hasil permintaan unggah itu sendiri tidak diperiksa, jadi kegagalan unggah tidak dilaporkan dan tindakan verify tidak dipanggil.
Unggahan batch
$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
}
Protokol API batch
Batch LFS API menggunakan JSON melalui HTTP:
Permintaan
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}
]
}
Respons
{
"objects": [
{
"oid": "abc123...",
"size": 12345,
"actions": {
"download": {
"href": "https://storage.example.com/abc123...",
"header": {
"Authorization": "Bearer token"
}
}
}
}
]
}
Mengintegrasikan LFS dengan operasi repositori
Saat membaca repositori yang menggunakan LFS, konten blob mungkin berupa pointer LFS, bukan data file sebenarnya. Untuk mendapatkan konten sebenarnya:
$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;
}
Penanganan error
Permintaan batch yang gagal atau tidak valid, serta permintaan unduhan yang gagal, melempar ProtocolException. download() juga melempar error jika server tidak mengembalikan URL unduhan untuk objek tersebut, tanpa pesan error dari server. batchDownload() dan batchUpload() tidak melempar error untuk kesalahan per objek; keduanya mengembalikan kesalahan tersebut di field error.
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";
}
Properti pointer LFS
Class LfsPointer hanya dapat dibaca:
$pointer->oid; // string: SHA-256 hash (hex)
$pointer->size; // int: file size in bytes
$pointer->version; // string: spec version URL