feat: adapt roster sources into package resolution

This commit is contained in:
codex
2026-08-05 13:09:04 +03:00
parent cea9d70dc3
commit b83742b3a5
4 changed files with 195 additions and 0 deletions
@@ -0,0 +1,32 @@
using Launcher.Next.Core;
namespace Launcher.Next.Infrastructure;
/// <summary>
/// Reads a catalog descriptor only. The returned source is later copied into
/// local immutable staging by <see cref="IPackageSynchronizer"/>; it is never
/// an active launch root.
/// </summary>
public sealed class FileSystemCatalogPackageAcquirer(string catalogRoot) : IPackageCatalogPackageAcquirer
{
public async Task<CatalogPackage?> AcquireAsync(PackageRequirement requirement, CancellationToken cancellationToken)
{
var root = Path.GetFullPath(catalogRoot);
var candidate = Path.GetFullPath(Path.Combine(root, requirement.PackageId, requirement.RequiredVersion));
if (!IsWithin(root, candidate) || !Directory.Exists(candidate) || IsReparsePoint(candidate))
return null;
var manifestPath = Path.Combine(candidate, "package.manifest.json");
if (!File.Exists(manifestPath) || IsReparsePoint(manifestPath))
return null;
var manifest = PackageManifestJson.Parse(await File.ReadAllTextAsync(manifestPath, cancellationToken));
return new CatalogPackage(manifest, candidate);
}
private static bool IsWithin(string root, string candidate) =>
candidate.StartsWith(Path.TrimEndingDirectorySeparator(root) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
private static bool IsReparsePoint(string path) =>
(File.GetAttributes(path) & FileAttributes.ReparsePoint) != 0;
}