feat: add typed local package pilot root
This commit is contained in:
@@ -10,8 +10,9 @@ internal static class PackageLifecyclePilotCli
|
|||||||
{
|
{
|
||||||
public static async Task<int> RunAsync(string[] args)
|
public static async Task<int> RunAsync(string[] args)
|
||||||
{
|
{
|
||||||
if (args.Length != 4 || args[0] != "--mode" || args[1] != "PackageLifecyclePilot" || args[2] != "--root" || !Path.IsPathFullyQualified(args[3]) || args[3].StartsWith(@"\\")) return 2;
|
if (args.Length != 4 || args[0] != "--mode" || args[1] != "PackageLifecyclePilot" || args[2] != "--root") return 2;
|
||||||
var root=Path.GetFullPath(args[3]); var id=Guid.NewGuid().ToString("N"); var evidenceDir=Path.Combine(root,"evidence",id); Directory.CreateDirectory(evidenceDir);
|
ResolvedPackagePilotRoot pilotRoot; try { pilotRoot=new PathResolver().ResolvePackagePilotRoot(args[3]); } catch { return 2; }
|
||||||
|
var root=pilotRoot.Value; var id=Guid.NewGuid().ToString("N"); var evidenceDir=Path.Combine(root,"evidence",id); Directory.CreateDirectory(evidenceDir);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var catalog=Path.Combine(root,"catalog"); Directory.CreateDirectory(catalog); var store=new LocalPackageStore(root,new Sha256FileHasher());
|
var catalog=Path.Combine(root,"catalog"); Directory.CreateDirectory(catalog); var store=new LocalPackageStore(root,new Sha256FileHasher());
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ public sealed record ResolvedLegacySettingsPath { internal ResolvedLegacySetting
|
|||||||
public sealed record ResolvedLegacyDownloadListPath { internal ResolvedLegacyDownloadListPath(string value) => Value=value; public string Value { get; } }
|
public sealed record ResolvedLegacyDownloadListPath { internal ResolvedLegacyDownloadListPath(string value) => Value=value; public string Value { get; } }
|
||||||
public sealed record ResolvedLegacyCompatibilityOverlayPath { internal ResolvedLegacyCompatibilityOverlayPath(string value) => Value=value; public string Value { get; } }
|
public sealed record ResolvedLegacyCompatibilityOverlayPath { internal ResolvedLegacyCompatibilityOverlayPath(string value) => Value=value; public string Value { get; } }
|
||||||
public sealed record ResolvedLegacyProbeEvidenceRoot { internal ResolvedLegacyProbeEvidenceRoot(string value) => Value=value; public string Value { get; } }
|
public sealed record ResolvedLegacyProbeEvidenceRoot { internal ResolvedLegacyProbeEvidenceRoot(string value) => Value=value; public string Value { get; } }
|
||||||
|
public sealed record ResolvedLocalPackageCacheRoot { internal ResolvedLocalPackageCacheRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
public sealed record ResolvedPackageVersionStoreRoot { internal ResolvedPackageVersionStoreRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
public sealed record ResolvedPackageStagingRoot { internal ResolvedPackageStagingRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
public sealed record ResolvedActivePackageRoot { internal ResolvedActivePackageRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
public sealed record ResolvedPackageLifecycleEvidenceRoot { internal ResolvedPackageLifecycleEvidenceRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
public sealed record ResolvedPackagePilotRoot { internal ResolvedPackagePilotRoot(string value)=>Value=value; public string Value{get;} }
|
||||||
|
|
||||||
public interface IPathResolver
|
public interface IPathResolver
|
||||||
{
|
{
|
||||||
@@ -41,6 +47,7 @@ public interface IPathResolver
|
|||||||
ResolvedLegacyDownloadListPath ResolveLegacyDownloadListPath(LauncherPathVariables variables);
|
ResolvedLegacyDownloadListPath ResolveLegacyDownloadListPath(LauncherPathVariables variables);
|
||||||
ResolvedLegacyCompatibilityOverlayPath ResolveLegacyCompatibilityOverlayPath(LauncherPathVariables variables);
|
ResolvedLegacyCompatibilityOverlayPath ResolveLegacyCompatibilityOverlayPath(LauncherPathVariables variables);
|
||||||
ResolvedLegacyProbeEvidenceRoot ResolveLegacyProbeEvidenceRoot(LauncherPathVariables variables);
|
ResolvedLegacyProbeEvidenceRoot ResolveLegacyProbeEvidenceRoot(LauncherPathVariables variables);
|
||||||
|
ResolvedPackagePilotRoot ResolvePackagePilotRoot(string value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PathResolver(IReadOnlyDictionary<string, string?>? environment = null) : IPathResolver
|
public sealed class PathResolver(IReadOnlyDictionary<string, string?>? environment = null) : IPathResolver
|
||||||
@@ -109,6 +116,8 @@ public sealed class PathResolver(IReadOnlyDictionary<string, string?>? environme
|
|||||||
if(value.StartsWith(@"\\",StringComparison.Ordinal)) throw new InvalidOperationException("LEGACY_PROBE_EVIDENCE_ROOT_NOT_LOCAL");
|
if(value.StartsWith(@"\\",StringComparison.Ordinal)) throw new InvalidOperationException("LEGACY_PROBE_EVIDENCE_ROOT_NOT_LOCAL");
|
||||||
return new(value);
|
return new(value);
|
||||||
}
|
}
|
||||||
|
public ResolvedPackagePilotRoot ResolvePackagePilotRoot(string value)
|
||||||
|
{ if (string.IsNullOrWhiteSpace(value)||value.Contains('*')||value.Contains('?')||value.StartsWith(@"\\")||!Path.IsPathFullyQualified(value)) throw new InvalidOperationException("PACKAGE_PILOT_ROOT_NOT_LOCAL"); var full=Path.GetFullPath(value); var info=new DirectoryInfo(full); if(info.Exists&&info.Attributes.HasFlag(FileAttributes.ReparsePoint)) throw new InvalidOperationException("PACKAGE_ROOT_REPARSE_REJECTED"); return new(full); }
|
||||||
private string ResolveExistingFile(string role, LauncherPathVariables variables)
|
private string ResolveExistingFile(string role, LauncherPathVariables variables)
|
||||||
{
|
{
|
||||||
var value=ResolvePath(Resolve(variables,[role]).Require(role),variables);
|
var value=ResolvePath(Resolve(variables,[role]).Require(role),variables);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ namespace Launcher.Next.Tests;
|
|||||||
|
|
||||||
public sealed class PackageLifecycleTests
|
public sealed class PackageLifecycleTests
|
||||||
{
|
{
|
||||||
|
[Fact] public void PilotRootRejectsUncAndRelativePaths()
|
||||||
|
{ var resolver=new PathResolver(new Dictionary<string,string?>()); Assert.Throws<InvalidOperationException>(()=>resolver.ResolvePackagePilotRoot(@"\\server\share")); Assert.Throws<InvalidOperationException>(()=>resolver.ResolvePackagePilotRoot("relative")); }
|
||||||
private static PackageRequirement Req(string version) => new("Lifecycle.Package", "Plant3D", 2026, "x64", "pilot", version, "lifecycle-test", true);
|
private static PackageRequirement Req(string version) => new("Lifecycle.Package", "Plant3D", 2026, "x64", "pilot", version, "lifecycle-test", true);
|
||||||
private static PackageManifest Manifest(string version, byte[] a, byte[] b) => new(1, "Lifecycle.Package", version, "Plant3D", 2026, "x64", "entry.dll", [
|
private static PackageManifest Manifest(string version, byte[] a, byte[] b) => new(1, "Lifecycle.Package", version, "Plant3D", 2026, "x64", "entry.dll", [
|
||||||
new("entry.dll", a.Length, Convert.ToHexString(SHA256.HashData(a))),
|
new("entry.dll", a.Length, Convert.ToHexString(SHA256.HashData(a))),
|
||||||
|
|||||||
Reference in New Issue
Block a user