| File: tests\Shared\CliPackageDiscovery.cs | Web Access |
| Project: src\tests\Aspire.Cli.EndToEnd.Tests\Aspire.Cli.EndToEnd.Tests.csproj (Aspire.Cli.EndToEnd.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.RegularExpressions; namespace Aspire.Tests.Shared; internal sealed record CliPackageInfo(string PackageId, string Version, string PackagePath); internal static partial class CliPackageDiscovery { internal const string AspireCliPackageId = "Aspire.Cli"; private const string AspireCliPackagePrefix = AspireCliPackageId + "."; private const string NupkgSuffix = ".nupkg"; internal static bool IsValidVersion(string version) { return VersionPattern().IsMatch(version); } internal static CliPackageInfo FindAspireCliPointerPackage(string packageDirectory) { return TryFindAspireCliPointerPackage(packageDirectory) ?? throw new InvalidOperationException( $"No Aspire.Cli tool nupkg found in '{packageDirectory}'. Expected exactly one non-symbol Aspire.Cli.{{version}}.nupkg package. Available files: {GetAvailableAspireCliPackageNames(packageDirectory)}"); } internal static CliPackageInfo? TryFindAspireCliPointerPackage(string packageDirectory) { var matches = Directory.GetFiles(packageDirectory, "Aspire.Cli.*.nupkg") .Where(path => IsPointerPackageFileName(Path.GetFileName(path))) .Select(path => new CliPackageInfo(AspireCliPackageId, GetVersion(path), path)) .OrderBy(package => Path.GetFileName(package.PackagePath), StringComparer.OrdinalIgnoreCase) .ToList(); if (matches.Count == 0) { return null; } if (matches.Count > 1) { throw new InvalidOperationException( $"Found {matches.Count} Aspire.Cli pointer nupkg files in '{packageDirectory}': {string.Join(", ", matches.Select(p => Path.GetFileName(p.PackagePath)))}. Expected exactly one Aspire.Cli.{{version}}.nupkg package."); } return matches[0]; } private static bool IsPointerPackageFileName(string? fileName) { if (string.IsNullOrEmpty(fileName) || fileName.EndsWith(".snupkg", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".symbols.nupkg", StringComparison.OrdinalIgnoreCase) || !fileName.StartsWith(AspireCliPackagePrefix, StringComparison.OrdinalIgnoreCase) || !fileName.EndsWith(NupkgSuffix, StringComparison.OrdinalIgnoreCase)) { return false; } if (RidSpecificPackagePattern().IsMatch(fileName)) { return false; } var version = fileName[AspireCliPackagePrefix.Length..^NupkgSuffix.Length]; return IsValidVersion(version); } private static string GetVersion(string packagePath) { var fileName = Path.GetFileName(packagePath); var version = fileName[AspireCliPackagePrefix.Length..^NupkgSuffix.Length]; if (!IsValidVersion(version)) { throw new InvalidOperationException( $"Invalid Aspire.Cli nupkg version '{version}' in '{fileName}'. Expected only alphanumeric characters, dots, and dashes."); } return version; } private static string GetAvailableAspireCliPackageNames(string packageDirectory) { if (!Directory.Exists(packageDirectory)) { return string.Empty; } return string.Join(", ", Directory.GetFiles(packageDirectory, "Aspire.Cli*.nupkg") .Select(Path.GetFileName) .OrderBy(name => name, StringComparer.OrdinalIgnoreCase)); } [GeneratedRegex(@"^[0-9A-Za-z.\-]+$")] private static partial Regex VersionPattern(); [GeneratedRegex(@"^Aspire\.Cli\.(win|linux|linux-musl|osx)-(x64|arm64)\.", RegexOptions.IgnoreCase)] private static partial Regex RidSpecificPackagePattern(); }