semi implemented and features implemented save checkpoint

This commit is contained in:
master
2026-02-08 18:00:49 +02:00
parent 04360dff63
commit 1bf6bbf395
20895 changed files with 716795 additions and 64 deletions

View File

@@ -60,16 +60,14 @@ public sealed class OciArtifactPusher
try
{
var configDigest = await PushBlobAsync(reference, EmptyConfigBlob, OciMediaTypes.EmptyConfig, auth, cancellationToken)
.ConfigureAwait(false);
var configDigest = ComputeDigest(EmptyConfigBlob);
var layerDescriptors = new List<OciDescriptor>();
var layerDigests = new List<string>();
foreach (var layer in request.Layers)
{
var digest = await PushBlobAsync(reference, layer.Content, layer.MediaType, auth, cancellationToken)
.ConfigureAwait(false);
var digest = ComputeDigest(layer.Content);
layerDescriptors.Add(new OciDescriptor
{
@@ -86,7 +84,45 @@ public sealed class OciArtifactPusher
var manifestBytes = JsonSerializer.SerializeToUtf8Bytes(manifest, SerializerOptions);
var manifestDigest = ComputeDigest(manifestBytes);
var tag = reference.Tag ?? manifestDigest.Replace("sha256:", string.Empty, StringComparison.Ordinal);
var tag = request.Tag;
if (string.IsNullOrWhiteSpace(tag))
{
tag = reference.Tag ?? manifestDigest.Replace("sha256:", string.Empty, StringComparison.Ordinal);
}
if (request.SkipIfTagExists)
{
var existingDigest = await TryGetExistingManifestDigestAsync(reference, tag, auth, cancellationToken)
.ConfigureAwait(false);
if (existingDigest is not null)
{
if (string.IsNullOrWhiteSpace(existingDigest))
{
existingDigest = manifestDigest;
}
var existingReference = $"{reference.Registry}/{reference.Repository}@{existingDigest}";
_logger.LogInformation("OCI artifact already exists for tag {Tag}: {Reference}", tag, existingReference);
return new OciArtifactPushResult
{
Success = true,
AlreadyExists = true,
ManifestDigest = existingDigest,
ManifestReference = existingReference,
LayerDigests = layerDigests
};
}
}
await PushBlobAsync(reference, EmptyConfigBlob, OciMediaTypes.EmptyConfig, auth, cancellationToken)
.ConfigureAwait(false);
foreach (var layer in request.Layers)
{
await PushBlobAsync(reference, layer.Content, layer.MediaType, auth, cancellationToken)
.ConfigureAwait(false);
}
await PushManifestAsync(reference, manifestBytes, tag, auth, cancellationToken).ConfigureAwait(false);
var manifestReference = $"{reference.Registry}/{reference.Repository}@{manifestDigest}";
@@ -94,11 +130,12 @@ public sealed class OciArtifactPusher
_logger.LogInformation("Pushed OCI artifact {Reference}", manifestReference);
return new OciArtifactPushResult
{
Success = true,
ManifestDigest = manifestDigest,
ManifestReference = manifestReference,
LayerDigests = layerDigests
{
Success = true,
AlreadyExists = false,
ManifestDigest = manifestDigest,
ManifestReference = manifestReference,
LayerDigests = layerDigests
};
}
catch (OciRegistryException ex)
@@ -113,6 +150,40 @@ public sealed class OciArtifactPusher
}
}
private async Task<string?> TryGetExistingManifestDigestAsync(
OciImageReference reference,
string tag,
OciRegistryAuthorization auth,
CancellationToken cancellationToken)
{
var manifestUri = BuildRegistryUri(reference, $"manifests/{tag}");
using var request = new HttpRequestMessage(HttpMethod.Head, manifestUri);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(OciMediaTypes.ImageManifest));
auth.ApplyTo(request);
using var response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
if (response.StatusCode == HttpStatusCode.NotFound)
{
return null;
}
if (!response.IsSuccessStatusCode)
{
throw new OciRegistryException($"Manifest HEAD failed with {response.StatusCode}", "ERR_OCI_MANIFEST_HEAD");
}
if (response.Headers.TryGetValues("Docker-Content-Digest", out var digestValues))
{
var digest = digestValues.FirstOrDefault();
if (!string.IsNullOrWhiteSpace(digest))
{
return digest;
}
}
return string.Empty;
}
private OciArtifactManifest BuildManifest(
OciArtifactPushRequest request,
string configDigest,