Git LFS
Git Large File Storage (LFS) erstatter store filer i dit repository med små pointerfiler. Selve filindholdet gemmes på en separat LFS-server. Pitmaster kan parse og oprette LFS-pointere og kommunikere med LFS-servere via batch-API. Den læser ikke .gitattributes og kører ikke LFS' clean- og smudge-filtre: add() gemmer filer, som de er, og checkout() skriver pointerfiler. Din kode skal selv hente det faktiske indhold, som vist nedenfor.
LFS-pointerfiler
Når en fil spores af LFS, gemmer git en pointerfil i stedet for det faktiske indhold:
version https://git-lfs.github.com/spec/v1
oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
size 12345
Pointeren indeholder:
version: LFS-specifikationsversionen URLoid: SHA-256-hash af filens faktiske indhold (med præfiksetsha256:)size: filens faktiske størrelse i bytes
Parsing af pointere
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() returnerer null, hvis linjen version, oid sha256: eller size mangler. Den validerer ikke værdierne (et OID, der ikke er hexadecimalt, eller en størrelse, der ikke er numerisk, accepteres).
Registrering af pointere
if (LfsPointer::isPointer($blobContent)) {
// This blob is an LFS pointer, not actual file content
$pointer = LfsPointer::parse($blobContent);
}
isPointer() kontrollerer, om felterne for version URL, oid sha256: og size findes, uden at foretage fuld parsing.
Oprettelse af pointere
// 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
Serialisering af pointere
$content = $pointer->serialize();
// "version https://git-lfs.github.com/spec/v1\noid sha256:4d7a21...\nsize 12345\n"
LFS-klient
LfsClient kommunikerer med LFS-servere ved hjælp af batch-API (POST til <url>/objects/batch).
Oprettelse af en klient
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()-metoden følger standardkonventionen: føj /info/lfs til git URL (og tilføj .git, hvis den ikke allerede findes). Kun HTTP(S)-remote-URL'er giver et brugbart LFS-URL; SCP-lignende SSH-remotes (git@host:repo.git) gør ikke.
LfsClient bruger PHPs HTTP-stream-wrapper (allow_url_fopen skal være aktiveret). Den sender ingen legitimationsoplysninger og ignorerer header-kortet, der returneres med hver handling, så den virker kun med LFS-servere og lager-URL'er, der ikke kræver godkendelse. Den er ikke knyttet til et repository-håndtag og foretager derfor netværksanmodninger, selv når du arbejder med et repository, der er åbnet med Pitmaster::processFreeOptions().
Download af filer
// Single file download
$content = $client->download($pointer->oid, $pointer->size);
file_put_contents('large-file.bin', $content);
I praksis gør download() følgende:
- Sender en batchanmodning for handlingen
download - Modtager en download-URL fra serveren
- Henter filindholdet fra denne URL
De downloadede bytes kontrolleres ikke mod OID'et eller størrelsen.
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']
}
}
Upload af filer
$client->upload($pointer->oid, $pointer->size, $fileContent);
Upload sender en batchanmodning for handlingen upload. Hvis serveren allerede har objektet, returneres ingen upload-URL, og handlingen gør intet. Selve uploadanmodningens resultat kontrolleres ikke, så en mislykket upload rapporteres ikke, og verify-handlingen kaldes ikke.
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-protokol
LFS-batch-API bruger JSON over HTTP:
Anmodning
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}
]
}
Svar
{
"objects": [
{
"oid": "abc123...",
"size": 12345,
"actions": {
"download": {
"href": "https://storage.example.com/abc123...",
"header": {
"Authorization": "Bearer token"
}
}
}
}
]
}
Integration af LFS med repository-operationer
Når du læser et repository, der bruger LFS, kan blob-indholdet være LFS-pointere i stedet for faktiske fildata. Sådan henter du det rigtige indhold:
$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;
}
Fejlhåndtering
En mislykket eller ugyldig batchanmodning og en mislykket downloadanmodning kaster ProtocolException. download() kaster også en fejl, når serveren ikke returnerer en download-URL for objektet, uden serverens fejlmeddelelse. batchDownload() og batchUpload() kaster ikke fejl ved fejl for enkelte objekter; de returnerer dem i feltet 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-pointeregenskaber
Klassen LfsPointer er skrivebeskyttet:
$pointer->oid; // string: SHA-256 hash (hex)
$pointer->size; // int: file size in bytes
$pointer->version; // string: spec version URL