Refactor code structure for improved readability and maintainability; optimize performance in key functions.
This commit is contained in:
141
src/Cli/StellaOps.Cli/Services/OciImageReferenceParser.cs
Normal file
141
src/Cli/StellaOps.Cli/Services/OciImageReferenceParser.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using StellaOps.Cli.Services.Models;
|
||||
|
||||
namespace StellaOps.Cli.Services;
|
||||
|
||||
internal static class OciImageReferenceParser
|
||||
{
|
||||
public static OciImageReference Parse(string reference)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reference))
|
||||
{
|
||||
throw new ArgumentException("Image reference is required.", nameof(reference));
|
||||
}
|
||||
|
||||
reference = reference.Trim();
|
||||
if (reference.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
|
||||
reference.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ParseUri(reference);
|
||||
}
|
||||
|
||||
var registry = string.Empty;
|
||||
var remainder = reference;
|
||||
var parts = reference.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (parts.Length > 1 && LooksLikeRegistry(parts[0]))
|
||||
{
|
||||
registry = parts[0];
|
||||
remainder = string.Join('/', parts.Skip(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
registry = "docker.io";
|
||||
}
|
||||
|
||||
var repository = remainder;
|
||||
string? tag = null;
|
||||
string? digest = null;
|
||||
|
||||
var atIndex = remainder.LastIndexOf('@');
|
||||
if (atIndex >= 0)
|
||||
{
|
||||
repository = remainder[..atIndex];
|
||||
digest = remainder[(atIndex + 1)..];
|
||||
}
|
||||
else
|
||||
{
|
||||
var lastColon = remainder.LastIndexOf(':');
|
||||
var lastSlash = remainder.LastIndexOf('/');
|
||||
if (lastColon > lastSlash)
|
||||
{
|
||||
repository = remainder[..lastColon];
|
||||
tag = remainder[(lastColon + 1)..];
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(repository))
|
||||
{
|
||||
throw new ArgumentException("Image repository is required.", nameof(reference));
|
||||
}
|
||||
|
||||
if (string.Equals(registry, "docker.io", StringComparison.OrdinalIgnoreCase) &&
|
||||
!repository.Contains('/', StringComparison.Ordinal))
|
||||
{
|
||||
repository = $"library/{repository}";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tag) && string.IsNullOrWhiteSpace(digest))
|
||||
{
|
||||
tag = "latest";
|
||||
}
|
||||
|
||||
return new OciImageReference
|
||||
{
|
||||
Registry = registry,
|
||||
Repository = repository,
|
||||
Tag = tag,
|
||||
Digest = digest,
|
||||
Original = reference
|
||||
};
|
||||
}
|
||||
|
||||
private static OciImageReference ParseUri(string reference)
|
||||
{
|
||||
if (!Uri.TryCreate(reference, UriKind.Absolute, out var uri))
|
||||
{
|
||||
throw new ArgumentException("Invalid image reference URI.", nameof(reference));
|
||||
}
|
||||
|
||||
var registry = uri.Authority;
|
||||
var remainder = uri.AbsolutePath.Trim('/');
|
||||
|
||||
string? tag = null;
|
||||
string? digest = null;
|
||||
|
||||
var atIndex = remainder.LastIndexOf('@');
|
||||
if (atIndex >= 0)
|
||||
{
|
||||
digest = remainder[(atIndex + 1)..];
|
||||
remainder = remainder[..atIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
var lastColon = remainder.LastIndexOf(':');
|
||||
if (lastColon > remainder.LastIndexOf('/'))
|
||||
{
|
||||
tag = remainder[(lastColon + 1)..];
|
||||
remainder = remainder[..lastColon];
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(registry, "docker.io", StringComparison.OrdinalIgnoreCase) &&
|
||||
!remainder.Contains('/', StringComparison.Ordinal))
|
||||
{
|
||||
remainder = $"library/{remainder}";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tag) && string.IsNullOrWhiteSpace(digest))
|
||||
{
|
||||
tag = "latest";
|
||||
}
|
||||
|
||||
return new OciImageReference
|
||||
{
|
||||
Registry = registry,
|
||||
Repository = remainder,
|
||||
Tag = tag,
|
||||
Digest = digest,
|
||||
Original = reference
|
||||
};
|
||||
}
|
||||
|
||||
private static bool LooksLikeRegistry(string value)
|
||||
{
|
||||
if (string.Equals(value, "localhost", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return value.Contains('.', StringComparison.Ordinal) || value.Contains(':', StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user