diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f036fd9d..932b9c21 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,7 +29,7 @@ jobs:
- name: Install .NET Core
uses: actions/setup-dotnet@v4
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '8.0.x'
- name: Build & test (Release)
run: dotnet test src -c Release
diff --git a/Dockerfile b/Dockerfile
index 0c8c702f..a6722338 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,20 +1,20 @@
-FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS build
-ARG TARGETARCH
-WORKDIR /app
-
-RUN mkdir -p src/UnityNuGet && mkdir -p src/UnityNuGet.Server && mkdir -p src/UnityNuGet.Tests
-
-COPY src/*.sln src
-COPY src/UnityNuGet/*.csproj src/UnityNuGet
-COPY src/UnityNuGet.Server/*.csproj src/UnityNuGet.Server
-COPY src/UnityNuGet.Tests/*.csproj src/UnityNuGet.Tests
-RUN dotnet restore src -a $TARGETARCH
-
-COPY . ./
-RUN dotnet publish src -a $TARGETARCH -c Release -o /app/src/out
-
-# Build runtime image
-FROM mcr.microsoft.com/dotnet/aspnet:7.0
-WORKDIR /app
-COPY --from=build /app/src/out .
-ENTRYPOINT ["dotnet", "UnityNuGet.Server.dll"]
+FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+ARG TARGETARCH
+WORKDIR /app
+
+RUN mkdir -p src/UnityNuGet && mkdir -p src/UnityNuGet.Server && mkdir -p src/UnityNuGet.Tests
+
+COPY src/*.sln src
+COPY src/UnityNuGet/*.csproj src/UnityNuGet
+COPY src/UnityNuGet.Server/*.csproj src/UnityNuGet.Server
+COPY src/UnityNuGet.Tests/*.csproj src/UnityNuGet.Tests
+RUN dotnet restore src -a $TARGETARCH
+
+COPY . ./
+RUN dotnet publish src -a $TARGETARCH -c Release -o /app/src/out
+
+# Build runtime image
+FROM mcr.microsoft.com/dotnet/aspnet:8.0
+WORKDIR /app
+COPY --from=build /app/src/out .
+ENTRYPOINT ["dotnet", "UnityNuGet.Server.dll"]
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 00000000..b91d59b2
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,8 @@
+
+
+
+ enable
+ true
+
+
+
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
new file mode 100644
index 00000000..a423acc8
--- /dev/null
+++ b/src/Directory.Packages.props
@@ -0,0 +1,24 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/UnityNuGet.Server/Controllers/ApiController.cs b/src/UnityNuGet.Server/Controllers/ApiController.cs
index 95aade7a..43d3cc15 100644
--- a/src/UnityNuGet.Server/Controllers/ApiController.cs
+++ b/src/UnityNuGet.Server/Controllers/ApiController.cs
@@ -1,130 +1,124 @@
-using System.IO;
-using System.Linq;
-using System.Text;
-using Microsoft.AspNetCore.Mvc;
-using UnityNuGet.Npm;
-
-namespace UnityNuGet.Server.Controllers
-{
- ///
- /// Main entry to emulate the following NPM endpoints:
- ///
- /// - "-/all": query all packages (return json)
- /// - "{packageId}": query a specific package (return json)
- /// - "{package_id}/-/{package_file}": download a specific package
- ///
- [Route("")]
- [ApiController]
- public class ApiController : ControllerBase
- {
- private readonly RegistryCacheSingleton _cacheSingleton;
- private readonly RegistryCacheReport _registryCacheReport;
-
- public ApiController(RegistryCacheSingleton cacheSingleton, RegistryCacheReport registryCacheReport)
- {
- _cacheSingleton = cacheSingleton;
- _registryCacheReport = registryCacheReport;
- }
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.AspNetCore.Mvc;
+using UnityNuGet.Npm;
+
+namespace UnityNuGet.Server.Controllers
+{
+ ///
+ /// Main entry to emulate the following NPM endpoints:
+ ///
+ /// - "-/all": query all packages (return json)
+ /// - "{packageId}": query a specific package (return json)
+ /// - "{package_id}/-/{package_file}": download a specific package
+ ///
+ [Route("")]
+ [ApiController]
+ public class ApiController(RegistryCacheSingleton cacheSingleton, RegistryCacheReport registryCacheReport) : ControllerBase
+ {
+ private readonly RegistryCacheSingleton _cacheSingleton = cacheSingleton;
+ private readonly RegistryCacheReport _registryCacheReport = registryCacheReport;
// GET /
- [HttpGet("")]
- public IActionResult Home()
- {
- return Ok();
- }
-
- // GET -/all
- [HttpGet("-/all")]
- public JsonResult GetAll()
- {
- if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
-
- var result = instance?.All();
- return new JsonResult(result);
- }
-
- // GET {packageId}
- [HttpGet("{id}")]
- public JsonResult GetPackage(string id)
- {
- if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
-
- var package = instance?.GetPackage(id);
- if (package == null)
- {
- return new JsonResult(NpmError.NotFound);
- }
-
- return new JsonResult(package);
- }
-
- // GET {package_id}/-/{package_file}
- [HttpGet("{id}/-/{file}")]
- [HttpHead("{id}/-/{file}")]
- public IActionResult DownloadPackage(string id, string file)
- {
- if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
-
- var package = instance?.GetPackage(id);
- if (package == null)
- {
- return new JsonResult(NpmError.NotFound);
- }
-
- if (!file.StartsWith(id + "-") || !file.EndsWith(".tgz"))
- {
- return new JsonResult(NpmError.NotFound);
- }
-
- var filePath = instance?.GetPackageFilePath(file);
- if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath))
- {
- return new JsonResult(NpmError.NotFound);
- }
-
- // This method can be called with HEAD request, so in that case we just calculate the content length
- if (Request.Method.Equals("HEAD"))
- {
- Response.ContentType = "application/octet-stream";
- Response.ContentLength = new FileInfo(filePath).Length;
- return Ok();
- }
- else
- {
- return new PhysicalFileResult(filePath, "application/octet-stream") { FileDownloadName = file };
- }
- }
-
- private bool TryGetInstance(out RegistryCache? cacheInstance, out NpmError? npmError)
- {
- var instance = _cacheSingleton.Instance;
- cacheInstance = instance;
-
- if (instance == null)
- {
- if (_registryCacheReport.ErrorMessages.Any())
- {
- var stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Error initializing the server:");
-
- foreach (var error in _registryCacheReport.ErrorMessages)
- {
- stringBuilder.AppendLine(error);
- }
-
- npmError = new NpmError("not_initialized", stringBuilder.ToString());
- }
- else
- {
- npmError = new NpmError("not_initialized", $"The server is initializing ({_registryCacheReport.Progress:F1}% completed). Please retry later...");
- }
- }
- else
- {
- npmError = null;
- }
-
- return instance != null;
- }
- }
-}
+ [HttpGet("")]
+ public IActionResult Home()
+ {
+ return Ok();
+ }
+
+ // GET -/all
+ [HttpGet("-/all")]
+ public JsonResult GetAll()
+ {
+ if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
+
+ var result = instance?.All();
+ return new JsonResult(result);
+ }
+
+ // GET {packageId}
+ [HttpGet("{id}")]
+ public JsonResult GetPackage(string id)
+ {
+ if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
+
+ var package = instance?.GetPackage(id);
+ if (package == null)
+ {
+ return new JsonResult(NpmError.NotFound);
+ }
+
+ return new JsonResult(package);
+ }
+
+ // GET {package_id}/-/{package_file}
+ [HttpGet("{id}/-/{file}")]
+ [HttpHead("{id}/-/{file}")]
+ public IActionResult DownloadPackage(string id, string file)
+ {
+ if (!TryGetInstance(out var instance, out var error)) return new JsonResult(error);
+
+ var package = instance?.GetPackage(id);
+ if (package == null)
+ {
+ return new JsonResult(NpmError.NotFound);
+ }
+
+ if (!file.StartsWith(id + "-") || !file.EndsWith(".tgz"))
+ {
+ return new JsonResult(NpmError.NotFound);
+ }
+
+ var filePath = instance?.GetPackageFilePath(file);
+ if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath))
+ {
+ return new JsonResult(NpmError.NotFound);
+ }
+
+ // This method can be called with HEAD request, so in that case we just calculate the content length
+ if (Request.Method.Equals("HEAD"))
+ {
+ Response.ContentType = "application/octet-stream";
+ Response.ContentLength = new FileInfo(filePath).Length;
+ return Ok();
+ }
+ else
+ {
+ return new PhysicalFileResult(filePath, "application/octet-stream") { FileDownloadName = file };
+ }
+ }
+
+ private bool TryGetInstance(out RegistryCache? cacheInstance, out NpmError? npmError)
+ {
+ var instance = _cacheSingleton.Instance;
+ cacheInstance = instance;
+
+ if (instance == null)
+ {
+ if (_registryCacheReport.ErrorMessages.Any())
+ {
+ var stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine("Error initializing the server:");
+
+ foreach (var error in _registryCacheReport.ErrorMessages)
+ {
+ stringBuilder.AppendLine(error);
+ }
+
+ npmError = new NpmError("not_initialized", stringBuilder.ToString());
+ }
+ else
+ {
+ npmError = new NpmError("not_initialized", $"The server is initializing ({_registryCacheReport.Progress:F1}% completed). Please retry later...");
+ }
+ }
+ else
+ {
+ npmError = null;
+ }
+
+ return instance != null;
+ }
+ }
+}
diff --git a/src/UnityNuGet.Server/NuGetRedirectLogger.cs b/src/UnityNuGet.Server/NuGetRedirectLogger.cs
index 1dd600ff..3e03d271 100644
--- a/src/UnityNuGet.Server/NuGetRedirectLogger.cs
+++ b/src/UnityNuGet.Server/NuGetRedirectLogger.cs
@@ -1,47 +1,42 @@
-using System;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using NuGet.Common;
-using ILogger = Microsoft.Extensions.Logging.ILogger;
-using LogLevel = NuGet.Common.LogLevel;
-
-namespace UnityNuGet.Server
-{
- ///
- /// A NuGet logger redirecting to a
- ///
- public class NuGetRedirectLogger : LoggerBase
- {
- private readonly ILogger _logger;
-
- public NuGetRedirectLogger(ILogger logger)
- {
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- }
-
- public override void Log(ILogMessage message)
- {
- LoggerExtensions.Log(_logger, GetLogLevel(message.Level), "{Message}", message.Message);
- }
-
- public override Task LogAsync(ILogMessage message)
- {
- LoggerExtensions.Log(_logger, GetLogLevel(message.Level), "{Message}", message.Message);
- return Task.CompletedTask;
- }
-
- private static Microsoft.Extensions.Logging.LogLevel GetLogLevel(LogLevel logLevel)
- {
- return logLevel switch
- {
- LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug,
- LogLevel.Verbose => Microsoft.Extensions.Logging.LogLevel.Trace,
- LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information,
- LogLevel.Minimal => Microsoft.Extensions.Logging.LogLevel.Information,
- LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning,
- LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error,
- _ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null),
- };
- }
- }
-}
+using System;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using NuGet.Common;
+using ILogger = Microsoft.Extensions.Logging.ILogger;
+using LogLevel = NuGet.Common.LogLevel;
+
+namespace UnityNuGet.Server
+{
+ ///
+ /// A NuGet logger redirecting to a
+ ///
+ public class NuGetRedirectLogger(ILogger logger) : LoggerBase
+ {
+ private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+
+ public override void Log(ILogMessage message)
+ {
+ LoggerExtensions.Log(_logger, GetLogLevel(message.Level), "{Message}", message.Message);
+ }
+
+ public override Task LogAsync(ILogMessage message)
+ {
+ LoggerExtensions.Log(_logger, GetLogLevel(message.Level), "{Message}", message.Message);
+ return Task.CompletedTask;
+ }
+
+ private static Microsoft.Extensions.Logging.LogLevel GetLogLevel(LogLevel logLevel)
+ {
+ return logLevel switch
+ {
+ LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug,
+ LogLevel.Verbose => Microsoft.Extensions.Logging.LogLevel.Trace,
+ LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information,
+ LogLevel.Minimal => Microsoft.Extensions.Logging.LogLevel.Information,
+ LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning,
+ LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error,
+ _ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null),
+ };
+ }
+ }
+}
diff --git a/src/UnityNuGet.Server/RegistryCacheInitializer.cs b/src/UnityNuGet.Server/RegistryCacheInitializer.cs
index 9d6f8892..4fdc8f65 100644
--- a/src/UnityNuGet.Server/RegistryCacheInitializer.cs
+++ b/src/UnityNuGet.Server/RegistryCacheInitializer.cs
@@ -1,82 +1,73 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-
-namespace UnityNuGet.Server
-{
- public class RegistryCacheInitializer : IHostedService
- {
- private readonly IConfiguration configuration;
- private readonly IHostEnvironment hostEnvironment;
- private readonly ILoggerFactory loggerFactory;
- private readonly RegistryOptions registryOptions;
- private readonly RegistryCacheSingleton registryCacheSingleton;
-
- public RegistryCacheInitializer(IConfiguration configuration, IHostEnvironment hostEnvironment, ILoggerFactory loggerFactory, IOptions registryOptionsAccessor, RegistryCacheSingleton registryCacheSingleton)
- {
- this.configuration = configuration;
- this.hostEnvironment = hostEnvironment;
- this.loggerFactory = loggerFactory;
- registryOptions = registryOptionsAccessor.Value;
- this.registryCacheSingleton = registryCacheSingleton;
- }
-
- public Task StartAsync(CancellationToken cancellationToken)
- {
- var loggerRedirect = new NuGetRedirectLogger(loggerFactory.CreateLogger("NuGet"));
-
- Uri uri = registryOptions.RootHttpUrl!;
-
- bool isDevelopment = hostEnvironment.IsDevelopment();
- if (isDevelopment)
- {
- var urls = configuration[WebHostDefaults.ServerUrlsKey];
-
- // Select HTTPS in production, HTTP in development
- var url = (urls?.Split(';').FirstOrDefault(x => !x.StartsWith("https"))) ?? throw new InvalidOperationException($"Unable to find a proper server URL from `{urls}`. Expecting a `http://...` URL in development");
-
- // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#dotnet_running_in_container-and-dotnet_running_in_containers
- bool runningInContainer = configuration.GetValue("DOTNET_RUNNING_IN_CONTAINER");
-
- uri = new Uri(runningInContainer ? url.Replace("+", "localhost") : url);
- }
-
- // Get the current directory from registry options (prepend binary folder in dev)
- string unityPackageFolder;
-
- if (isDevelopment)
- {
- var currentDirectory = Path.GetDirectoryName(typeof(Startup).Assembly.Location)!;
- unityPackageFolder = Path.Combine(currentDirectory, new DirectoryInfo(registryOptions.RootPersistentFolder!).Name);
- }
- else
- {
- if (Path.IsPathRooted(registryOptions.RootPersistentFolder))
- {
- unityPackageFolder = registryOptions.RootPersistentFolder;
- }
- else
- {
- unityPackageFolder = Path.Combine(Directory.GetCurrentDirectory(), registryOptions.RootPersistentFolder!);
- }
- }
- loggerRedirect.LogInformation($"Using Unity Package folder `{unityPackageFolder}`");
-
- // Add the cache accessible from the services
- registryCacheSingleton.UnityPackageFolder = unityPackageFolder;
- registryCacheSingleton.ServerUri = uri;
- registryCacheSingleton.NuGetRedirectLogger = loggerRedirect;
-
- return Task.CompletedTask;
- }
-
- public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
- }
-}
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace UnityNuGet.Server
+{
+ public class RegistryCacheInitializer(IConfiguration configuration, IHostEnvironment hostEnvironment, ILoggerFactory loggerFactory, IOptions registryOptionsAccessor, RegistryCacheSingleton registryCacheSingleton) : IHostedService
+ {
+ private readonly IConfiguration configuration = configuration;
+ private readonly IHostEnvironment hostEnvironment = hostEnvironment;
+ private readonly ILoggerFactory loggerFactory = loggerFactory;
+ private readonly RegistryOptions registryOptions = registryOptionsAccessor.Value;
+ private readonly RegistryCacheSingleton registryCacheSingleton = registryCacheSingleton;
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ var loggerRedirect = new NuGetRedirectLogger(loggerFactory.CreateLogger("NuGet"));
+
+ Uri uri = registryOptions.RootHttpUrl!;
+
+ bool isDevelopment = hostEnvironment.IsDevelopment();
+ if (isDevelopment)
+ {
+ var urls = configuration[WebHostDefaults.ServerUrlsKey];
+
+ // Select HTTPS in production, HTTP in development
+ var url = (urls?.Split(';').FirstOrDefault(x => !x.StartsWith("https"))) ?? throw new InvalidOperationException($"Unable to find a proper server URL from `{urls}`. Expecting a `http://...` URL in development");
+
+ // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#dotnet_running_in_container-and-dotnet_running_in_containers
+ bool runningInContainer = configuration.GetValue("DOTNET_RUNNING_IN_CONTAINER");
+
+ uri = new Uri(runningInContainer ? url.Replace("+", "localhost") : url);
+ }
+
+ // Get the current directory from registry options (prepend binary folder in dev)
+ string unityPackageFolder;
+
+ if (isDevelopment)
+ {
+ var currentDirectory = Path.GetDirectoryName(typeof(Startup).Assembly.Location)!;
+ unityPackageFolder = Path.Combine(currentDirectory, new DirectoryInfo(registryOptions.RootPersistentFolder!).Name);
+ }
+ else
+ {
+ if (Path.IsPathRooted(registryOptions.RootPersistentFolder))
+ {
+ unityPackageFolder = registryOptions.RootPersistentFolder;
+ }
+ else
+ {
+ unityPackageFolder = Path.Combine(Directory.GetCurrentDirectory(), registryOptions.RootPersistentFolder!);
+ }
+ }
+ loggerRedirect.LogInformation($"Using Unity Package folder `{unityPackageFolder}`");
+
+ // Add the cache accessible from the services
+ registryCacheSingleton.UnityPackageFolder = unityPackageFolder;
+ registryCacheSingleton.ServerUri = uri;
+ registryCacheSingleton.NuGetRedirectLogger = loggerRedirect;
+
+ return Task.CompletedTask;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+ }
+}
diff --git a/src/UnityNuGet.Server/RegistryCacheReport.cs b/src/UnityNuGet.Server/RegistryCacheReport.cs
index 4861e521..f50b4ad3 100644
--- a/src/UnityNuGet.Server/RegistryCacheReport.cs
+++ b/src/UnityNuGet.Server/RegistryCacheReport.cs
@@ -1,84 +1,78 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.Options;
-
-namespace UnityNuGet.Server
-{
- ///
- /// Main class that stores relevant messages that may appear during the build of the Unity packages with .
- ///
- public class RegistryCacheReport
- {
- private readonly IList _informationMessages = new List();
- private readonly IList _warningMessages = new List();
- private readonly IList _errorMessages = new List();
-
- private DateTime? _lastUpdate;
-
- private readonly RegistryCacheSingleton _registryCacheSingleton;
- private readonly RegistryOptions _registryOptions;
-
- public RegistryCacheReport(RegistryCacheSingleton registryCacheSingleton, IOptions registryOptionsAccessor)
- {
- _registryCacheSingleton = registryCacheSingleton;
- _registryOptions = registryOptionsAccessor.Value;
- }
-
- public IEnumerable InformationMeessages => _informationMessages;
-
- public IEnumerable WarningMessages => _warningMessages;
-
- public IEnumerable ErrorMessages => _errorMessages;
-
- public bool Running { get; private set; }
-
- public double Progress
- {
- get
- {
- var currentIndex = _registryCacheSingleton.ProgressPackageIndex;
- var totalCount = _registryCacheSingleton.ProgressTotalPackageCount;
- var percent = totalCount != 0 ? (double)currentIndex * 100 / totalCount : 0;
-
- return percent;
- }
- }
-
- public TimeSpan? TimeRemainingForNextUpdate
- {
- get
- {
- if (_errorMessages.Count == 0)
- {
- return _lastUpdate != null ? _lastUpdate.Value.Add(_registryOptions.UpdateInterval) - DateTime.UtcNow : null;
- }
- else
- {
- return TimeSpan.FromSeconds(0);
- }
- }
- }
-
- public void AddInformation(string message) => _informationMessages.Add(message);
-
- public void AddWarning(string message) => _warningMessages.Add(message);
-
- public void AddError(string message) => _errorMessages.Add(message);
-
- public void Start()
- {
- Running = true;
-
- _informationMessages.Clear();
- _warningMessages.Clear();
- _errorMessages.Clear();
- }
-
- public void Complete()
- {
- Running = false;
-
- _lastUpdate = DateTime.UtcNow;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Options;
+
+namespace UnityNuGet.Server
+{
+ ///
+ /// Main class that stores relevant messages that may appear during the build of the Unity packages with .
+ ///
+ public class RegistryCacheReport(RegistryCacheSingleton registryCacheSingleton, IOptions registryOptionsAccessor)
+ {
+ private readonly RegistryCacheSingleton _registryCacheSingleton = registryCacheSingleton;
+ private readonly RegistryOptions _registryOptions = registryOptionsAccessor.Value;
+
+ private readonly List _informationMessages = [];
+ private readonly List _warningMessages = [];
+ private readonly List _errorMessages = [];
+
+ private DateTime? _lastUpdate;
+
+ public IEnumerable InformationMeessages => _informationMessages;
+
+ public IEnumerable WarningMessages => _warningMessages;
+
+ public IEnumerable ErrorMessages => _errorMessages;
+
+ public bool Running { get; private set; }
+
+ public double Progress
+ {
+ get
+ {
+ var currentIndex = _registryCacheSingleton.ProgressPackageIndex;
+ var totalCount = _registryCacheSingleton.ProgressTotalPackageCount;
+ var percent = totalCount != 0 ? (double)currentIndex * 100 / totalCount : 0;
+
+ return percent;
+ }
+ }
+
+ public TimeSpan? TimeRemainingForNextUpdate
+ {
+ get
+ {
+ if (_errorMessages.Count == 0)
+ {
+ return _lastUpdate != null ? _lastUpdate.Value.Add(_registryOptions.UpdateInterval) - DateTime.UtcNow : null;
+ }
+ else
+ {
+ return TimeSpan.FromSeconds(0);
+ }
+ }
+ }
+
+ public void AddInformation(string message) => _informationMessages.Add(message);
+
+ public void AddWarning(string message) => _warningMessages.Add(message);
+
+ public void AddError(string message) => _errorMessages.Add(message);
+
+ public void Start()
+ {
+ Running = true;
+
+ _informationMessages.Clear();
+ _warningMessages.Clear();
+ _errorMessages.Clear();
+ }
+
+ public void Complete()
+ {
+ Running = false;
+
+ _lastUpdate = DateTime.UtcNow;
+ }
+ }
+}
diff --git a/src/UnityNuGet.Server/RegistryCacheUpdater.cs b/src/UnityNuGet.Server/RegistryCacheUpdater.cs
index d3dbdd95..aed12d3f 100644
--- a/src/UnityNuGet.Server/RegistryCacheUpdater.cs
+++ b/src/UnityNuGet.Server/RegistryCacheUpdater.cs
@@ -1,82 +1,74 @@
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-
-namespace UnityNuGet.Server
-{
- ///
- /// Update the RegistryCache at a regular interval
- ///
- internal sealed class RegistryCacheUpdater : BackgroundService
- {
- private readonly RegistryCacheReport _registryCacheReport;
- private readonly RegistryCacheSingleton _currentRegistryCache;
- private readonly ILogger _logger;
- private readonly RegistryOptions _registryOptions;
-
- public RegistryCacheUpdater(RegistryCacheReport registryCacheReport, RegistryCacheSingleton currentRegistryCache, ILogger logger, IOptions registryOptionsAccessor)
- {
- _registryCacheReport = registryCacheReport;
- _currentRegistryCache = currentRegistryCache;
- _logger = logger;
- _registryOptions = registryOptionsAccessor.Value;
- }
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- try
- {
- while (!stoppingToken.IsCancellationRequested)
- {
- _logger.LogInformation("Starting to update RegistryCache");
-
- _registryCacheReport.Start();
-
- var newRegistryCache = new RegistryCache(_currentRegistryCache.UnityPackageFolder!, _currentRegistryCache.ServerUri!, _registryOptions.UnityScope!, _registryOptions.MinimumUnityVersion!, _registryOptions.PackageNameNuGetPostFix!, _registryOptions.TargetFrameworks!, _currentRegistryCache.NuGetRedirectLogger!)
- {
- // Update progress
- OnProgress = (current, total) =>
- {
- _currentRegistryCache.ProgressTotalPackageCount = total;
- _currentRegistryCache.ProgressPackageIndex = current;
- },
- OnInformation = message => _registryCacheReport.AddInformation(message),
- OnWarning = message => _registryCacheReport.AddWarning(message),
- OnError = message => _registryCacheReport.AddError(message)
- };
-
- await newRegistryCache.Build();
-
- if (_registryCacheReport.ErrorMessages.Any())
- {
- _logger.LogInformation("RegistryCache not updated due to errors. See previous logs");
- }
- else
- {
- // Update the registry cache in the services
- _currentRegistryCache.Instance = newRegistryCache;
-
- _logger.LogInformation("RegistryCache successfully updated");
- }
-
- _registryCacheReport.Complete();
-
- await Task.Delay((int)_registryOptions.UpdateInterval.TotalMilliseconds, stoppingToken);
- }
- }
- catch (Exception ex)
- {
- string message = "Error while building a new registry cache.";
-
- _logger.LogError(ex, "{Message}", message);
-
- _registryCacheReport.AddError($"{message}. Reason: {ex}");
- _registryCacheReport.Complete();
- }
- }
- }
-}
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace UnityNuGet.Server
+{
+ ///
+ /// Update the RegistryCache at a regular interval
+ ///
+ internal sealed class RegistryCacheUpdater(RegistryCacheReport registryCacheReport, RegistryCacheSingleton currentRegistryCache, ILogger logger, IOptions registryOptionsAccessor) : BackgroundService
+ {
+ private readonly RegistryCacheReport _registryCacheReport = registryCacheReport;
+ private readonly RegistryCacheSingleton _currentRegistryCache = currentRegistryCache;
+ private readonly ILogger _logger = logger;
+ private readonly RegistryOptions _registryOptions = registryOptionsAccessor.Value;
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ try
+ {
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ _logger.LogInformation("Starting to update RegistryCache");
+
+ _registryCacheReport.Start();
+
+ var newRegistryCache = new RegistryCache(_currentRegistryCache.UnityPackageFolder!, _currentRegistryCache.ServerUri!, _registryOptions.UnityScope!, _registryOptions.MinimumUnityVersion!, _registryOptions.PackageNameNuGetPostFix!, _registryOptions.TargetFrameworks!, _currentRegistryCache.NuGetRedirectLogger!)
+ {
+ // Update progress
+ OnProgress = (current, total) =>
+ {
+ _currentRegistryCache.ProgressTotalPackageCount = total;
+ _currentRegistryCache.ProgressPackageIndex = current;
+ },
+ OnInformation = message => _registryCacheReport.AddInformation(message),
+ OnWarning = message => _registryCacheReport.AddWarning(message),
+ OnError = message => _registryCacheReport.AddError(message)
+ };
+
+ await newRegistryCache.Build();
+
+ if (_registryCacheReport.ErrorMessages.Any())
+ {
+ _logger.LogInformation("RegistryCache not updated due to errors. See previous logs");
+ }
+ else
+ {
+ // Update the registry cache in the services
+ _currentRegistryCache.Instance = newRegistryCache;
+
+ _logger.LogInformation("RegistryCache successfully updated");
+ }
+
+ _registryCacheReport.Complete();
+
+ await Task.Delay((int)_registryOptions.UpdateInterval.TotalMilliseconds, stoppingToken);
+ }
+ }
+ catch (Exception ex)
+ {
+ string message = "Error while building a new registry cache.";
+
+ _logger.LogError(ex, "{Message}", message);
+
+ _registryCacheReport.AddError($"{message}. Reason: {ex}");
+ _registryCacheReport.Complete();
+ }
+ }
+ }
+}
diff --git a/src/UnityNuGet.Server/UnityNuGet.Server.csproj b/src/UnityNuGet.Server/UnityNuGet.Server.csproj
index 52e06b76..56d92248 100644
--- a/src/UnityNuGet.Server/UnityNuGet.Server.csproj
+++ b/src/UnityNuGet.Server/UnityNuGet.Server.csproj
@@ -1,12 +1,10 @@
-
+
- net7.0
- enable
+ net8.0
/subscriptions/b6745039-70e7-4641-994b-5457cb220e2a/resourcegroups/Default-ApplicationInsights-EastUS/providers/microsoft.insights/components/unitynuget-registry
/subscriptions/b6745039-70e7-4641-994b-5457cb220e2a/resourcegroups/Default-ApplicationInsights-EastUS/providers/microsoft.insights/components/unitynuget-registry
1be0a769-8d75-4a27-99e0-128afcc0ffee
- true
@@ -16,11 +14,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/src/UnityNuGet.Tests/NativeTests.cs b/src/UnityNuGet.Tests/NativeTests.cs
index 1dd28f4e..60419540 100644
--- a/src/UnityNuGet.Tests/NativeTests.cs
+++ b/src/UnityNuGet.Tests/NativeTests.cs
@@ -1,53 +1,53 @@
-using System;
-using System.IO;
-using System.Threading.Tasks;
-using NUnit.Framework;
-
-namespace UnityNuGet.Tests
-{
- [Ignore("Ignore native libs tests")]
- public class NativeTests
- {
- [Test]
- public async Task TestBuild()
- {
- var unityPackages = Path.Combine(Path.GetDirectoryName(typeof(RegistryCacheTests).Assembly.Location), "unity_packages");
- Directory.Delete(unityPackages, true);
-
- var errorsTriggered = false;
-
- var registryCache = new RegistryCache(
- unityPackages,
- new Uri("http://localhost/"),
- "org.nuget",
- "2019.1",
- " (NuGet)",
- new RegistryTargetFramework[] {
- new RegistryTargetFramework { Name = "netstandard2.1", DefineConstraints = new string[] { "UNITY_2021_2_OR_NEWER"} },
- new RegistryTargetFramework { Name = "netstandard2.0", DefineConstraints = new string[] { "!UNITY_2021_2_OR_NEWER" } },
- },
- new NuGetConsoleLogger())
- {
- Filter = "rhino3dm",
- OnError = message =>
- {
- errorsTriggered = true;
- }
- };
-
- await registryCache.Build();
-
- Assert.False(errorsTriggered, "The registry failed to build, check the logs");
- var allResult = registryCache.All();
- var allResultJson = allResult.ToJson();
-
- StringAssert.Contains("org.nuget.rhino3dm", allResultJson);
-
- var rhinoPackage = registryCache.GetPackage("org.nuget.rhino3dm");
- Assert.NotNull(rhinoPackage);
- var rhinopackageJson = rhinoPackage.ToJson();
- StringAssert.Contains("org.nuget.rhino3dm", rhinopackageJson);
- StringAssert.Contains("7.11.0", rhinopackageJson);
- }
- }
-}
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace UnityNuGet.Tests
+{
+ [Ignore("Ignore native libs tests")]
+ public class NativeTests
+ {
+ [Test]
+ public async Task TestBuild()
+ {
+ var unityPackages = Path.Combine(Path.GetDirectoryName(typeof(RegistryCacheTests).Assembly.Location)!, "unity_packages");
+ Directory.Delete(unityPackages, true);
+
+ var errorsTriggered = false;
+
+ var registryCache = new RegistryCache(
+ unityPackages,
+ new Uri("http://localhost/"),
+ "org.nuget",
+ "2019.1",
+ " (NuGet)",
+ [
+ new() { Name = "netstandard2.1", DefineConstraints = ["UNITY_2021_2_OR_NEWER"] },
+ new() { Name = "netstandard2.0", DefineConstraints = ["!UNITY_2021_2_OR_NEWER"] },
+ ],
+ new NuGetConsoleLogger())
+ {
+ Filter = "rhino3dm",
+ OnError = message =>
+ {
+ errorsTriggered = true;
+ }
+ };
+
+ await registryCache.Build();
+
+ Assert.That(errorsTriggered, Is.False, "The registry failed to build, check the logs");
+ var allResult = registryCache.All();
+ var allResultJson = allResult.ToJson();
+
+ Assert.That(allResultJson, Does.Contain("org.nuget.rhino3dm"));
+
+ var rhinoPackage = registryCache.GetPackage("org.nuget.rhino3dm");
+ Assert.That(rhinoPackage, Is.Not.Null);
+ var rhinopackageJson = rhinoPackage!.ToJson();
+ Assert.That(rhinopackageJson, Does.Contain("org.nuget.rhino3dm"));
+ Assert.That(rhinopackageJson, Does.Contain("7.11.0"));
+ }
+ }
+}
diff --git a/src/UnityNuGet.Tests/NuGetHelperTests.cs b/src/UnityNuGet.Tests/NuGetHelperTests.cs
index 44329295..17c63a47 100644
--- a/src/UnityNuGet.Tests/NuGetHelperTests.cs
+++ b/src/UnityNuGet.Tests/NuGetHelperTests.cs
@@ -18,7 +18,7 @@ public class NuGetHelperTests
[TestCase("analyzers/Test.resources.dll")]
public void IsApplicableAnalyzerResource_Valid(string input)
{
- Assert.True(NuGetHelper.IsApplicableAnalyzerResource(input));
+ Assert.That(NuGetHelper.IsApplicableAnalyzerResource(input), Is.True);
}
[Test]
@@ -31,7 +31,7 @@ public void IsApplicableAnalyzerResource_Valid(string input)
[TestCase("analyzers/Test.dll")]
public void IsApplicableAnalyzerResource_Invalid(string input)
{
- Assert.False(NuGetHelper.IsApplicableAnalyzerResource(input));
+ Assert.That(NuGetHelper.IsApplicableAnalyzerResource(input), Is.False);
}
// Examples:
@@ -48,7 +48,7 @@ public void IsApplicableAnalyzerResource_Invalid(string input)
[TestCase("analyzers/Test.dll")]
public void IsApplicableUnitySupportedRoslynVersionFolder_Valid(string input)
{
- Assert.True(NuGetHelper.IsApplicableUnitySupportedRoslynVersionFolder(input));
+ Assert.That(NuGetHelper.IsApplicableUnitySupportedRoslynVersionFolder(input), Is.True);
}
[Test]
@@ -56,7 +56,7 @@ public void IsApplicableUnitySupportedRoslynVersionFolder_Valid(string input)
[TestCase("analyzers/dotnet/roslyn4.0/Test.dll")]
public void IsApplicableUnitySupportedRoslynVersionFolder_Invalid(string input)
{
- Assert.False(NuGetHelper.IsApplicableUnitySupportedRoslynVersionFolder(input));
+ Assert.That(NuGetHelper.IsApplicableUnitySupportedRoslynVersionFolder(input), Is.False);
}
[Test]
@@ -64,17 +64,17 @@ public void GetCompatiblePackageDependencyGroups_SpecificSingleFramework()
{
IList packageDependencyGroups = new PackageDependencyGroup[]
{
- new PackageDependencyGroup(CommonFrameworks.NetStandard13, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard16, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard20, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard21, Array.Empty())
+ new(CommonFrameworks.NetStandard13, Array.Empty()),
+ new(CommonFrameworks.NetStandard16, Array.Empty()),
+ new(CommonFrameworks.NetStandard20, Array.Empty()),
+ new(CommonFrameworks.NetStandard21, Array.Empty())
};
- IEnumerable targetFrameworks = new RegistryTargetFramework[] { new RegistryTargetFramework { Framework = CommonFrameworks.NetStandard20 } };
+ IEnumerable targetFrameworks = new RegistryTargetFramework[] { new() { Framework = CommonFrameworks.NetStandard20 } };
IEnumerable compatibleDependencyGroups = NuGetHelper.GetCompatiblePackageDependencyGroups(packageDependencyGroups, targetFrameworks);
- CollectionAssert.AreEqual(new PackageDependencyGroup[] { packageDependencyGroups[2] }, compatibleDependencyGroups);
+ Assert.That(compatibleDependencyGroups, Is.EqualTo(new PackageDependencyGroup[] { packageDependencyGroups[2] }).AsCollection);
}
[Test]
@@ -82,17 +82,17 @@ public void GetCompatiblePackageDependencyGroups_SpecificMultipleFrameworks()
{
IList packageDependencyGroups = new PackageDependencyGroup[]
{
- new PackageDependencyGroup(CommonFrameworks.NetStandard13, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard16, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard20, Array.Empty()),
- new PackageDependencyGroup(CommonFrameworks.NetStandard21, Array.Empty())
+ new(CommonFrameworks.NetStandard13, Array.Empty()),
+ new(CommonFrameworks.NetStandard16, Array.Empty()),
+ new(CommonFrameworks.NetStandard20, Array.Empty()),
+ new(CommonFrameworks.NetStandard21, Array.Empty())
};
- IEnumerable targetFrameworks = new RegistryTargetFramework[] { new RegistryTargetFramework { Framework = CommonFrameworks.NetStandard20 }, new RegistryTargetFramework { Framework = CommonFrameworks.NetStandard21 } };
+ IEnumerable targetFrameworks = new RegistryTargetFramework[] { new() { Framework = CommonFrameworks.NetStandard20 }, new() { Framework = CommonFrameworks.NetStandard21 } };
IEnumerable compatibleDependencyGroups = NuGetHelper.GetCompatiblePackageDependencyGroups(packageDependencyGroups, targetFrameworks);
- CollectionAssert.AreEqual(new PackageDependencyGroup[] { packageDependencyGroups[2], packageDependencyGroups[3] }, compatibleDependencyGroups);
+ Assert.That(compatibleDependencyGroups, Is.EqualTo(new PackageDependencyGroup[] { packageDependencyGroups[2], packageDependencyGroups[3] }).AsCollection);
}
[Test]
@@ -100,14 +100,14 @@ public void GetCompatiblePackageDependencyGroups_AnyFramework()
{
IList packageDependencyGroups = new PackageDependencyGroup[]
{
- new PackageDependencyGroup(new NuGetFramework(SpecialIdentifiers.Any), Array.Empty())
+ new(new NuGetFramework(SpecialIdentifiers.Any), Array.Empty())
};
- IEnumerable targetFrameworks = new RegistryTargetFramework[] { new RegistryTargetFramework { Framework = CommonFrameworks.NetStandard20 } };
+ IEnumerable targetFrameworks = new RegistryTargetFramework[] { new() { Framework = CommonFrameworks.NetStandard20 } };
IEnumerable compatibleDependencyGroups = NuGetHelper.GetCompatiblePackageDependencyGroups(packageDependencyGroups, targetFrameworks);
- CollectionAssert.AreEqual(packageDependencyGroups, compatibleDependencyGroups);
+ Assert.That(compatibleDependencyGroups, Is.EqualTo(packageDependencyGroups).AsCollection);
}
}
}
diff --git a/src/UnityNuGet.Tests/PlatformDefinitionTests.cs b/src/UnityNuGet.Tests/PlatformDefinitionTests.cs
index 6c4377b0..7ac0b412 100644
--- a/src/UnityNuGet.Tests/PlatformDefinitionTests.cs
+++ b/src/UnityNuGet.Tests/PlatformDefinitionTests.cs
@@ -1,132 +1,144 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using NUnit.Framework;
-
-namespace UnityNuGet.Tests
-{
- public class PlatformDefinitionTests
- {
- [Test]
- public void CanFindDefinitions()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
-
- // Look-up by OS should return the most general configuration
- var win = platformDefs.Find(UnityOs.Windows);
- Assert.IsNotNull(win);
- Assert.AreEqual(win.Cpu, UnityCpu.AnyCpu);
-
- // Look-up explicit configuration
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using NUnit.Framework;
+
+namespace UnityNuGet.Tests
+{
+ public class PlatformDefinitionTests
+ {
+ [Test]
+ public void CanFindDefinitions()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+
+ // Look-up by OS should return the most general configuration
+ var win = platformDefs.Find(UnityOs.Windows);
+ Assert.That(win, Is.Not.Null);
+ Assert.That(win!.Cpu, Is.EqualTo(UnityCpu.AnyCpu));
+
+ // Look-up explicit configuration
var win64 = platformDefs.Find(UnityOs.Windows, UnityCpu.X64);
- Assert.IsNotNull(win64);
- Assert.AreEqual(win64.Os, win.Os);
- Assert.AreEqual(win64.Cpu, UnityCpu.X64);
- Assert.True(win.Children.Contains(win64));
-
- // Look-up invalid configuration
- var and = platformDefs.Find(UnityOs.Android, UnityCpu.None);
- Assert.IsNull(and);
- }
-
- [Test]
- public void RemainingPlatforms_NoneVisited()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var visited = new HashSet();
-
- // If no platform was visited, the remaining platforms should be the (AnyOS, AnyCPU) config.
- var remaining = platformDefs.GetRemainingPlatforms(visited);
- Assert.IsNotNull(remaining);
- Assert.AreEqual(1, remaining.Count);
- Assert.AreEqual(remaining.First(), platformDefs);
- }
-
- [Test]
- public void RemainingPlatforms_OneVisited()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
-
- foreach (var child in platformDefs.Children)
+ Assert.Multiple(() =>
{
- var visited = new HashSet() { child };
- var remaining = platformDefs.GetRemainingPlatforms(visited);
-
- // We should get all other children, except the one already visited
- Assert.AreEqual(platformDefs.Children.Count, remaining.Count + 1);
- foreach (var r in remaining)
+ Assert.That(win64, Is.Not.Null);
+ Assert.That(win.Os, Is.EqualTo(win64!.Os));
+ });
+ Assert.Multiple(() =>
+ {
+ Assert.That(win64.Cpu, Is.EqualTo(UnityCpu.X64));
+ Assert.That(win.Children, Does.Contain(win64));
+ });
+
+ // Look-up invalid configuration
+ var and = platformDefs.Find(UnityOs.Android, UnityCpu.None);
+ Assert.That(and, Is.Null);
+ }
+
+ [Test]
+ public void RemainingPlatforms_NoneVisited()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var visited = new HashSet();
+
+ // If no platform was visited, the remaining platforms should be the (AnyOS, AnyCPU) config.
+ var remaining = platformDefs.GetRemainingPlatforms(visited);
+ Assert.That(remaining, Is.Not.Null);
+ Assert.Multiple(() =>
+ {
+ Assert.That(remaining, Has.Count.EqualTo(1));
+ Assert.That(platformDefs, Is.EqualTo(remaining.First()));
+ });
+ }
+
+ [Test]
+ public void RemainingPlatforms_OneVisited()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+
+ foreach (var child in platformDefs.Children)
+ {
+ var visited = new HashSet() { child };
+ var remaining = platformDefs.GetRemainingPlatforms(visited);
+
+ // We should get all other children, except the one already visited
+ Assert.That(remaining.Count + 1, Is.EqualTo(platformDefs.Children.Count));
+ foreach (var r in remaining)
{
- Assert.AreNotEqual(r, child);
- Assert.IsTrue(platformDefs.Children.Contains(r));
- }
- }
- }
-
- [Test]
- public void RemainingPlatforms_LeafVisited()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var win64 = platformDefs.Find(UnityOs.Windows, UnityCpu.X64);
- var visited = new HashSet() { win64 };
-
- // The remaining platforms should be all non-windows, as well as all !x64 windows
- var expected = platformDefs.Children
- .Except(new[] { win64.Parent })
- .Concat(
- win64.Parent.Children
- .Except(new[] { win64 }))
- .ToHashSet();
- var actual = platformDefs.GetRemainingPlatforms(visited);
- Assert.IsTrue(expected.SetEquals(actual));
- }
-
- [TestCase("")]
- [TestCase("base")]
- public void TestConfigPath_Root(string basePath)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var file = new PlatformFile("a/b/c.dll", platformDefs);
-
- // We don't use extra paths for the (AnyOS, AnyCPU) configuration
- var actual = file.GetDestinationPath(basePath);
- var expected = Path.Combine(
- basePath,
- Path.GetFileName(file.SourcePath));
- Assert.AreEqual(actual, expected);
- }
-
- [TestCase("")]
- [TestCase("base")]
- public void TestConfigPath_OsOnly(string basePath)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var win = platformDefs.Find(UnityOs.Windows);
- var file = new PlatformFile("a/b/c.dll", win);
-
- var actual = file.GetDestinationPath(basePath);
- var expected = Path.Combine(
- basePath,
- "Windows",
- Path.GetFileName(file.SourcePath));
- Assert.AreEqual(actual, expected);
- }
-
- [TestCase("")]
- [TestCase("base")]
- public void TestConfigPath_Full(string basePath)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var win64 = platformDefs.Find(UnityOs.Windows, UnityCpu.X64);
- var file = new PlatformFile("a/b/c.dll", win64);
-
- var actual = file.GetDestinationPath(basePath);
- var expected = Path.Combine(
- basePath,
- "Windows",
- "x86_64",
- Path.GetFileName(file.SourcePath));
- Assert.AreEqual(actual, expected);
- }
- }
-}
+ Assert.Multiple(() =>
+ {
+ Assert.That(child, Is.Not.EqualTo(r));
+ Assert.That(platformDefs.Children, Does.Contain(r));
+ });
+ }
+ }
+ }
+
+ [Test]
+ public void RemainingPlatforms_LeafVisited()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var win64 = platformDefs.Find(UnityOs.Windows, UnityCpu.X64);
+ var visited = new HashSet() { win64! };
+
+ // The remaining platforms should be all non-windows, as well as all !x64 windows
+ var expected = platformDefs.Children
+ .Except(new[] { win64!.Parent })
+ .Concat(
+ win64.Parent!.Children
+ .Except(new[] { win64 }))
+ .ToHashSet();
+ var actual = platformDefs.GetRemainingPlatforms(visited);
+ Assert.That(expected.SetEquals(actual), Is.True);
+ }
+
+ [TestCase("")]
+ [TestCase("base")]
+ public void TestConfigPath_Root(string basePath)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var file = new PlatformFile("a/b/c.dll", platformDefs);
+
+ // We don't use extra paths for the (AnyOS, AnyCPU) configuration
+ var actual = file.GetDestinationPath(basePath);
+ var expected = Path.Combine(
+ basePath,
+ Path.GetFileName(file.SourcePath));
+ Assert.That(expected, Is.EqualTo(actual));
+ }
+
+ [TestCase("")]
+ [TestCase("base")]
+ public void TestConfigPath_OsOnly(string basePath)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var win = platformDefs.Find(UnityOs.Windows);
+ var file = new PlatformFile("a/b/c.dll", win!);
+
+ var actual = file.GetDestinationPath(basePath);
+ var expected = Path.Combine(
+ basePath,
+ "Windows",
+ Path.GetFileName(file.SourcePath));
+ Assert.That(expected, Is.EqualTo(actual));
+ }
+
+ [TestCase("")]
+ [TestCase("base")]
+ public void TestConfigPath_Full(string basePath)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var win64 = platformDefs.Find(UnityOs.Windows, UnityCpu.X64);
+ var file = new PlatformFile("a/b/c.dll", win64!);
+
+ var actual = file.GetDestinationPath(basePath);
+ var expected = Path.Combine(
+ basePath,
+ "Windows",
+ "x86_64",
+ Path.GetFileName(file.SourcePath));
+ Assert.That(expected, Is.EqualTo(actual));
+ }
+ }
+}
diff --git a/src/UnityNuGet.Tests/RegistryCacheTests.cs b/src/UnityNuGet.Tests/RegistryCacheTests.cs
index 6e7372ba..e13c464f 100644
--- a/src/UnityNuGet.Tests/RegistryCacheTests.cs
+++ b/src/UnityNuGet.Tests/RegistryCacheTests.cs
@@ -12,17 +12,17 @@ public async Task TestBuild()
{
var errorsTriggered = false;
- var unityPackages = Path.Combine(Path.GetDirectoryName(typeof(RegistryCacheTests).Assembly.Location), "unity_packages");
+ var unityPackages = Path.Combine(Path.GetDirectoryName(typeof(RegistryCacheTests).Assembly.Location)!, "unity_packages");
var registryCache = new RegistryCache(
unityPackages,
new Uri("http://localhost/"),
"org.nuget",
"2019.1",
" (NuGet)",
- new RegistryTargetFramework[] {
- new RegistryTargetFramework { Name = "netstandard2.1", DefineConstraints = new string[] { "UNITY_2021_2_OR_NEWER"} },
- new RegistryTargetFramework { Name = "netstandard2.0", DefineConstraints = new string[] { "!UNITY_2021_2_OR_NEWER" } },
- },
+ [
+ new() { Name = "netstandard2.1", DefineConstraints = ["UNITY_2021_2_OR_NEWER"] },
+ new() { Name = "netstandard2.0", DefineConstraints = ["!UNITY_2021_2_OR_NEWER"] },
+ ],
new NuGetConsoleLogger())
{
OnError = message =>
@@ -36,20 +36,20 @@ public async Task TestBuild()
await registryCache.Build();
- Assert.False(errorsTriggered, "The registry failed to build, check the logs");
+ Assert.That(errorsTriggered, Is.False, "The registry failed to build, check the logs");
var allResult = registryCache.All();
- Assert.True(allResult.Packages.Count >= 3);
+ Assert.That(allResult.Packages, Has.Count.GreaterThanOrEqualTo(3));
var allResultJson = allResult.ToJson();
- StringAssert.Contains("org.nuget.scriban", allResultJson);
- StringAssert.Contains("org.nuget.system.runtime.compilerservices.unsafe", allResultJson);
+ Assert.That(allResultJson, Does.Contain("org.nuget.scriban"));
+ Assert.That(allResultJson, Does.Contain("org.nuget.system.runtime.compilerservices.unsafe"));
var scribanPackage = registryCache.GetPackage("org.nuget.scriban");
- Assert.NotNull(scribanPackage);
- var scribanPackageJson = scribanPackage.ToJson();
- StringAssert.Contains("org.nuget.scriban", scribanPackageJson);
- StringAssert.Contains("2.1.0", scribanPackageJson);
+ Assert.That(scribanPackage, Is.Not.Null);
+ var scribanPackageJson = scribanPackage!.ToJson();
+ Assert.That(scribanPackageJson, Does.Contain("org.nuget.scriban"));
+ Assert.That(scribanPackageJson, Does.Contain("2.1.0"));
}
}
}
diff --git a/src/UnityNuGet.Tests/RegistryTests.cs b/src/UnityNuGet.Tests/RegistryTests.cs
index 21dee362..5d7681e2 100644
--- a/src/UnityNuGet.Tests/RegistryTests.cs
+++ b/src/UnityNuGet.Tests/RegistryTests.cs
@@ -1,4 +1,7 @@
-using System.Linq;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -10,7 +13,6 @@
using NuGet.Protocol.Core.Types;
using NUnit.Framework;
using static NuGet.Frameworks.FrameworkConstants;
-using System.IO;
namespace UnityNuGet.Tests
{
@@ -23,7 +25,7 @@ public void Make_Sure_That_The_Order_In_The_Registry_Is_Respected()
var originalPackageNames = registry.Select(r => r.Key).ToArray();
var sortedPackageNames = originalPackageNames.OrderBy(p => p).ToArray();
- Assert.AreEqual(sortedPackageNames, originalPackageNames);
+ Assert.That(originalPackageNames, Is.EqualTo(sortedPackageNames));
}
[Test]
@@ -32,7 +34,7 @@ public void Ensure_That_Packages_Already_Included_In_Net_Standard_Are_not_Includ
var registry = Registry.GetInstance();
var packageNames = registry.Select(r => r.Key).Where(DotNetHelper.IsNetStandard20Assembly).ToArray();
- Assert.IsEmpty(packageNames);
+ Assert.That(packageNames, Is.Empty);
}
[Test]
@@ -57,14 +59,14 @@ public async Task CanParse_PackageWithRuntimes()
var runtimeLibs = await RuntimeLibraries
.GetSupportedRuntimeLibsAsync(downloadResult.PackageReader, CommonFrameworks.NetStandard20, logger)
.ToListAsync();
- Assert.IsTrue(runtimeLibs.Any());
+ Assert.That(runtimeLibs, Is.Not.Empty);
// Make sure these runtime libraries are only for Windows
var platformDefs = PlatformDefinition.CreateAllPlatforms();
var win = platformDefs.Find(UnityOs.Windows);
foreach (var (file, os, cpu) in runtimeLibs)
{
- Assert.AreEqual(platformDefs.Find(os, cpu), win);
+ Assert.That(platformDefs.Find(os, cpu), Is.EqualTo(win));
}
// Get the lib files
@@ -73,7 +75,7 @@ public async Task CanParse_PackageWithRuntimes()
versions,
new RegistryTargetFramework[]
{
- new RegistryTargetFramework
+ new()
{
Framework = CommonFrameworks.NetStandard20,
},
@@ -88,7 +90,7 @@ public async Task CanParse_PackageWithRuntimes()
var runtimeFiles = runtimeLibs
.Select(l => Path.GetFileName(l.file))
.ToHashSet();
- Assert.IsTrue(libFiles.SetEquals(runtimeFiles));
+ Assert.That(libFiles.SetEquals(runtimeFiles), Is.True);
}
[Test]
@@ -103,7 +105,7 @@ public async Task Ensure_Min_Version_Is_Correct_Ignoring_Analyzers_And_Native_Li
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
var resource = await repository.GetResourceAsync();
- var nuGetFrameworks = new RegistryTargetFramework[] { new RegistryTargetFramework { Framework = CommonFrameworks.NetStandard20 } };
+ var nuGetFrameworks = new RegistryTargetFramework[] { new() { Framework = CommonFrameworks.NetStandard20 } };
var excludedPackages = new string[] {
// All versions target "Any" and not .netstandard2.0 / 2.1
@@ -151,7 +153,7 @@ public async Task Ensure_Min_Version_Is_Correct_Ignoring_Analyzers_And_Native_Li
if (packageIdentity != null)
{
- Assert.AreEqual(packageIdentity.Version, versionRange.MinVersion, $"Package {packageId}");
+ Assert.That(versionRange!.MinVersion, Is.EqualTo(packageIdentity.Version), $"Package {packageId}");
}
else
{
@@ -159,7 +161,7 @@ public async Task Ensure_Min_Version_Is_Correct_Ignoring_Analyzers_And_Native_Li
var downloadResult = await PackageDownloader.GetDownloadResourceResultAsync(
new SourceRepository[] { repository },
- new PackageIdentity(registryKvp.Key, registryKvp.Value.Version.MinVersion),
+ new PackageIdentity(registryKvp.Key, registryKvp.Value.Version!.MinVersion),
new PackageDownloadContext(cache),
SettingsUtility.GetGlobalPackagesFolder(settings),
logger, cancellationToken);
@@ -177,5 +179,62 @@ public async Task Ensure_Min_Version_Is_Correct_Ignoring_Analyzers_And_Native_Li
}
}
}
+
+ [Test]
+ public async Task Ensure_Do_Not_Exceed_The_Maximum_Number_Of_Allowed_Versions()
+ {
+ const int maxAllowedVersions = 100;
+
+ var registry = Registry.GetInstance();
+
+ var logger = NullLogger.Instance;
+ var cancellationToken = CancellationToken.None;
+
+ var cache = new SourceCacheContext();
+ var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
+ var resource = await repository.GetResourceAsync();
+
+ List<(string packageId, int versionCount)> packages = [];
+
+ foreach (var registryKvp in registry.Where(r => !r.Value.Analyzer && !r.Value.Ignored))
+ {
+ var packageId = registryKvp.Key;
+
+ var versionRange = registryKvp.Value.Version;
+
+ var dependencyPackageMetas = await resource.GetMetadataAsync(
+ packageId,
+ includePrerelease: false,
+ includeUnlisted: false,
+ cache,
+ logger,
+ cancellationToken);
+
+ var versions = dependencyPackageMetas.Where(v => versionRange!.Satisfies(v.Identity.Version)).ToArray();
+
+ if (versions.Length > maxAllowedVersions)
+ {
+ packages.Add((registryKvp.Key, versions.Length));
+ }
+ }
+
+ StringBuilder stringBuilder = new();
+
+ foreach (var (packageId, versionCount) in packages.OrderByDescending(p => p.versionCount))
+ {
+ stringBuilder.AppendLine($"{packageId} -> {versionCount}");
+ }
+
+ if (stringBuilder.Length == 0)
+ {
+ const bool trueConstant = true;
+
+ Assert.That(trueConstant, Is.True);
+ }
+ else
+ {
+ Assert.Inconclusive(stringBuilder.ToString());
+ }
+ }
}
}
diff --git a/src/UnityNuGet.Tests/UnityMetaTests.cs b/src/UnityNuGet.Tests/UnityMetaTests.cs
index 6a1299c1..4ecc8350 100644
--- a/src/UnityNuGet.Tests/UnityMetaTests.cs
+++ b/src/UnityNuGet.Tests/UnityMetaTests.cs
@@ -1,162 +1,173 @@
-using System;
-using System.Linq;
-using System.Text.RegularExpressions;
-using NUnit.Framework;
-
-namespace UnityNuGet.Tests
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+using NUnit.Framework;
+
+namespace UnityNuGet.Tests
{
- public class UnityMetaTests
- {
- [Test]
- public void GetMetaForDll_FormatsDefineConstraintsProperly_WithoutConstraints()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs, Array.Empty(), Array.Empty());
- StringAssert.DoesNotContain("defineConstraints", output);
-
- // This is on the same line in the template, so ensure it's intact
- StringAssert.Contains("\n isPreloaded: 0\n", output);
- }
-
- [Test]
- public void GetMetaForDll_FormatsLabelsProperly_WithoutLabels()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs, Array.Empty(), Array.Empty());
- StringAssert.DoesNotContain("labels", output);
-
- // This is on the same line in the template, so ensure it's intact
- StringAssert.Contains("\nPluginImporter:\n", output);
+#pragma warning disable CA1861 // Avoid constant arrays as arguments
+ public class UnityMetaTests
+ {
+ [Test]
+ public void GetMetaForDll_FormatsDefineConstraintsProperly_WithoutConstraints()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs!, Array.Empty(), Array.Empty());
+ Assert.That(output, Does.Not.Contain("defineConstraints"));
+
+ // This is on the same line in the template, so ensure it's intact
+ Assert.That(output, Does.Contain("\n isPreloaded: 0\n"));
+ }
+
+ [Test]
+ public void GetMetaForDll_FormatsLabelsProperly_WithoutLabels()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs!, Array.Empty(), Array.Empty());
+ Assert.That(output, Does.Not.Contain("labels"));
+
+ // This is on the same line in the template, so ensure it's intact
+ Assert.That(output, Does.Contain("\nPluginImporter:\n"));
}
[TestCase(new[] { "FIRST" }, "\n defineConstraints:\n - FIRST\n")]
- [TestCase(new[] { "FIRST", "SECOND" }, "\n defineConstraints:\n - FIRST\n - SECOND\n")]
- public void GetMetaForDll_FormatsDefineConstraintsProperly_WithConstraints(
- string[] constraints, string expected)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs, Array.Empty(), constraints);
-
- StringAssert.Contains(expected, output);
-
- // This is on the same line in the template, so ensure it's intact
- StringAssert.Contains("\n isPreloaded: 0\n", output);
- }
-
- [TestCase(new[] { "FIRST" }, "\nlabels:\n - FIRST\n")]
- [TestCase(new[] { "FIRST", "SECOND" }, "\nlabels:\n - FIRST\n - SECOND\n")]
- public void GetMetaForDll_FormatsLabelsProperly_WithLabels(
- string[] labels, string expected)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs, labels, Array.Empty());
-
- StringAssert.Contains(expected, output);
-
- // This is on the same line in the template, so ensure it's intact
- StringAssert.Contains("\nPluginImporter:\n", output);
- }
-
- [TestCase(true, "1")]
- [TestCase(false, "0")]
- public void GetMetaForDll_FormatsAnyPlatformEnabledProperly(bool value, string expected)
- {
- PlatformDefinition platformDef;
-
- if (value)
+ [TestCase(new[] { "FIRST", "SECOND" }, "\n defineConstraints:\n - FIRST\n - SECOND\n")]
+ public void GetMetaForDll_FormatsDefineConstraintsProperly_WithConstraints(
+ string[] constraints, string expected)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs!, Array.Empty(), constraints);
+
+ Assert.That(output, Does.Contain(expected));
+
+ // This is on the same line in the template, so ensure it's intact
+ Assert.That(output, Does.Contain("\n isPreloaded: 0\n"));
+ }
+
+ [TestCase(new[] { "FIRST" }, "\nlabels:\n - FIRST\n")]
+ [TestCase(new[] { "FIRST", "SECOND" }, "\nlabels:\n - FIRST\n - SECOND\n")]
+ public void GetMetaForDll_FormatsLabelsProperly_WithLabels(
+ string[] labels, string expected)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs!, labels, Array.Empty());
+
+ Assert.That(output, Does.Contain(expected));
+
+ // This is on the same line in the template, so ensure it's intact
+ Assert.That(output, Does.Contain("\nPluginImporter:\n"));
+ }
+
+ [TestCase(true, "1")]
+ [TestCase(false, "0")]
+ public void GetMetaForDll_FormatsAnyPlatformEnabledProperly(bool value, string expected)
+ {
+ PlatformDefinition? platformDef;
+
+ if (value)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ platformDef = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ }
+ else
+ {
+ platformDef = new PlatformDefinition(UnityOs.AnyOs, UnityCpu.None, isEditorConfig: false);
+ }
+
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), platformDef!, Array.Empty(), Array.Empty());
+
+ Assert.That(output, Does.Contain($"\n platformData:\n - first:\n Any:\n second:\n enabled: {expected}\n"));
+ }
+
+ [Test]
+ public void GetMetaForDll_ContainsNoWindowsNewlines()
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
+ var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs!, Array.Empty(), new[] { "TEST" });
+ Assert.That(output, Does.Not.Contain("\r"));
+ }
+
+ [TestCase(UnityOs.Android, "Android", "Android")]
+ [TestCase(UnityOs.WebGL, "WebGL", "WebGL")]
+ [TestCase(UnityOs.iOS, "iPhone", "iOS")]
+ public void GetMetaForDll_NonEditor(UnityOs os, string platformName, string osName)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var output = UnityMeta.GetMetaForDll(
+ Guid.NewGuid(),
+ platformDefs.Find(os)!,
+ Array.Empty(),
+ Array.Empty());
+
+ // There should be a single 'Exclude Android: 0' match
+ var excludeRegex = new Regex("Exclude (.*): 0");
+ var excludeMatches = excludeRegex.Matches(output);
+ Assert.That(excludeMatches, Is.Not.Null);
+ Assert.That(excludeMatches, Has.Count.EqualTo(1));
+ Assert.Multiple(() =>
{
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- platformDef = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- }
- else
+ Assert.That(excludeMatches.Single().Groups, Has.Count.EqualTo(2));
+ Assert.That(osName, Is.EqualTo(excludeMatches.Single().Groups[1].Value));
+ });
+
+ // There should be a single 'enabled: 1' match
+ var enableRegex = new Regex("enabled: 1");
+ var enableMatches = enableRegex.Matches(output);
+ Assert.That(enableMatches, Is.Not.Null);
+ Assert.Multiple(() =>
{
- platformDef = new PlatformDefinition(UnityOs.AnyOs, UnityCpu.None, isEditorConfig: false);
- }
-
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), platformDef, Array.Empty(), Array.Empty());
-
- StringAssert.Contains($"\n platformData:\n - first:\n Any:\n second:\n enabled: {expected}\n", output);
- }
-
- [Test]
- public void GetMetaForDll_ContainsNoWindowsNewlines()
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var anyOs = platformDefs.Find(UnityOs.AnyOs, UnityCpu.AnyCpu);
- var output = UnityMeta.GetMetaForDll(Guid.NewGuid(), anyOs, Array.Empty(), new[] { "TEST" });
- StringAssert.DoesNotContain("\r", output);
- }
-
- [TestCase(UnityOs.Android, "Android", "Android")]
- [TestCase(UnityOs.WebGL, "WebGL", "WebGL")]
- [TestCase(UnityOs.iOS, "iPhone", "iOS")]
- public void GetMetaForDll_NonEditor(UnityOs os, string platformName, string osName)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var output = UnityMeta.GetMetaForDll(
- Guid.NewGuid(),
- platformDefs.Find(os),
- Array.Empty(),
- Array.Empty());
-
- // There should be a single 'Exclude Android: 0' match
- var excludeRegex = new Regex("Exclude (.*): 0");
- var excludeMatches = excludeRegex.Matches(output);
- Assert.IsNotNull(excludeMatches);
- Assert.AreEqual(excludeMatches.Count, 1);
- Assert.AreEqual(excludeMatches.Single().Groups.Count, 2);
- Assert.AreEqual(excludeMatches.Single().Groups[1].Value, osName);
-
- // There should be a single 'enabled: 1' match
- var enableRegex = new Regex("enabled: 1");
+ Assert.That(enableMatches, Has.Count.EqualTo(1));
+
+ Assert.That(output, Does.Contain($"- first:\n {platformName}: {osName}\n second:\n enabled: 1\n"));
+ });
+ }
+
+ [TestCase(UnityOs.Windows, new[] { "Win", "Win64" })]
+ [TestCase(UnityOs.Linux, new[] { "Linux64" })]
+ [TestCase(UnityOs.OSX, new[] { "OSXUniversal" })]
+ public void GetMetaForDll_Editor(UnityOs os, string[] osNames)
+ {
+ var platformDefs = PlatformDefinition.CreateAllPlatforms();
+ var pDef = platformDefs.Find(os);
+ var output = UnityMeta.GetMetaForDll(
+ Guid.NewGuid(),
+ pDef!,
+ Array.Empty(),
+ Array.Empty());
+
+ // There should be only 'Exclude Editor: 0' and 'Exclude {{ osName }}: 0' matches
+ var excludeRegex = new Regex("Exclude (.*): 0");
+ var excludeMatches = excludeRegex.Matches(output);
+ Assert.That(excludeMatches, Is.Not.Null);
+ var actualExcludes = excludeMatches
+ .Select(match => match.Groups[1].Value)
+ .ToHashSet();
+
+ var expectedExcludes = osNames
+ .Append("Editor")
+ .ToHashSet();
+ Assert.That(actualExcludes.SetEquals(expectedExcludes), Is.True);
+
+ // There should be as many 'enabled: 1' matches as exclude matches
+ var enableRegex = new Regex("enabled: 1");
var enableMatches = enableRegex.Matches(output);
- Assert.IsNotNull(enableMatches);
- Assert.AreEqual(enableMatches.Count, 1);
-
- StringAssert.Contains($"- first:\n {platformName}: {osName}\n second:\n enabled: 1\n", output);
- }
-
- [TestCase(UnityOs.Windows, new[] { "Win", "Win64" })]
- [TestCase(UnityOs.Linux, new[] { "Linux64" })]
- [TestCase(UnityOs.OSX, new[] { "OSXUniversal" })]
- public void GetMetaForDll_Editor(UnityOs os, string[] osNames)
- {
- var platformDefs = PlatformDefinition.CreateAllPlatforms();
- var pDef = platformDefs.Find(os);
- var output = UnityMeta.GetMetaForDll(
- Guid.NewGuid(),
- pDef,
- Array.Empty(),
- Array.Empty());
-
- // There should be only 'Exclude Editor: 0' and 'Exclude {{ osName }}: 0' matches
- var excludeRegex = new Regex("Exclude (.*): 0");
- var excludeMatches = excludeRegex.Matches(output);
- Assert.IsNotNull(excludeMatches);
- var actualExcludes = excludeMatches
- .Select(match => match.Groups[1].Value)
- .ToHashSet();
-
- var expectedExcludes = osNames
- .Append("Editor")
- .ToHashSet();
- Assert.IsTrue(actualExcludes.SetEquals(expectedExcludes));
-
- // There should be as many 'enabled: 1' matches as exclude matches
- var enableRegex = new Regex("enabled: 1");
- var enableMatches = enableRegex.Matches(output);
- Assert.IsNotNull(enableMatches);
- Assert.AreEqual(enableMatches.Count, excludeMatches.Count);
-
- foreach (var osName in actualExcludes)
+ Assert.Multiple(() =>
{
- var platformName = (osName == "Editor") ? osName : "Standalone";
- StringAssert.Contains($"- first:\n {platformName}: {osName}\n second:\n enabled: 1\n", output);
- }
- }
+ Assert.That(enableMatches, Is.Not.Null);
+ Assert.That(excludeMatches, Has.Count.EqualTo(enableMatches.Count));
+ });
+
+ foreach (var osName in actualExcludes)
+ {
+ var platformName = (osName == "Editor") ? osName : "Standalone";
+ Assert.That(output, Does.Contain($"- first:\n {platformName}: {osName}\n second:\n enabled: 1\n"));
+ }
+ }
}
-}
+#pragma warning restore CA1861 // Avoid constant arrays as arguments
+}
diff --git a/src/UnityNuGet.Tests/UnityNuGet.Tests.csproj b/src/UnityNuGet.Tests/UnityNuGet.Tests.csproj
index 96e44cdd..b0f45a29 100644
--- a/src/UnityNuGet.Tests/UnityNuGet.Tests.csproj
+++ b/src/UnityNuGet.Tests/UnityNuGet.Tests.csproj
@@ -1,16 +1,19 @@
-
+
- net7.0
+ net8.0
false
false
- true
-
-
-
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/src/UnityNuGet/DotNetHelper.cs b/src/UnityNuGet/DotNetHelper.cs
index fb8be2ed..baf4df53 100644
--- a/src/UnityNuGet/DotNetHelper.cs
+++ b/src/UnityNuGet/DotNetHelper.cs
@@ -1,238 +1,236 @@
-using System.Collections.Generic;
-
-namespace UnityNuGet
-{
- ///
- /// Helper class to identify which NuGet packages are replaced by .NET Standard 2.0 / 2.1
- ///
- static class DotNetHelper
- {
- public static bool IsNetStandard20Assembly(string packageId) => NetStandard20Assemblies.Contains(packageId);
-
- public static bool IsNetStandard21Assembly(string packageId) => NetStandard21Assemblies.Contains(packageId);
-
- // Retrieved from NuGet package (/build/netstandard2.0/ref): https://www.nuget.org/packages/NETStandard.Library/2.0.3
- private static readonly HashSet NetStandard20Assemblies = new()
- {
- "Microsoft.Win32.Primitives",
- "System.AppContext",
- "System.Collections.Concurrent",
- "System.Collections",
- "System.Collections.NonGeneric",
- "System.Collections.Specialized",
- "System.ComponentModel.Composition",
- "System.ComponentModel",
- "System.ComponentModel.EventBasedAsync",
- "System.ComponentModel.Primitives",
- "System.ComponentModel.TypeConverter",
- "System.Console",
- "System.Core",
- "System.Data.Common",
- "System.Data",
- "System.Diagnostics.Contracts",
- "System.Diagnostics.Debug",
- "System.Diagnostics.FileVersionInfo",
- "System.Diagnostics.Process",
- "System.Diagnostics.StackTrace",
- "System.Diagnostics.TextWriterTraceListener",
- "System.Diagnostics.Tools",
- "System.Diagnostics.TraceSource",
- "System.Diagnostics.Tracing",
- "System",
- "System.Drawing",
- "System.Drawing.Primitives",
- "System.Dynamic.Runtime",
- "System.Globalization.Calendars",
- "System.Globalization",
- "System.Globalization.Extensions",
- "System.IO.Compression",
- "System.IO.Compression.FileSystem",
- "System.IO.Compression.ZipFile",
- "System.IO",
- "System.IO.FileSystem",
- "System.IO.FileSystem.DriveInfo",
- "System.IO.FileSystem.Primitives",
- "System.IO.FileSystem.Watcher",
- "System.IO.IsolatedStorage",
- "System.IO.MemoryMappedFiles",
- "System.IO.Pipes",
- "System.IO.UnmanagedMemoryStream",
- "System.Linq",
- "System.Linq.Expressions",
- "System.Linq.Parallel",
- "System.Linq.Queryable",
- "System.Net",
- "System.Net.Http",
- "System.Net.NameResolution",
- "System.Net.NetworkInformation",
- "System.Net.Ping",
- "System.Net.Primitives",
- "System.Net.Requests",
- "System.Net.Security",
- "System.Net.Sockets",
- "System.Net.WebHeaderCollection",
- "System.Net.WebSockets.Client",
- "System.Net.WebSockets",
- "System.Numerics",
- "System.ObjectModel",
- "System.Reflection",
- "System.Reflection.Extensions",
- "System.Reflection.Primitives",
- "System.Resources.Reader",
- "System.Resources.ResourceManager",
- "System.Resources.Writer",
- "System.Runtime.CompilerServices.VisualC",
- "System.Runtime",
- "System.Runtime.Extensions",
- "System.Runtime.Handles",
- "System.Runtime.InteropServices",
- "System.Runtime.InteropServices.RuntimeInformation",
- "System.Runtime.Numerics",
- "System.Runtime.Serialization",
- "System.Runtime.Serialization.Formatters",
- "System.Runtime.Serialization.Json",
- "System.Runtime.Serialization.Primitives",
- "System.Runtime.Serialization.Xml",
- "System.Security.Claims",
- "System.Security.Cryptography.Algorithms",
- "System.Security.Cryptography.Csp",
- "System.Security.Cryptography.Encoding",
- "System.Security.Cryptography.Primitives",
- "System.Security.Cryptography.X509Certificates",
- "System.Security.Principal",
- "System.Security.SecureString",
- "System.ServiceModel.Web",
- "System.Text.Encoding",
- "System.Text.Encoding.Extensions",
- "System.Text.RegularExpressions",
- "System.Threading",
- "System.Threading.Overlapped",
- "System.Threading.Tasks",
- "System.Threading.Tasks.Parallel",
- "System.Threading.Thread",
- "System.Threading.ThreadPool",
- "System.Threading.Timer",
- "System.Transactions",
- "System.ValueTuple",
- "System.Web",
- "System.Windows",
- "System.Xml",
- "System.Xml.Linq",
- "System.Xml.ReaderWriter",
- "System.Xml.Serialization",
- "System.Xml.XDocument",
- "System.Xml.XmlDocument",
- "System.Xml.XmlSerializer",
- "System.Xml.XPath",
- "System.Xml.XPath.XDocument"
- };
-
- // Retrieved from NuGet package (/ref/netstandard2.1): https://www.nuget.org/packages/NETStandard.Library.Ref
- private static readonly HashSet NetStandard21Assemblies = new()
- {
- "Microsoft.Win32.Primitives",
- "System.AppContext",
- "System.Buffers",
- "System.Collections.Concurrent",
- "System.Collections",
- "System.Collections.NonGeneric",
- "System.Collections.Specialized",
- "System.ComponentModel",
- "System.ComponentModel.EventBasedAsync",
- "System.ComponentModel.Primitives",
- "System.ComponentModel.TypeConverter",
- "System.Console",
- "System.Data.Common",
- "System.Diagnostics.Contracts",
- "System.Diagnostics.Debug",
- "System.Diagnostics.FileVersionInfo",
- "System.Diagnostics.Process",
- "System.Diagnostics.StackTrace",
- "System.Diagnostics.TextWriterTraceListener",
- "System.Diagnostics.Tools",
- "System.Diagnostics.TraceSource",
- "System.Diagnostics.Tracing",
- "System.Drawing.Primitives",
- "System.Dynamic.Runtime",
- "System.Globalization.Calendars",
- "System.Globalization",
- "System.Globalization.Extensions",
- "System.IO.Compression",
- "System.IO.Compression.ZipFile",
- "System.IO",
- "System.IO.FileSystem",
- "System.IO.FileSystem.DriveInfo",
- "System.IO.FileSystem.Primitives",
- "System.IO.FileSystem.Watcher",
- "System.IO.IsolatedStorage",
- "System.IO.MemoryMappedFiles",
- "System.IO.Pipes",
- "System.IO.UnmanagedMemoryStream",
- "System.Linq",
- "System.Linq.Expressions",
- "System.Linq.Parallel",
- "System.Linq.Queryable",
- "System.Memory",
- "System.Net.Http",
- "System.Net.NameResolution",
- "System.Net.NetworkInformation",
- "System.Net.Ping",
- "System.Net.Primitives",
- "System.Net.Requests",
- "System.Net.Security",
- "System.Net.Sockets",
- "System.Net.WebHeaderCollection",
- "System.Net.WebSockets.Client",
- "System.Net.WebSockets",
- "System.Numerics.Vectors",
- "System.ObjectModel",
- "System.Reflection.DispatchProxy",
- "System.Reflection",
- "System.Reflection.Emit",
- "System.Reflection.Emit.ILGeneration",
- "System.Reflection.Emit.Lightweight",
- "System.Reflection.Extensions",
- "System.Reflection.Primitives",
- "System.Resources.Reader",
- "System.Resources.ResourceManager",
- "System.Resources.Writer",
- "System.Runtime.CompilerServices.VisualC",
- "System.Runtime",
- "System.Runtime.Extensions",
- "System.Runtime.Handles",
- "System.Runtime.InteropServices",
- "System.Runtime.InteropServices.RuntimeInformation",
- "System.Runtime.Numerics",
- "System.Runtime.Serialization.Formatters",
- "System.Runtime.Serialization.Json",
- "System.Runtime.Serialization.Primitives",
- "System.Runtime.Serialization.Xml",
- "System.Security.Claims",
- "System.Security.Cryptography.Algorithms",
- "System.Security.Cryptography.Csp",
- "System.Security.Cryptography.Encoding",
- "System.Security.Cryptography.Primitives",
- "System.Security.Cryptography.X509Certificates",
- "System.Security.Principal",
- "System.Security.SecureString",
- "System.Text.Encoding",
- "System.Text.Encoding.Extensions",
- "System.Text.RegularExpressions",
- "System.Threading",
- "System.Threading.Overlapped",
- "System.Threading.Tasks",
- "System.Threading.Tasks.Extensions",
- "System.Threading.Tasks.Parallel",
- "System.Threading.Thread",
- "System.Threading.ThreadPool",
- "System.Threading.Timer",
- "System.ValueTuple",
- "System.Xml.ReaderWriter",
- "System.Xml.XDocument",
- "System.Xml.XmlDocument",
- "System.Xml.XmlSerializer",
- "System.Xml.XPath",
- "System.Xml.XPath.XDocument",
- };
- }
-}
+using System.Collections.Generic;
+
+namespace UnityNuGet
+{
+ ///
+ /// Helper class to identify which NuGet packages are replaced by .NET Standard 2.0 / 2.1
+ ///
+ static class DotNetHelper
+ {
+ public static bool IsNetStandard20Assembly(string packageId) => NetStandard20Assemblies.Contains(packageId);
+
+ public static bool IsNetStandard21Assembly(string packageId) => NetStandard21Assemblies.Contains(packageId);
+
+ // Retrieved from NuGet package (/build/netstandard2.0/ref): https://www.nuget.org/packages/NETStandard.Library/2.0.3
+ private static readonly HashSet NetStandard20Assemblies = [
+ "Microsoft.Win32.Primitives",
+ "System.AppContext",
+ "System.Collections.Concurrent",
+ "System.Collections",
+ "System.Collections.NonGeneric",
+ "System.Collections.Specialized",
+ "System.ComponentModel.Composition",
+ "System.ComponentModel",
+ "System.ComponentModel.EventBasedAsync",
+ "System.ComponentModel.Primitives",
+ "System.ComponentModel.TypeConverter",
+ "System.Console",
+ "System.Core",
+ "System.Data.Common",
+ "System.Data",
+ "System.Diagnostics.Contracts",
+ "System.Diagnostics.Debug",
+ "System.Diagnostics.FileVersionInfo",
+ "System.Diagnostics.Process",
+ "System.Diagnostics.StackTrace",
+ "System.Diagnostics.TextWriterTraceListener",
+ "System.Diagnostics.Tools",
+ "System.Diagnostics.TraceSource",
+ "System.Diagnostics.Tracing",
+ "System",
+ "System.Drawing",
+ "System.Drawing.Primitives",
+ "System.Dynamic.Runtime",
+ "System.Globalization.Calendars",
+ "System.Globalization",
+ "System.Globalization.Extensions",
+ "System.IO.Compression",
+ "System.IO.Compression.FileSystem",
+ "System.IO.Compression.ZipFile",
+ "System.IO",
+ "System.IO.FileSystem",
+ "System.IO.FileSystem.DriveInfo",
+ "System.IO.FileSystem.Primitives",
+ "System.IO.FileSystem.Watcher",
+ "System.IO.IsolatedStorage",
+ "System.IO.MemoryMappedFiles",
+ "System.IO.Pipes",
+ "System.IO.UnmanagedMemoryStream",
+ "System.Linq",
+ "System.Linq.Expressions",
+ "System.Linq.Parallel",
+ "System.Linq.Queryable",
+ "System.Net",
+ "System.Net.Http",
+ "System.Net.NameResolution",
+ "System.Net.NetworkInformation",
+ "System.Net.Ping",
+ "System.Net.Primitives",
+ "System.Net.Requests",
+ "System.Net.Security",
+ "System.Net.Sockets",
+ "System.Net.WebHeaderCollection",
+ "System.Net.WebSockets.Client",
+ "System.Net.WebSockets",
+ "System.Numerics",
+ "System.ObjectModel",
+ "System.Reflection",
+ "System.Reflection.Extensions",
+ "System.Reflection.Primitives",
+ "System.Resources.Reader",
+ "System.Resources.ResourceManager",
+ "System.Resources.Writer",
+ "System.Runtime.CompilerServices.VisualC",
+ "System.Runtime",
+ "System.Runtime.Extensions",
+ "System.Runtime.Handles",
+ "System.Runtime.InteropServices",
+ "System.Runtime.InteropServices.RuntimeInformation",
+ "System.Runtime.Numerics",
+ "System.Runtime.Serialization",
+ "System.Runtime.Serialization.Formatters",
+ "System.Runtime.Serialization.Json",
+ "System.Runtime.Serialization.Primitives",
+ "System.Runtime.Serialization.Xml",
+ "System.Security.Claims",
+ "System.Security.Cryptography.Algorithms",
+ "System.Security.Cryptography.Csp",
+ "System.Security.Cryptography.Encoding",
+ "System.Security.Cryptography.Primitives",
+ "System.Security.Cryptography.X509Certificates",
+ "System.Security.Principal",
+ "System.Security.SecureString",
+ "System.ServiceModel.Web",
+ "System.Text.Encoding",
+ "System.Text.Encoding.Extensions",
+ "System.Text.RegularExpressions",
+ "System.Threading",
+ "System.Threading.Overlapped",
+ "System.Threading.Tasks",
+ "System.Threading.Tasks.Parallel",
+ "System.Threading.Thread",
+ "System.Threading.ThreadPool",
+ "System.Threading.Timer",
+ "System.Transactions",
+ "System.ValueTuple",
+ "System.Web",
+ "System.Windows",
+ "System.Xml",
+ "System.Xml.Linq",
+ "System.Xml.ReaderWriter",
+ "System.Xml.Serialization",
+ "System.Xml.XDocument",
+ "System.Xml.XmlDocument",
+ "System.Xml.XmlSerializer",
+ "System.Xml.XPath",
+ "System.Xml.XPath.XDocument"
+ ];
+
+ // Retrieved from NuGet package (/ref/netstandard2.1): https://www.nuget.org/packages/NETStandard.Library.Ref
+ private static readonly HashSet NetStandard21Assemblies = [
+ "Microsoft.Win32.Primitives",
+ "System.AppContext",
+ "System.Buffers",
+ "System.Collections.Concurrent",
+ "System.Collections",
+ "System.Collections.NonGeneric",
+ "System.Collections.Specialized",
+ "System.ComponentModel",
+ "System.ComponentModel.EventBasedAsync",
+ "System.ComponentModel.Primitives",
+ "System.ComponentModel.TypeConverter",
+ "System.Console",
+ "System.Data.Common",
+ "System.Diagnostics.Contracts",
+ "System.Diagnostics.Debug",
+ "System.Diagnostics.FileVersionInfo",
+ "System.Diagnostics.Process",
+ "System.Diagnostics.StackTrace",
+ "System.Diagnostics.TextWriterTraceListener",
+ "System.Diagnostics.Tools",
+ "System.Diagnostics.TraceSource",
+ "System.Diagnostics.Tracing",
+ "System.Drawing.Primitives",
+ "System.Dynamic.Runtime",
+ "System.Globalization.Calendars",
+ "System.Globalization",
+ "System.Globalization.Extensions",
+ "System.IO.Compression",
+ "System.IO.Compression.ZipFile",
+ "System.IO",
+ "System.IO.FileSystem",
+ "System.IO.FileSystem.DriveInfo",
+ "System.IO.FileSystem.Primitives",
+ "System.IO.FileSystem.Watcher",
+ "System.IO.IsolatedStorage",
+ "System.IO.MemoryMappedFiles",
+ "System.IO.Pipes",
+ "System.IO.UnmanagedMemoryStream",
+ "System.Linq",
+ "System.Linq.Expressions",
+ "System.Linq.Parallel",
+ "System.Linq.Queryable",
+ "System.Memory",
+ "System.Net.Http",
+ "System.Net.NameResolution",
+ "System.Net.NetworkInformation",
+ "System.Net.Ping",
+ "System.Net.Primitives",
+ "System.Net.Requests",
+ "System.Net.Security",
+ "System.Net.Sockets",
+ "System.Net.WebHeaderCollection",
+ "System.Net.WebSockets.Client",
+ "System.Net.WebSockets",
+ "System.Numerics.Vectors",
+ "System.ObjectModel",
+ "System.Reflection.DispatchProxy",
+ "System.Reflection",
+ "System.Reflection.Emit",
+ "System.Reflection.Emit.ILGeneration",
+ "System.Reflection.Emit.Lightweight",
+ "System.Reflection.Extensions",
+ "System.Reflection.Primitives",
+ "System.Resources.Reader",
+ "System.Resources.ResourceManager",
+ "System.Resources.Writer",
+ "System.Runtime.CompilerServices.VisualC",
+ "System.Runtime",
+ "System.Runtime.Extensions",
+ "System.Runtime.Handles",
+ "System.Runtime.InteropServices",
+ "System.Runtime.InteropServices.RuntimeInformation",
+ "System.Runtime.Numerics",
+ "System.Runtime.Serialization.Formatters",
+ "System.Runtime.Serialization.Json",
+ "System.Runtime.Serialization.Primitives",
+ "System.Runtime.Serialization.Xml",
+ "System.Security.Claims",
+ "System.Security.Cryptography.Algorithms",
+ "System.Security.Cryptography.Csp",
+ "System.Security.Cryptography.Encoding",
+ "System.Security.Cryptography.Primitives",
+ "System.Security.Cryptography.X509Certificates",
+ "System.Security.Principal",
+ "System.Security.SecureString",
+ "System.Text.Encoding",
+ "System.Text.Encoding.Extensions",
+ "System.Text.RegularExpressions",
+ "System.Threading",
+ "System.Threading.Overlapped",
+ "System.Threading.Tasks",
+ "System.Threading.Tasks.Extensions",
+ "System.Threading.Tasks.Parallel",
+ "System.Threading.Thread",
+ "System.Threading.ThreadPool",
+ "System.Threading.Timer",
+ "System.ValueTuple",
+ "System.Xml.ReaderWriter",
+ "System.Xml.XDocument",
+ "System.Xml.XmlDocument",
+ "System.Xml.XmlSerializer",
+ "System.Xml.XPath",
+ "System.Xml.XPath.XDocument",
+ ];
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmError.cs b/src/UnityNuGet/Npm/NpmError.cs
index 4c77053a..17a8a992 100644
--- a/src/UnityNuGet/Npm/NpmError.cs
+++ b/src/UnityNuGet/Npm/NpmError.cs
@@ -1,24 +1,18 @@
-using Newtonsoft.Json;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// A simple object to return npm errors. Used mainly for returning
- ///
- public class NpmError : NpmObject
- {
- public static readonly NpmError NotFound = new("not_found", "document not found");
-
- public NpmError(string error, string reason)
- {
- Error = error;
- Reason = reason;
- }
-
- [JsonProperty("error")]
- public string Error { get; }
-
- [JsonProperty("reason")]
- public string Reason { get; }
- }
-}
+using Newtonsoft.Json;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// A simple object to return npm errors. Used mainly for returning
+ ///
+ public class NpmError(string error, string reason) : NpmObject
+ {
+ public static readonly NpmError NotFound = new("not_found", "document not found");
+
+ [JsonProperty("error")]
+ public string Error { get; } = error;
+
+ [JsonProperty("reason")]
+ public string Reason { get; } = reason;
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmPackage.cs b/src/UnityNuGet/Npm/NpmPackage.cs
index dc5420ec..5275f683 100644
--- a/src/UnityNuGet/Npm/NpmPackage.cs
+++ b/src/UnityNuGet/Npm/NpmPackage.cs
@@ -1,51 +1,51 @@
-using System;
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// Describes a full NPM package (used as a response to `{packageId}`)
- ///
- public class NpmPackage : NpmObject
- {
- public NpmPackage()
- {
- Revision = "1-0";
- DistTags = new();
- Versions = new();
- Time = new();
- Users = new();
- }
-
- [JsonProperty("_id")]
- public string? Id { get; set; }
-
- [JsonProperty("_rev")]
- public string Revision { get; set; }
-
- [JsonProperty("name")]
- public string? Name { get; set; }
-
- [JsonProperty("license")]
- public string? License { get; set; }
-
- [JsonProperty("description")]
- public string? Description { get; set; }
-
- [JsonProperty("dist-tags")]
- public Dictionary DistTags { get; }
-
- [JsonProperty("versions")]
- public Dictionary Versions { get; }
-
- [JsonProperty("time")]
- public Dictionary Time { get; }
-
- [JsonProperty("repository", NullValueHandling = NullValueHandling.Ignore)]
- public NpmSourceRepository? Repository { get; set; }
-
- [JsonProperty("users")]
- public Dictionary Users { get; }
- }
-}
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// Describes a full NPM package (used as a response to `{packageId}`)
+ ///
+ public class NpmPackage : NpmObject
+ {
+ public NpmPackage()
+ {
+ Revision = "1-0";
+ DistTags = [];
+ Versions = [];
+ Time = [];
+ Users = [];
+ }
+
+ [JsonProperty("_id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("_rev")]
+ public string Revision { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("license")]
+ public string? License { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("dist-tags")]
+ public Dictionary DistTags { get; }
+
+ [JsonProperty("versions")]
+ public Dictionary Versions { get; }
+
+ [JsonProperty("time")]
+ public Dictionary Time { get; }
+
+ [JsonProperty("repository", NullValueHandling = NullValueHandling.Ignore)]
+ public NpmSourceRepository? Repository { get; set; }
+
+ [JsonProperty("users")]
+ public Dictionary Users { get; }
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmPackageInfo.cs b/src/UnityNuGet/Npm/NpmPackageInfo.cs
index 31834ecb..b2401a70 100644
--- a/src/UnityNuGet/Npm/NpmPackageInfo.cs
+++ b/src/UnityNuGet/Npm/NpmPackageInfo.cs
@@ -1,40 +1,40 @@
-using System;
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// Describes a package for "all" listing, used by
- ///
- public class NpmPackageInfo : NpmObject
- {
- public NpmPackageInfo()
- {
- Maintainers = new();
- Versions = new();
- Keywords = new();
- }
-
- [JsonProperty("name")]
- public string? Name { get; set; }
-
- [JsonProperty("description")]
- public string? Description { get; set; }
-
- [JsonProperty("maintainers")]
- public List Maintainers { get; }
-
- [JsonProperty("versions")]
- public Dictionary Versions { get; }
-
- [JsonProperty("time")]
- public DateTimeOffset? Time { get; set; }
-
- [JsonProperty("keywords")]
- public List Keywords { get; }
-
- [JsonProperty("author")]
- public string? Author { get; set; }
- }
-}
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// Describes a package for "all" listing, used by
+ ///
+ public class NpmPackageInfo : NpmObject
+ {
+ public NpmPackageInfo()
+ {
+ Maintainers = [];
+ Versions = [];
+ Keywords = [];
+ }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("maintainers")]
+ public List Maintainers { get; }
+
+ [JsonProperty("versions")]
+ public Dictionary Versions { get; }
+
+ [JsonProperty("time")]
+ public DateTimeOffset? Time { get; set; }
+
+ [JsonProperty("keywords")]
+ public List Keywords { get; }
+
+ [JsonProperty("author")]
+ public string? Author { get; set; }
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmPackageListAllResponse.cs b/src/UnityNuGet/Npm/NpmPackageListAllResponse.cs
index 7293a718..34ac33f0 100644
--- a/src/UnityNuGet/Npm/NpmPackageListAllResponse.cs
+++ b/src/UnityNuGet/Npm/NpmPackageListAllResponse.cs
@@ -1,50 +1,48 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// Represents a `-/all` listing package NPM response
- ///
- ///
- /// NOTE: only used to serialize from C# to JSON (JSON To C# is not implemented)
- ///
- public class NpmPackageListAllResponse : NpmObject
- {
- public NpmPackageListAllResponse()
- {
- Unused = 99999;
- Packages = new();
- }
-
- [JsonProperty("_updated")]
- public int Unused { get; set; }
-
- [JsonIgnore]
- public Dictionary Packages { get; }
-
- // everything else gets stored here
- [JsonExtensionData]
-#pragma warning disable IDE0051 // Remove unused private members
- private IDictionary AdditionalData
-#pragma warning restore IDE0051 // Remove unused private members
- {
- get
- {
- var marshalPackages = new Dictionary();
- foreach (var packagePair in Packages)
- {
- marshalPackages.Add(packagePair.Key, JObject.FromObject(packagePair.Value));
- }
-
- return marshalPackages;
- }
- }
-
- public void Reset()
- {
- Packages.Clear();
- }
- }
-}
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// Represents a `-/all` listing package NPM response
+ ///
+ ///
+ /// NOTE: only used to serialize from C# to JSON (JSON To C# is not implemented)
+ ///
+ public class NpmPackageListAllResponse : NpmObject
+ {
+ public NpmPackageListAllResponse()
+ {
+ Unused = 99999;
+ Packages = [];
+ }
+
+ [JsonProperty("_updated")]
+ public int Unused { get; set; }
+
+ [JsonIgnore]
+ public Dictionary Packages { get; }
+
+ // Everything else gets stored here
+ [JsonExtensionData]
+ private IDictionary AdditionalData
+ {
+ get
+ {
+ var marshalPackages = new Dictionary();
+ foreach (var packagePair in Packages)
+ {
+ marshalPackages.Add(packagePair.Key, JObject.FromObject(packagePair.Value));
+ }
+
+ return marshalPackages;
+ }
+ }
+
+ public void Reset()
+ {
+ Packages.Clear();
+ }
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmPackageRegistry.cs b/src/UnityNuGet/Npm/NpmPackageRegistry.cs
index 3db6003b..4eb69f90 100644
--- a/src/UnityNuGet/Npm/NpmPackageRegistry.cs
+++ b/src/UnityNuGet/Npm/NpmPackageRegistry.cs
@@ -1,38 +1,38 @@
-using System.Collections.Generic;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// Used to store all type of responses (all packages, or single packages but also unlisted packages)
- ///
- public class NpmPackageRegistry : NpmObject
- {
- public NpmPackageRegistry()
- {
- Packages = new();
- ListedPackageInfos = new();
- UnlistedPackageInfos = new();
- }
-
- public Dictionary Packages { get; }
-
- public NpmPackageListAllResponse ListedPackageInfos { get; }
-
- public NpmPackageListAllResponse UnlistedPackageInfos { get; }
-
- public void AddPackage(NpmPackageCacheEntry entry, bool isListed)
- {
- var package = entry.Package!;
- Packages.Add(package.Id!, package);
- var packageInfos = isListed ? ListedPackageInfos : UnlistedPackageInfos;
- packageInfos.Packages.Add(package.Id!, entry.Info!);
- }
-
- public void Reset()
- {
- Packages.Clear();
- ListedPackageInfos.Reset();
- UnlistedPackageInfos.Reset();
- }
- }
-}
+using System.Collections.Generic;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// Used to store all type of responses (all packages, or single packages but also unlisted packages)
+ ///
+ public class NpmPackageRegistry : NpmObject
+ {
+ public NpmPackageRegistry()
+ {
+ Packages = [];
+ ListedPackageInfos = new();
+ UnlistedPackageInfos = new();
+ }
+
+ public Dictionary Packages { get; }
+
+ public NpmPackageListAllResponse ListedPackageInfos { get; }
+
+ public NpmPackageListAllResponse UnlistedPackageInfos { get; }
+
+ public void AddPackage(NpmPackageCacheEntry entry, bool isListed)
+ {
+ var package = entry.Package!;
+ Packages.Add(package.Id!, package);
+ var packageInfos = isListed ? ListedPackageInfos : UnlistedPackageInfos;
+ packageInfos.Packages.Add(package.Id!, entry.Info!);
+ }
+
+ public void Reset()
+ {
+ Packages.Clear();
+ ListedPackageInfos.Reset();
+ UnlistedPackageInfos.Reset();
+ }
+ }
+}
diff --git a/src/UnityNuGet/Npm/NpmPackageVersion.cs b/src/UnityNuGet/Npm/NpmPackageVersion.cs
index de90dee1..932f7f92 100644
--- a/src/UnityNuGet/Npm/NpmPackageVersion.cs
+++ b/src/UnityNuGet/Npm/NpmPackageVersion.cs
@@ -1,51 +1,51 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
-namespace UnityNuGet.Npm
-{
- ///
- /// Describes a version of a
- ///
- public class NpmPackageVersion : NpmObject
- {
- public NpmPackageVersion()
- {
- Dependencies = new();
- Distribution = new();
- Scripts = new();
- }
-
- [JsonProperty("name")]
- public string? Name { get; set; }
-
- [JsonProperty("version")]
- public string? Version { get; set; }
-
- [JsonProperty("dist")]
- public NpmDistribution Distribution { get; }
-
- [JsonProperty("dependencies")]
- public Dictionary Dependencies { get; }
-
- [JsonProperty("_id")]
- public string? Id { get; set; }
-
- [JsonProperty("unity", NullValueHandling = NullValueHandling.Ignore)]
- public string? Unity { get; set; }
-
- [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)]
- public string? Description { get; set; }
-
- [JsonProperty("displayName", NullValueHandling = NullValueHandling.Ignore)]
- public string? DisplayName { get; set; }
-
- [JsonProperty("scripts", NullValueHandling = NullValueHandling.Ignore)]
- public Dictionary Scripts { get; }
-
- [JsonProperty("repository", NullValueHandling = NullValueHandling.Ignore)]
- public NpmSourceRepository? Repository { get; set; }
-
- [JsonProperty("author", NullValueHandling = NullValueHandling.Ignore)]
- public string? Author { get; set; }
- }
-}
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace UnityNuGet.Npm
+{
+ ///
+ /// Describes a version of a
+ ///
+ public class NpmPackageVersion : NpmObject
+ {
+ public NpmPackageVersion()
+ {
+ Dependencies = [];
+ Distribution = new();
+ Scripts = [];
+ }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("version")]
+ public string? Version { get; set; }
+
+ [JsonProperty("dist")]
+ public NpmDistribution Distribution { get; }
+
+ [JsonProperty("dependencies")]
+ public Dictionary Dependencies { get; }
+
+ [JsonProperty("_id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("unity", NullValueHandling = NullValueHandling.Ignore)]
+ public string? Unity { get; set; }
+
+ [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)]
+ public string? Description { get; set; }
+
+ [JsonProperty("displayName", NullValueHandling = NullValueHandling.Ignore)]
+ public string? DisplayName { get; set; }
+
+ [JsonProperty("scripts", NullValueHandling = NullValueHandling.Ignore)]
+ public Dictionary Scripts { get; }
+
+ [JsonProperty("repository", NullValueHandling = NullValueHandling.Ignore)]
+ public NpmSourceRepository? Repository { get; set; }
+
+ [JsonProperty("author", NullValueHandling = NullValueHandling.Ignore)]
+ public string? Author { get; set; }
+ }
+}
diff --git a/src/UnityNuGet/NuGetHelper.cs b/src/UnityNuGet/NuGetHelper.cs
index 7266c3d0..ff4f6111 100644
--- a/src/UnityNuGet/NuGetHelper.cs
+++ b/src/UnityNuGet/NuGetHelper.cs
@@ -8,10 +8,11 @@
namespace UnityNuGet
{
- static class NuGetHelper
+ static partial class NuGetHelper
{
// https://learn.microsoft.com/en-us/visualstudio/extensibility/roslyn-version-support
- private static readonly Regex roslynVersionRegex = new(@"/roslyn(\d+)\.(\d+)\.?(\d*)/");
+ [GeneratedRegex(@"/roslyn(\d+)\.(\d+)\.?(\d*)/")]
+ private static partial Regex RoslynVersion();
// https://docs.unity3d.com/Manual/roslyn-analyzers.html
private static readonly Version unityRoslynSupportedVersion = new(3, 8, 0);
@@ -63,7 +64,7 @@ bool IsResource()
public static bool IsApplicableUnitySupportedRoslynVersionFolder(string file)
{
- var roslynVersionMatch = roslynVersionRegex.Match(file);
+ var roslynVersionMatch = RoslynVersion().Match(file);
bool hasRoslynVersionFolder = roslynVersionMatch.Success;
bool hasUnitySupportedRoslynVersionFolder = hasRoslynVersionFolder &&
diff --git a/src/UnityNuGet/PlatformDefinition.cs b/src/UnityNuGet/PlatformDefinition.cs
index 08d8e277..04e247ae 100644
--- a/src/UnityNuGet/PlatformDefinition.cs
+++ b/src/UnityNuGet/PlatformDefinition.cs
@@ -1,407 +1,392 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace UnityNuGet
-{
- ///
- /// All operating systems supported by Unity
- ///
- public enum UnityOs
- {
- AnyOs,
- Windows,
- Linux,
- OSX,
- Android,
- WebGL,
- iOS
- }
-
- ///
- /// All CPUs supported by Unity
- ///
- public enum UnityCpu
- {
- AnyCpu,
- X64,
- X86,
- ARM64,
- ARMv7,
- None,
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace UnityNuGet
+{
+ ///
+ /// All operating systems supported by Unity
+ ///
+ public enum UnityOs
+ {
+ AnyOs,
+ Windows,
+ Linux,
+ OSX,
+ Android,
+ WebGL,
+ iOS
+ }
+
+ ///
+ /// All CPUs supported by Unity
+ ///
+ public enum UnityCpu
+ {
+ AnyCpu,
+ X64,
+ X86,
+ ARM64,
+ ARMv7,
+ None,
+ }
+
+ ///
+ /// Extensions for and
+ ///
+ internal static class UnityEnumExtensions
+ {
+ ///
+ /// Converts a to string.
+ ///
+ /// The value to be converted.
+ /// This method should be used for constructing package paths for OS-dependent files.
+ /// A string representation of the provided value.
+ public static string GetPathName(this UnityOs os)
+ {
+ return os switch
+ {
+ UnityOs.AnyOs => string.Empty,
+ _ => GetName(os),
+ };
+ }
+
+ ///
+ /// Converts a to a string representation accepted by the Unity .meta file format.
+ ///
+ /// The value to be converted.
+ /// A string representation of the provided value.
+ public static string GetName(this UnityOs os)
+ {
+ return os switch
+ {
+ UnityOs.AnyOs => "AnyOS",
+ UnityOs.Windows => "Windows",
+ UnityOs.Linux => "Linux",
+ UnityOs.OSX => "OSX",
+ UnityOs.Android => "Android",
+ UnityOs.WebGL => "WebGL",
+ UnityOs.iOS => "iOS",
+ _ => throw new ArgumentException($"Unknown OS {os}"),
+ };
+ }
+
+ ///
+ /// Converts a to string.
+ ///
+ /// The value to be converted.
+ /// This method should be used for constructing package paths for CPU-dependent files.
+ /// A string representation of the provided value.
+ public static string GetPathName(this UnityCpu cpu)
+ {
+ return cpu switch
+ {
+ UnityCpu.AnyCpu => string.Empty,
+ _ => GetName(cpu),
+ };
+ }
+
+ ///
+ /// Converts a to a string representation accepted by the Unity .meta file format.
+ ///
+ /// The value to be converted.
+ /// A string representation of the provided value.
+ public static string GetName(this UnityCpu cpu)
+ {
+ return cpu switch
+ {
+ UnityCpu.AnyCpu => "AnyCPU",
+ UnityCpu.X64 => "x86_64",
+ UnityCpu.X86 => "x86",
+ UnityCpu.ARM64 => "ARM64",
+ UnityCpu.ARMv7 => "ARMv7",
+ UnityCpu.None => "None",
+ _ => throw new ArgumentException($"Unknown CPU {cpu}"),
+ };
+ }
}
- ///
- /// Extensions for and
- ///
- internal static class UnityEnumExtensions
- {
- ///
- /// Converts a to string.
- ///
- /// The value to be converted.
- /// This method should be used for constructing package paths for OS-dependent files.
- /// A string representation of the provided value.
- public static string GetPathName(this UnityOs os)
- {
- return os switch
- {
- UnityOs.AnyOs => string.Empty,
- _ => GetName(os),
- };
- }
-
- ///
- /// Converts a to a string representation accepted by the Unity .meta file format.
- ///
- /// The value to be converted.
- /// A string representation of the provided value.
- public static string GetName(this UnityOs os)
- {
- return os switch
- {
- UnityOs.AnyOs => "AnyOS",
- UnityOs.Windows => "Windows",
- UnityOs.Linux => "Linux",
- UnityOs.OSX => "OSX",
- UnityOs.Android => "Android",
- UnityOs.WebGL => "WebGL",
- UnityOs.iOS => "iOS",
- _ => throw new ArgumentException($"Unknown OS {os}"),
- };
- }
-
- ///
- /// Converts a to string.
- ///
- /// The value to be converted.
- /// This method should be used for constructing package paths for CPU-dependent files.
- /// A string representation of the provided value.
- public static string GetPathName(this UnityCpu cpu)
- {
- return cpu switch
- {
- UnityCpu.AnyCpu => string.Empty,
- _ => GetName(cpu),
- };
- }
-
- ///
- /// Converts a to a string representation accepted by the Unity .meta file format.
- ///
- /// The value to be converted.
- /// A string representation of the provided value.
- public static string GetName(this UnityCpu cpu)
- {
- return cpu switch
- {
- UnityCpu.AnyCpu => "AnyCPU",
- UnityCpu.X64 => "x86_64",
- UnityCpu.X86 => "x86",
- UnityCpu.ARM64 => "ARM64",
- UnityCpu.ARMv7 => "ARMv7",
- UnityCpu.None => "None",
- _ => throw new ArgumentException($"Unknown CPU {cpu}"),
- };
- }
+ ///
+ /// A subtree of hierarchical (os, cpu) configuration tuples that are supported by Unity.
+ ///
+ ///
+ /// The root node is typically the most general configuration, i.e.
+ /// supporting and . Leaf nodes are typically specialized,
+ /// targeting a specific OS and CPU flavor.
+ ///
+ ///
+ /// Creates a new instance.
+ ///
+ /// The OS.
+ /// The CPU flavor.
+ /// True if the Unity editor is available in this (os, cpu) tuple.
+ internal class PlatformDefinition(UnityOs os, UnityCpu cpu, bool isEditorConfig)
+ {
+ private readonly UnityOs _os = os;
+ private readonly UnityCpu _cpu = cpu;
+ private readonly bool _isEditor = isEditorConfig;
+ private readonly List _children = [];
+
+ private PlatformDefinition? _parent = null;
+
+ ///
+ /// The parent that is a superset of this.
+ ///
+ public PlatformDefinition? Parent
+ {
+ get => _parent;
+
+ private set
+ {
+ _parent = value;
+ }
+ }
+
+ ///
+ /// The child configurations this is a superset of.
+ ///
+ public IReadOnlyList Children
+ {
+ get => _children;
+
+ private set
+ {
+ _children.AddRange(value);
+
+ foreach (var child in _children)
+ {
+ child.Parent = this;
+ }
+ }
+ }
+
+ ///
+ /// The distance from the root in the configuration tree.
+ ///
+ public int Depth
+ => (_parent == null) ? 0 : (1 + _parent.Depth);
+
+ ///
+ /// The operating system.
+ ///
+ public UnityOs Os
+ => _os;
+
+ ///
+ /// The CPU flavor.
+ ///
+ public UnityCpu Cpu
+ => _cpu;
+
+ ///
+ public override string ToString()
+ => $"{_os}.{_cpu}";
+
+ ///
+ /// Attempts to find a that matches the given
+ /// and among the descendants of this configuration.
+ ///
+ /// The operating system to match.
+ /// The CPU flavor to match.
+ /// A matching .
+ public PlatformDefinition? Find(UnityOs os, UnityCpu? cpu = default)
+ {
+ // Test self
+ if ((_os == os) && ((cpu == null) || (_cpu == cpu)))
+ {
+ return this;
+ }
+
+ // Recurse to children
+ return _children
+ .Select(c => c.Find(os, cpu))
+ .Where(c => c != null)
+ .FirstOrDefault();
+ }
+
+ ///
+ /// Attempts to find a for which the Unity editor is available
+ /// among the descendants of this configuration.
+ ///
+ /// A matching .
+ public PlatformDefinition? FindEditor()
+ {
+ // Test self
+ if (_isEditor)
+ {
+ return this;
+ }
+
+ // Recurse to children
+ return _children
+ .Select(c => c.FindEditor())
+ .Where(c => c != null)
+ .FirstOrDefault();
+ }
+
+ ///
+ /// Returns the difference set of configurations this is a superset of,
+ /// that are not already part of the given visited set.
+ ///
+ /// The set of already visited configurations, that should not be part of the returned set.
+ ///
+ /// A set of configurations this is a superset of,
+ /// that are not already part of the given visited set.
+ ///
+ public HashSet GetRemainingPlatforms(IReadOnlySet visitedPlatforms)
+ {
+ var remainingPlatforms = new HashSet
+ {
+ // Push the root
+ this
+ };
+
+ for (bool found = true; found;)
+ {
+ found = false;
+
+ foreach (var p in remainingPlatforms)
+ {
+ // Remove p if already visited
+ if (visitedPlatforms.Contains(p))
+ {
+ remainingPlatforms.Remove(p);
+ found = true;
+ break;
+ }
+
+ // If p has descendants that were visited, we can't use it and need to expand it
+ if (p.HasVisitedDescendants(visitedPlatforms))
+ {
+ remainingPlatforms.Remove(p);
+
+ foreach (var c in p.Children)
+ {
+ remainingPlatforms.Add(c);
+ }
+
+ found = true;
+ break;
+ }
+ }
+ }
+
+ return remainingPlatforms;
+ }
+
+ ///
+ /// Creates the tree of all known (os, cpu) configurations supported by Unity
+ ///
+ ///
+ public static PlatformDefinition CreateAllPlatforms()
+ {
+ var root = new PlatformDefinition(UnityOs.AnyOs, UnityCpu.AnyCpu, isEditorConfig: true)
+ {
+ Children = new List()
+ {
+ new(UnityOs.Windows, UnityCpu.AnyCpu, isEditorConfig: true)
+ {
+ Children = new List()
+ {
+ new(UnityOs.Windows, UnityCpu.X64, isEditorConfig: true),
+ new(UnityOs.Windows, UnityCpu.X86, isEditorConfig: false),
+ },
+ },
+ new(UnityOs.Linux, UnityCpu.X64, isEditorConfig: true),
+ new(UnityOs.Android, UnityCpu.ARMv7, isEditorConfig: false),
+ new(UnityOs.WebGL, UnityCpu.AnyCpu, isEditorConfig: false),
+ new(UnityOs.iOS, UnityCpu.AnyCpu, isEditorConfig: false),
+ new(UnityOs.OSX, UnityCpu.AnyCpu, isEditorConfig: true)
+ {
+ Children = new List()
+ {
+ new(UnityOs.OSX, UnityCpu.X64, isEditorConfig: true),
+ new(UnityOs.OSX, UnityCpu.ARM64, isEditorConfig: true),
+ },
+ }
+ }
+ };
+
+ return root;
+ }
+
+ ///
+ /// Returns true if either this or any of its descendants
+ /// is also part of the given set of visited configurations.
+ /// The set of visited configurations to test against.
+ ///
+ private bool HasVisitedDescendants(IReadOnlySet visitedPlatforms)
+ {
+ if (visitedPlatforms.Contains(this))
+ {
+ return true;
+ }
+
+ foreach (var c in _children)
+ {
+ if (c.HasVisitedDescendants(visitedPlatforms))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
- ///
- /// A subtree of hierarchical (os, cpu) configuration tuples that are supported by Unity.
- ///
- ///
- /// The root node is typically the most general configuration, i.e.
- /// supporting and . Leaf nodes are typically specialized,
- /// targeting a specific OS and CPU flavor.
- ///
- internal class PlatformDefinition
- {
- private readonly UnityOs _os;
- private readonly UnityCpu _cpu;
- private readonly bool _isEditor;
- private readonly List _children;
-
- private PlatformDefinition? _parent;
-
- ///
- /// Creates a new instance.
- ///
- /// The OS.
- /// The CPU flavor.
- /// True if the Unity editor is available in this (os, cpu) tuple.
- public PlatformDefinition(UnityOs os, UnityCpu cpu, bool isEditorConfig)
- {
- _os = os;
- _cpu = cpu;
- _parent = null;
- _children = new();
- _isEditor = isEditorConfig;
- }
-
- ///
- /// The parent that is a superset of this.
- ///
- public PlatformDefinition? Parent
- {
- get => _parent;
-
- private set
- {
- _parent = value;
- }
- }
-
- ///
- /// The child configurations this is a superset of.
- ///
- public IReadOnlyList Children
- {
- get => _children;
-
- private set
- {
- _children.AddRange(value);
-
- foreach (var child in _children)
- {
- child.Parent = this;
- }
- }
- }
-
- ///
- /// The distance from the root in the configuration tree.
- ///
- public int Depth
- => (_parent == null) ? 0 : (1 + _parent.Depth);
-
- ///
- /// The operating system.
- ///
- public UnityOs Os
- => _os;
-
- ///
- /// The CPU flavor.
- ///
- public UnityCpu Cpu
- => _cpu;
-
- ///
- public override string ToString()
- => $"{_os}.{_cpu}";
-
- ///
- /// Attempts to find a that matches the given
- /// and among the descendants of this configuration.
- ///
- /// The operating system to match.
- /// The CPU flavor to match.
- /// A matching .
- public PlatformDefinition? Find(UnityOs os, UnityCpu? cpu = default)
- {
- // Test self
- if ((_os == os) && ((cpu == null) || (_cpu == cpu)))
- {
- return this;
- }
-
- // Recurse to children
- return _children
- .Select(c => c.Find(os, cpu))
- .Where(c => c != null)
- .FirstOrDefault();
- }
-
- ///
- /// Attempts to find a for which the Unity editor is available
- /// among the descendants of this configuration.
- ///
- /// A matching .
- public PlatformDefinition? FindEditor()
- {
- // Test self
- if (_isEditor)
- {
- return this;
- }
-
- // Recurse to children
- return _children
- .Select(c => c.FindEditor())
- .Where(c => c != null)
- .FirstOrDefault();
- }
-
- ///
- /// Returns the difference set of configurations this is a superset of,
- /// that are not already part of the given visited set.
- ///
- /// The set of already visited configurations, that should not be part of the returned set.
- ///
- /// A set of configurations this is a superset of,
- /// that are not already part of the given visited set.
- ///
- public HashSet GetRemainingPlatforms(IReadOnlySet visitedPlatforms)
- {
- var remainingPlatforms = new HashSet
- {
- // Push the root
- this
- };
-
- for (bool found = true; found;)
- {
- found = false;
-
- foreach (var p in remainingPlatforms)
- {
- // Remove p if already visited
- if (visitedPlatforms.Contains(p))
- {
- remainingPlatforms.Remove(p);
- found = true;
- break;
- }
-
- // If p has descendants that were visited, we can't use it and need to expand it
- if (p.HasVisitedDescendants(visitedPlatforms))
- {
- remainingPlatforms.Remove(p);
-
- foreach (var c in p.Children)
- {
- remainingPlatforms.Add(c);
- }
-
- found = true;
- break;
- }
- }
- }
-
- return remainingPlatforms;
- }
-
- ///
- /// Creates the tree of all known (os, cpu) configurations supported by Unity
- ///
- ///
- public static PlatformDefinition CreateAllPlatforms()
- {
- var root = new PlatformDefinition(UnityOs.AnyOs, UnityCpu.AnyCpu, isEditorConfig: true)
- {
- Children = new List()
- {
- new PlatformDefinition(UnityOs.Windows, UnityCpu.AnyCpu, isEditorConfig: true)
- {
- Children = new List()
- {
- new PlatformDefinition(UnityOs.Windows, UnityCpu.X64, isEditorConfig: true),
- new PlatformDefinition(UnityOs.Windows, UnityCpu.X86, isEditorConfig: false),
- },
- },
- new PlatformDefinition(UnityOs.Linux, UnityCpu.X64, isEditorConfig: true),
- new PlatformDefinition(UnityOs.Android, UnityCpu.ARMv7, isEditorConfig: false),
- new PlatformDefinition(UnityOs.WebGL, UnityCpu.AnyCpu, isEditorConfig: false),
- new PlatformDefinition(UnityOs.iOS, UnityCpu.AnyCpu, isEditorConfig: false),
- new PlatformDefinition(UnityOs.OSX, UnityCpu.AnyCpu, isEditorConfig: true)
- {
- Children = new List()
- {
- new PlatformDefinition(UnityOs.OSX, UnityCpu.X64, isEditorConfig: true),
- new PlatformDefinition(UnityOs.OSX, UnityCpu.ARM64, isEditorConfig: true),
- },
- }
- }
- };
-
- return root;
- }
-
- ///
- /// Returns true if either this or any of its descendants
- /// is also part of the given set of visited configurations.
- /// The set of visited configurations to test against.
- ///
- private bool HasVisitedDescendants(IReadOnlySet visitedPlatforms)
- {
- if (visitedPlatforms.Contains(this))
- {
- return true;
- }
-
- foreach (var c in _children)
- {
- if (c.HasVisitedDescendants(visitedPlatforms))
- {
- return true;
- }
- }
-
- return false;
- }
- }
-
- ///
- /// Associates a file path with the the file is compatible with.
- ///
- internal class PlatformFile
- {
- private readonly PlatformDefinition _platform;
- private readonly string _sourcePath;
-
- ///
- /// Creates a new instance.
- ///
- /// The full path of the file in the original NuGet package.
- /// The platform the file is compatible with.
- public PlatformFile(string sourcePath, PlatformDefinition platform)
- {
- _sourcePath = sourcePath;
- _platform = platform;
- }
-
- ///
- /// The full path of the file in the original NuGet package.
- ///
- public string SourcePath
- => _sourcePath;
-
- ///
- /// The the file is compatible with.
- ///
- public PlatformDefinition Platform
- => _platform;
-
- ///
- /// Returns the full path of the file in the UPM package.
- ///
- /// The file path to start from.
- /// The full path of the file in the UPM package.
- public string GetDestinationPath(string basePath)
- {
- // We start with just the base path
- var fullPath = basePath;
- var depth = _platform.Depth;
-
- if (depth > 0)
- {
- // Our configuration is not AnyOS, add a / to our full path
- fullPath = Path.Combine(fullPath, _platform.Os.GetPathName());
- }
-
- if (depth > 1)
- {
- // Our CPU os not AnyCPU, add a / to our full path
- fullPath = Path.Combine(fullPath, _platform.Cpu.GetPathName());
- }
-
- // Finally, append the file name and return
- var fileName = Path.GetFileName(_sourcePath);
- fullPath = Path.Combine(fullPath, fileName);
- return fullPath;
- }
- }
-}
+ ///
+ /// Associates a file path with the the file is compatible with.
+ ///
+ ///
+ /// Creates a new instance.
+ ///
+ /// The full path of the file in the original NuGet package.
+ /// The platform the file is compatible with.
+ internal class PlatformFile(string sourcePath, PlatformDefinition platform)
+ {
+ private readonly PlatformDefinition _platform = platform;
+ private readonly string _sourcePath = sourcePath;
+
+ ///
+ /// The full path of the file in the original NuGet package.
+ ///
+ public string SourcePath
+ => _sourcePath;
+
+ ///
+ /// The the file is compatible with.
+ ///
+ public PlatformDefinition Platform
+ => _platform;
+
+ ///
+ /// Returns the full path of the file in the UPM package.
+ ///
+ /// The file path to start from.
+ /// The full path of the file in the UPM package.
+ public string GetDestinationPath(string basePath)
+ {
+ // We start with just the base path
+ var fullPath = basePath;
+ var depth = _platform.Depth;
+
+ if (depth > 0)
+ {
+ // Our configuration is not AnyOS, add a / to our full path
+ fullPath = Path.Combine(fullPath, _platform.Os.GetPathName());
+ }
+
+ if (depth > 1)
+ {
+ // Our CPU os not AnyCPU, add a / to our full path
+ fullPath = Path.Combine(fullPath, _platform.Cpu.GetPathName());
+ }
+
+ // Finally, append the file name and return
+ var fileName = Path.GetFileName(_sourcePath);
+ fullPath = Path.Combine(fullPath, fileName);
+ return fullPath;
+ }
+ }
+}
diff --git a/src/UnityNuGet/Registry.cs b/src/UnityNuGet/Registry.cs
index de0d0f04..a9c19297 100644
--- a/src/UnityNuGet/Registry.cs
+++ b/src/UnityNuGet/Registry.cs
@@ -1,44 +1,39 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Runtime.Serialization;
-using Newtonsoft.Json;
-
-namespace UnityNuGet
-{
- ///
- /// Loads the `registry.json` file at startup
- ///
- [Serializable]
- public sealed class Registry : Dictionary
- {
- private const string RegistryFileName = "registry.json";
- private static readonly object LockRead = new();
- private static Registry? _registry = null;
-
- // A comparer is established for cases where the dependency name is not set to the correct case.
- // Example: https://www.nuget.org/packages/NeoSmart.Caching.Sqlite/0.1.0#dependencies-body-tab
- public Registry() : base(StringComparer.OrdinalIgnoreCase)
- {
- }
-
- private Registry(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
-
- public static Registry Parse(string json)
- {
- ArgumentNullException.ThrowIfNull(json);
- return JsonConvert.DeserializeObject(json, JsonCommonExtensions.Settings)!;
- }
-
- public static Registry GetInstance()
- {
- lock (LockRead)
- {
- _registry ??= Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(typeof(Registry).Assembly.Location)!, RegistryFileName)));
- }
- return _registry;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Newtonsoft.Json;
+
+namespace UnityNuGet
+{
+ ///
+ /// Loads the `registry.json` file at startup
+ ///
+ [Serializable]
+ public sealed class Registry : Dictionary
+ {
+ private const string RegistryFileName = "registry.json";
+ private static readonly object LockRead = new();
+ private static Registry? _registry = null;
+
+ // A comparer is established for cases where the dependency name is not set to the correct case.
+ // Example: https://www.nuget.org/packages/NeoSmart.Caching.Sqlite/0.1.0#dependencies-body-tab
+ public Registry() : base(StringComparer.OrdinalIgnoreCase)
+ {
+ }
+
+ public static Registry Parse(string json)
+ {
+ ArgumentNullException.ThrowIfNull(json);
+ return JsonConvert.DeserializeObject(json, JsonCommonExtensions.Settings)!;
+ }
+
+ public static Registry GetInstance()
+ {
+ lock (LockRead)
+ {
+ _registry ??= Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(typeof(Registry).Assembly.Location)!, RegistryFileName)));
+ }
+ return _registry;
+ }
+ }
+}
diff --git a/src/UnityNuGet/RegistryCache.cs b/src/UnityNuGet/RegistryCache.cs
index c63f4b3a..323a2f0e 100644
--- a/src/UnityNuGet/RegistryCache.cs
+++ b/src/UnityNuGet/RegistryCache.cs
@@ -280,7 +280,7 @@ private async Task BuildInternal()
var resolvedDependencyGroups = NuGetHelper.GetCompatiblePackageDependencyGroups(packageMeta.DependencySets, _targetFrameworks).ToList();
- if (!packageEntry.Analyzer && !resolvedDependencyGroups.Any())
+ if (!packageEntry.Analyzer && resolvedDependencyGroups.Count == 0)
{
using var downloadResult = await GetPackageDownloadResourceResult(packageIdentity);
@@ -570,7 +570,7 @@ RegistryEntry packageEntry
{
if (!collectedItems.TryGetValue(item, out var frameworksPerGroup))
{
- frameworksPerGroup = new HashSet();
+ frameworksPerGroup = [];
collectedItems.Add(item, frameworksPerGroup);
}
frameworksPerGroup.Add(targetFramework);
@@ -643,16 +643,16 @@ RegistryEntry packageEntry
meta = UnityMeta.GetMetaForDll(
GetStableGuid(identity, fileInUnityPackage),
new PlatformDefinition(UnityOs.AnyOs, UnityCpu.None, isEditorConfig: false),
- new string[] { "RoslynAnalyzer" },
- Array.Empty());
+ ["RoslynAnalyzer"],
+ []);
}
else
{
meta = UnityMeta.GetMetaForDll(
GetStableGuid(identity, fileInUnityPackage),
new PlatformDefinition(UnityOs.AnyOs, UnityCpu.None, isEditorConfig: false),
- Array.Empty(),
- Array.Empty());
+ [],
+ []);
}
}
else
@@ -765,7 +765,7 @@ RegistryEntry packageEntry
}
else
{
- folders = Array.Empty();
+ folders = [];
}
string folder = string.Empty;
@@ -789,7 +789,7 @@ RegistryEntry packageEntry
// use NET_STANDARD
var defineConstraints = hasMultiNetStandard
|| hasOnlyNetStandard21
- || isPackageNetStandard21Assembly ? frameworks.First(x => x.Framework == item.TargetFramework).DefineConstraints : Array.Empty();
+ || isPackageNetStandard21Assembly ? frameworks.First(x => x.Framework == item.TargetFramework).DefineConstraints : [];
meta = UnityMeta.GetMetaForDll(
GetStableGuid(identity, fileInUnityPackage),
@@ -902,7 +902,7 @@ RegistryEntry packageEntry
if (licenseUrlText != null)
{
licenseUrlText = licenseUrlText.Trim();
- if (licenseUrlText.StartsWith("<"))
+ if (licenseUrlText.StartsWith('<'))
{
try
{
@@ -1112,7 +1112,7 @@ private static UnityAsmdef CreateAnalyzerAmsdef(PackageIdentity packageIdentity)
return new()
{
Name = $"{packageIdentity.Id}_Unity", // Add _Unity suffix because Unity has a validation so that assemblies names do not collide with asmdefs assembly names
- IncludePlatforms = new string[] { "Editor" }
+ IncludePlatforms = ["Editor"]
};
}
@@ -1164,8 +1164,15 @@ private void LogError(string message)
private static List SplitCommaSeparatedString(string input)
{
var list = new List();
- if (input == null) return list;
- foreach (var entry in input.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
+
+ if (input == null)
+ {
+ return list;
+ }
+
+ char[] separators = [',', ';'];
+
+ foreach (var entry in input.Split(separators, StringSplitOptions.RemoveEmptyEntries))
{
list.Add(entry.Trim());
}
diff --git a/src/UnityNuGet/RegistryEntry.cs b/src/UnityNuGet/RegistryEntry.cs
index 2c2c67d8..8c00a404 100644
--- a/src/UnityNuGet/RegistryEntry.cs
+++ b/src/UnityNuGet/RegistryEntry.cs
@@ -1,27 +1,27 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
-using NuGet.Versioning;
-
-namespace UnityNuGet
-{
- ///
- /// An entry in the
- ///
- public class RegistryEntry
- {
- [JsonProperty("ignore")]
- public bool Ignored { get; set; }
-
- [JsonProperty("listed")]
- public bool Listed { get; set; }
-
- [JsonProperty("version")]
- public VersionRange? Version { get; set; }
-
- [JsonProperty("defineConstraints")]
- public List DefineConstraints { get; set; } = new();
-
- [JsonProperty("analyzer")]
- public bool Analyzer { get; set; }
- }
-}
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using NuGet.Versioning;
+
+namespace UnityNuGet
+{
+ ///
+ /// An entry in the
+ ///
+ public class RegistryEntry
+ {
+ [JsonProperty("ignore")]
+ public bool Ignored { get; set; }
+
+ [JsonProperty("listed")]
+ public bool Listed { get; set; }
+
+ [JsonProperty("version")]
+ public VersionRange? Version { get; set; }
+
+ [JsonProperty("defineConstraints")]
+ public List DefineConstraints { get; set; } = [];
+
+ [JsonProperty("analyzer")]
+ public bool Analyzer { get; set; }
+ }
+}
diff --git a/src/UnityNuGet/UnityNuGet.csproj b/src/UnityNuGet/UnityNuGet.csproj
index 1e3306b1..6943335e 100644
--- a/src/UnityNuGet/UnityNuGet.csproj
+++ b/src/UnityNuGet/UnityNuGet.csproj
@@ -1,11 +1,8 @@
-
+
- net7.0
- enable
+ net8.0
0.14.0
- 9.0
- true
@@ -23,14 +20,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/UnityNuGet/UnityPackage.cs b/src/UnityNuGet/UnityPackage.cs
index ae6be33d..b07b41d8 100644
--- a/src/UnityNuGet/UnityPackage.cs
+++ b/src/UnityNuGet/UnityPackage.cs
@@ -1,41 +1,41 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
-namespace UnityNuGet
-{
- ///
- ///
- ///
- public class UnityPackage : JsonObjectBase
- {
- public UnityPackage()
- {
- Keywords = new List();
- Dependencies = new Dictionary();
- }
-
- [JsonProperty("name")]
- public string? Name { get; set; }
-
- [JsonProperty("displayName")]
- public string? DisplayName { get; set; }
-
- [JsonProperty("version")]
- public string? Version { get; set; }
-
- [JsonProperty("unity")]
- public string? Unity { get; set; }
-
- [JsonProperty("description")]
- public string? Description { get; set; }
-
- [JsonProperty("keywords")]
- public List Keywords { get; }
-
- [JsonProperty("category")]
- public string? Category { get; set; }
-
- [JsonProperty("dependencies")]
- public Dictionary Dependencies { get; }
- }
-}
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace UnityNuGet
+{
+ ///
+ ///
+ ///
+ public class UnityPackage : JsonObjectBase
+ {
+ public UnityPackage()
+ {
+ Keywords = [];
+ Dependencies = [];
+ }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("displayName")]
+ public string? DisplayName { get; set; }
+
+ [JsonProperty("version")]
+ public string? Version { get; set; }
+
+ [JsonProperty("unity")]
+ public string? Unity { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("keywords")]
+ public List Keywords { get; }
+
+ [JsonProperty("category")]
+ public string? Category { get; set; }
+
+ [JsonProperty("dependencies")]
+ public Dictionary Dependencies { get; }
+ }
+}
diff --git a/src/global.json b/src/global.json
index 3a95bf88..f7fb55b4 100644
--- a/src/global.json
+++ b/src/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "7.0.100",
+ "version": "8.0.100",
"rollForward": "latestMinor",
"allowPrerelease": false
}