feat: add owned package staging cleanup
This commit is contained in:
@@ -71,11 +71,20 @@ public sealed class LocalPackageStore(string root, IFileHasher hasher) : ILocalP
|
||||
{
|
||||
if (!new PackageManifestValidator().Validate(manifest, manifest.ProductYear, manifest.Architecture).IsValid) throw new InvalidOperationException("MANIFEST_INVALID");
|
||||
if (manifest.Files.Any(x => string.Equals(x.Path, StoredManifestFileName, StringComparison.OrdinalIgnoreCase))) throw new InvalidOperationException("MANIFEST_RESERVED_FILE");
|
||||
var staging = Path.Combine(root, "Launcher", "staging", manifest.PackageId + "-" + manifest.Version + "-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(staging);
|
||||
var operationId = Guid.NewGuid().ToString("N"); var staging = Path.Combine(root, "Launcher", "staging", operationId); Directory.CreateDirectory(staging); await File.WriteAllTextAsync(Path.Combine(staging, ".package-staging-owner.json"), JsonSerializer.Serialize(new PackageStagingOwnership(operationId, manifest.PackageId, manifest.Version, staging, DateTimeOffset.UtcNow, operationId)), ct);
|
||||
try { var i = 0; foreach (var f in manifest.Files) { ct.ThrowIfCancellationRequested(); var source = Path.Combine(sourceRoot, f.Path); var dest = PackageFilePath(staging, f.Path); Directory.CreateDirectory(Path.GetDirectoryName(dest)!); File.Copy(source, dest, true); if (!string.Equals(await hasher.Sha256Async(dest, ct), f.Sha256, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("HASH_MISMATCH"); progress?.Report(new("copy", ++i, manifest.Files.Count)); }
|
||||
await File.WriteAllTextAsync(Path.Combine(staging, StoredManifestFileName), JsonSerializer.Serialize(manifest), ct);
|
||||
var versionDir = VersionDirectory(manifest.PackageId, manifest.Version); Directory.CreateDirectory(Path.GetDirectoryName(versionDir)!); if (Directory.Exists(versionDir)) Directory.Delete(staging, true); else Directory.Move(staging, versionDir); return new(manifest.PackageId, manifest.Version, versionDir); }
|
||||
catch { if (Directory.Exists(staging)) Directory.Delete(staging, true); throw; }
|
||||
File.Delete(marker); var versionDir = VersionDirectory(manifest.PackageId, manifest.Version); Directory.CreateDirectory(Path.GetDirectoryName(versionDir)!); if (Directory.Exists(versionDir)) Directory.Delete(staging, true); else Directory.Move(staging, versionDir); return new(manifest.PackageId, manifest.Version, versionDir); }
|
||||
catch { await CleanupOwnedStagingAsync(new PackageStagingOwnership(operationId, manifest.PackageId, manifest.Version, staging, DateTimeOffset.UtcNow, operationId), CancellationToken.None); throw; }
|
||||
}
|
||||
public async Task<PackageStagingCleanupResult> CleanupOwnedStagingAsync(PackageStagingOwnership ownership, CancellationToken ct)
|
||||
{
|
||||
var stagingRoot=Path.GetFullPath(Path.Combine(root,"Launcher","staging")); var directory=Path.GetFullPath(ownership.StagingDirectory); var prefix=stagingRoot.TrimEnd(Path.DirectorySeparatorChar)+Path.DirectorySeparatorChar;
|
||||
if (!directory.StartsWith(prefix,StringComparison.OrdinalIgnoreCase) || directory.Equals(stagingRoot,StringComparison.OrdinalIgnoreCase)) return new("OwnershipUnknown",ownership.OperationId);
|
||||
if (!Directory.Exists(directory)) return new("AlreadyAbsent",ownership.OperationId);
|
||||
var marker=Path.Combine(directory,".package-staging-owner.json"); if (!File.Exists(marker)) return new("OwnershipUnknown",ownership.OperationId);
|
||||
var stored=JsonSerializer.Deserialize<PackageStagingOwnership>(await File.ReadAllTextAsync(marker,ct)); if (stored is null || stored.OperationId!=ownership.OperationId || stored.PackageId!=ownership.PackageId || stored.Version!=ownership.Version) return new("OwnershipMismatch",ownership.OperationId);
|
||||
Directory.Delete(directory,true); return new("Cleaned",ownership.OperationId);
|
||||
}
|
||||
private async Task<string?> VerifyVersionAsync(PackageRequirement requirement, string version, CancellationToken ct)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user