Git LFS
Git Large File Storage (LFS) vervangt grote bestanden in uw repository door kleine pointerbestanden. De daadwerkelijke bestandsinhoud wordt op een aparte LFS-server opgeslagen. Pitmaster kan LFS-pointers parsen en aanmaken, en via de batch-API met LFS-servers communiceren. Het leest .gitattributes niet en voert de LFS clean- en smudge-filters niet uit: add() slaat bestanden ongewijzigd op en checkout() schrijft pointerbestanden. Uw code moet zelf de echte inhoud ophalen, zoals hieronder wordt getoond.
LFS-pointerbestanden
Wanneer een bestand door LFS wordt bijgehouden, slaat git een pointerbestand op in plaats van de daadwerkelijke inhoud:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
De pointer bevat:
version: de LFS-specificatieversie URLoid: hash van de daadwerkelijke bestandsinhoud volgens SHA-256 (met prefixsha256:)size: de daadwerkelijke bestandsgrootte in bytes
Pointers parsen
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() retourneert null wanneer de regel version, oid sha256: of size ontbreekt. De waarden worden niet gevalideerd (een niet-hexadecimale OID of niet-numerieke grootte wordt geaccepteerd).
Pointers detecteren
if (LfsPointer::isPointer($blobContent)) {
// This blob is an LFS pointer, not actual file content
$pointer = LfsPointer::parse($blobContent);
}
isPointer() controleert of de velden version URL, oid sha256: en size aanwezig zijn, zonder de pointer volledig te parsen.
Pointers aanmaken
// 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
Pointers serialiseren
$content = $pointer->serialize();
// "version https://git-lfs.github.com/spec/v1\noid sha256:4d7a21...\nsize 12345\n"
LFS-client
De LfsClient communiceert met LFS-servers via de batch-API (POST naar <url>/objects/batch).
Een client aanmaken
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);
De methode fromRemoteUrl() volgt de standaardconventie: voeg /info/lfs toe aan de git-URL (en voeg .git toe als dit ontbreekt). Alleen HTTP(S)-remote-URL's leveren een bruikbare LFS-URL op; SCP-achtige SSH-remotes (git@host:repo.git) niet.
LfsClient gebruikt de HTTP-streamwrapper van PHP (allow_url_fopen moet zijn ingeschakeld). Het verzendt geen referenties en negeert de header-map die bij elke actie wordt teruggestuurd; het werkt dus alleen met LFS-servers en opslag-URL's waarvoor geen authenticatie nodig is. Het is niet gekoppeld aan een repositoryhandle en doet daarom netwerkverzoeken, ook wanneer u werkt met een repository die is geopend met Pitmaster::processFreeOptions().
Bestanden downloaden
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);
Onder water doet download() het volgende:
- Verstuurt een batchverzoek voor de bewerking
download - Ontvangt een download-URL van de server
- Haalt de bestandsinhoud op via die URL
De gedownloade bytes worden niet gecontroleerd aan de hand van de OID of grootte.
Batchdownload
$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']
}
}
Bestanden uploaden
$client->upload($pointer->oid, $pointer->size, $fileContent);
Bij het uploaden wordt een batchverzoek voor de bewerking upload verstuurd. Als de server het object al heeft, retourneert deze geen upload-URL en wordt er niets gedaan. Het resultaat van het uploadverzoek zelf wordt niet gecontroleerd, waardoor een mislukte upload niet wordt gemeld en de actie verify niet wordt aangeroepen.
Batchupload
$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
}
Batch-API-protocol
De LFS-batch-API maakt gebruik van JSON via HTTP:
Verzoek
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}
]
}
Antwoord
{
"objects": [
{
"oid": "abc123...",
"size": 12345,
"actions": {
"download": {
"href": "https://storage.example.com/abc123...",
"header": {
"Authorization": "Bearer token"
}
}
}
}
]
}
LFS integreren met repositorybewerkingen
Bij het lezen van een repository die LFS gebruikt, kan de blobinhoud uit LFS-pointers bestaan in plaats van de daadwerkelijke bestandsgegevens. Zo haalt u de echte inhoud op:
$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;
}
Foutafhandeling
Een mislukt of ongeldig batchverzoek en een mislukt downloadverzoek veroorzaken ProtocolException. download() veroorzaakt dit ook als de server geen download-URL voor het object retourneert, zonder het foutbericht van de server. batchDownload() en batchUpload() veroorzaken geen fout bij fouten voor afzonderlijke objecten; ze retourneren deze in het veld 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";
}
LFS-pointereigenschappen
De class LfsPointer is alleen-lezen:
$pointer->oid; // string: SHA-256 hash (hex)
$pointer->size; // int: file size in bytes
$pointer->version; // string: spec version URL