Git LFS
A Git Large File Storage (LFS) a repository nagy fájljait kisméretű mutatófájlokkal helyettesíti. A tényleges fájltartalom külön LFS-kiszolgálón tárolódik. A Pitmaster képes LFS-mutatókat elemezni és létrehozni, valamint a kötegelt API protokollon keresztül kommunikálni az LFS-kiszolgálókkal. Nem olvassa a .gitattributes fájlt, és nem futtatja az LFS clean és smudge szűrőket: a add() változatlanul tárolja a fájlokat, a checkout() pedig mutatófájlokat ír. A tényleges tartalom letöltéséről az Ön kódjának kell gondoskodnia, az alábbi példa szerint.
LFS-mutatófájlok
Ha egy fájlt az LFS követ, a git a tényleges tartalom helyett mutatófájlt tárol:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
A mutató tartalma:
version: az LFS-specifikáció verziója, URLoid: a tényleges fájltartalom SHA-256 hashértéke (előtagjasha256:)size: a tényleges fájl mérete bájtban
Mutatók elemzése
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";
}
A parse() értéke null, ha hiányzik a version, oid sha256: vagy size sor. Az értékeket nem ellenőrzi (nem hexadecimális OID vagy nem numerikus méret is elfogadható).
Mutatók felismerése
if (LfsPointer::isPointer($blobContent)) {
// This blob is an LFS pointer, not actual file content
$pointer = LfsPointer::parse($blobContent);
}
A isPointer() teljes elemzés nélkül ellenőrzi a verzió-, URL- és oid sha256:-mezők, valamint a size mező meglétét.
Mutatók létrehozása
// 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
Mutatók szerializálása
$content = $pointer->serialize();
// "version https://git-lfs.github.com/spec/v1\noid sha256:4d7a21...\nsize 12345\n"
LFS-kliens
A LfsClient a kötegelt API használatával kommunikál az LFS-kiszolgálókkal (POST a következő címre: <url>/objects/batch).
Kliens létrehozása
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);
A fromRemoteUrl() metódus a szabványos konvenciót követi: a git URL címéhez hozzáfűzi a /info/lfs elemet (ha még nincs ott, előbb hozzáadja a .git részt). Használható LFS-URL-t csak a HTTP(S) távoli URL-ek adnak; az SCP-formátumú SSH távoli címek (git@host:repo.git) nem.
A LfsClient a PHP HTTP streamburkolóját használja (a allow_url_fopen beállítást engedélyezni kell). Nem küld hitelesítő adatokat, és figyelmen kívül hagyja a műveletenként visszakapott header leképezést, ezért csak hitelesítés nélküli LFS-kiszolgálókkal és tárhely-URL-ekkel működik. Nem kötődik repository-kezelőhöz, így hálózati kéréseket akkor is küld, ha a repository-t Pitmaster::processFreeOptions() beállítással nyitotta meg.
Fájlok letöltése
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);
A háttérben a download() a következőket teszi:
- Kötegelt kérést küld a
downloadművelethez - Letöltési URL választ kap a kiszolgálótól
- Letölti a fájltartalmat ebből a URL-ból
A letöltött bájtokat nem ellenőrzi az OID-vel vagy a mérettel.
Kötegelt letöltés
$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']
}
}
Fájlok feltöltése
$client->upload($pointer->oid, $pointer->size, $fileContent);
A feltöltés kötegelt kérést küld a upload művelethez. Ha a kiszolgálón már megtalálható az objektum, nem ad vissza feltöltési URL elemet, így a műveletnek nincs hatása. Magának a feltöltési kérésnek az eredményét nem ellenőrzi, ezért a sikertelen feltöltést nem jelzi, és a verify műveletet sem hívja meg.
Kötegelt feltöltés
$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
}
Kötegelt API protokoll
Az LFS kötegelt API protokollja a JSON protokollt használja a HTTP felett:
Kérés
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}
]
}
Válasz
{
"objects": [
{
"oid": "abc123...",
"size": 12345,
"actions": {
"download": {
"href": "https://storage.example.com/abc123...",
"header": {
"Authorization": "Bearer token"
}
}
}
}
]
}
LFS integrálása repository-műveletekkel
LFS-t használó repository olvasásakor a blob tartalma a tényleges fájladatok helyett LFS-mutató lehet. A tényleges tartalom lekéréséhez:
$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;
}
Hibakezelés
A sikertelen vagy érvénytelen kötegelt kérés, illetve a sikertelen letöltési kérés ProtocolException hibát dob. A download() akkor is hibát dob, ha a kiszolgáló nem ad vissza letöltési URL elemet az objektumhoz; a kiszolgáló hibaüzenetét ilyenkor nem tartalmazza. A batchDownload() és a batchUpload() objektumonkénti hibák esetén nem dob hibát, hanem a error mezőben adja vissza azokat.
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-mutató tulajdonságai
A LfsPointer osztály csak olvasható:
$pointer->oid; // string: SHA-256 hash (hex)
$pointer->size; // int: file size in bytes
$pointer->version; // string: spec version URL