feat: add explicit package activation receipts
This commit is contained in:
@@ -17,6 +17,9 @@ public sealed record ValidationResult(IReadOnlyList<ValidationIssue> Issues)
|
|||||||
{ public bool IsValid => Issues.Count == 0; public static ValidationResult Success { get; } = new([]); }
|
{ public bool IsValid => Issues.Count == 0; public static ValidationResult Success { get; } = new([]); }
|
||||||
public sealed record PackageProgress(string Stage, int Completed, int Total);
|
public sealed record PackageProgress(string Stage, int Completed, int Total);
|
||||||
public sealed record ActivationResult(string CurrentVersion, string? PreviousVersion);
|
public sealed record ActivationResult(string CurrentVersion, string? PreviousVersion);
|
||||||
|
public sealed record PackageActivationReceipt(string OperationId, string PackageId, string Version, string? PreviousVersion, DateTimeOffset ActivatedUtc);
|
||||||
|
public sealed record PackageActivationResult(string Outcome, PackageActivationReceipt? Receipt);
|
||||||
|
public sealed record PackageRollbackResult(string Outcome, string? CurrentVersion);
|
||||||
public sealed record PackageRequirement(string PackageId, string Product, int ProductYear, string Architecture, string Channel, string RequiredVersion, string RosterIdentity, bool AllowOfflineFallback);
|
public sealed record PackageRequirement(string PackageId, string Product, int ProductYear, string Architecture, string Channel, string RequiredVersion, string RosterIdentity, bool AllowOfflineFallback);
|
||||||
public sealed record CatalogPackage(PackageManifest Manifest, string SourceRoot);
|
public sealed record CatalogPackage(PackageManifest Manifest, string SourceRoot);
|
||||||
public sealed record PackageResolutionEvidence(string Code, string Detail);
|
public sealed record PackageResolutionEvidence(string Code, string Detail);
|
||||||
|
|||||||
@@ -29,6 +29,22 @@ public sealed class LocalPackageStore(string root, IFileHasher hasher) : ILocalP
|
|||||||
var temp = PointerPath(id) + ".tmp"; await File.WriteAllTextAsync(temp, JsonSerializer.Serialize(new Pointer(version, prior?.Current)), ct); File.Move(temp, PointerPath(id), true);
|
var temp = PointerPath(id) + ".tmp"; await File.WriteAllTextAsync(temp, JsonSerializer.Serialize(new Pointer(version, prior?.Current)), ct); File.Move(temp, PointerPath(id), true);
|
||||||
return new(version, prior?.Current);
|
return new(version, prior?.Current);
|
||||||
}
|
}
|
||||||
|
public async Task<PackageActivationResult> ActivateImmutableAsync(ImmutableLocalPackage package, PackageRequirement requirement, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (!string.Equals(package.PackageId, requirement.PackageId, StringComparison.Ordinal) || !string.Equals(package.Version, requirement.RequiredVersion, StringComparison.Ordinal)) return new("Blocked", null);
|
||||||
|
var prior = await ReadPointer(package.PackageId, ct);
|
||||||
|
if (prior?.Current == package.Version) return new("AlreadyActiveExact", new(Guid.NewGuid().ToString("N"), package.PackageId, package.Version, prior.Previous, DateTimeOffset.UtcNow));
|
||||||
|
var activated = await ActivateAsync(package.PackageId, package.Version, ct);
|
||||||
|
return new("Activated", new(Guid.NewGuid().ToString("N"), package.PackageId, activated.CurrentVersion, activated.PreviousVersion, DateTimeOffset.UtcNow));
|
||||||
|
}
|
||||||
|
public async Task<PackageRollbackResult> RollbackAsync(PackageActivationReceipt receipt, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var current=await GetCurrentVersionAsync(receipt.PackageId,ct);
|
||||||
|
if (!string.Equals(current,receipt.Version,StringComparison.Ordinal)) return new("RollbackBlockedStateChanged",current);
|
||||||
|
if (string.IsNullOrWhiteSpace(receipt.PreviousVersion)) return new("RollbackNotApplicable",current);
|
||||||
|
var restored=await ActivateAsync(receipt.PackageId,receipt.PreviousVersion,ct);
|
||||||
|
return new("RolledBack",restored.CurrentVersion);
|
||||||
|
}
|
||||||
public async Task<string?> RollbackAsync(string id, CancellationToken ct) { var p = await ReadPointer(id, ct); return p?.Previous is null ? null : (await ActivateAsync(id, p.Previous, ct)).CurrentVersion; }
|
public async Task<string?> RollbackAsync(string id, CancellationToken ct) { var p = await ReadPointer(id, ct); return p?.Previous is null ? null : (await ActivateAsync(id, p.Previous, ct)).CurrentVersion; }
|
||||||
public async Task BindAsync(PackageRequirement requirement, string version, CancellationToken ct)
|
public async Task BindAsync(PackageRequirement requirement, string version, CancellationToken ct)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user