using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using NugetForUnity.Helper; using NugetForUnity.Models; using NugetForUnity.PackageSource; using NugetForUnity.PluginSupport; using NugetForUnity.Ui; using UnityEngine; [assembly: InternalsVisibleTo("NuGetForUnity.Editor.Tests")] [assembly: InternalsVisibleTo("NuGetForUnity.PlayTests")] namespace NugetForUnity.Configuration { /// /// Manages the active configuration of NuGetForUnity . /// public static class ConfigurationManager { [NotNull] private static readonly string NativeRuntimeSettingsFilePath; /// /// The to use. /// [CanBeNull] private static INugetPackageSource activePackageSource; /// /// Backing field for the NuGet.config file. /// [CanBeNull] private static NugetConfigFile nugetConfigFile; [CanBeNull] private static NativeRuntimeSettings nativeRuntimeSettings; static ConfigurationManager() { NugetConfigFilePath = Path.Combine(UnityPathHelper.AbsoluteUnityPackagesNugetPath, NugetConfigFile.FileName); if (File.Exists(NugetConfigFilePath)) { NugetConfigFileDirectoryPath = UnityPathHelper.AbsoluteUnityPackagesNugetPath; } else { NugetConfigFilePath = Path.Combine(UnityPathHelper.AbsoluteAssetsPath, NugetConfigFile.FileName); NugetConfigFileDirectoryPath = UnityPathHelper.AbsoluteAssetsPath; } NativeRuntimeSettingsFilePath = Path.Combine( UnityPathHelper.AbsoluteProjectPath, "ProjectSettings", "Packages", NuGetForUnityUpdater.UpmPackageName, "NativeRuntimeSettings.json"); } /// /// Gets the path to the nuget.config file. /// /// /// . /// [NotNull] public static string NugetConfigFilePath { get; private set; } /// /// Gets the loaded NuGet.config file that holds the settings for NuGet. /// [NotNull] public static NugetConfigFile NugetConfigFile { get { if (nugetConfigFile is null) { LoadNugetConfigFile(); } Debug.Assert(nugetConfigFile != null, nameof(nugetConfigFile) + " != null"); return nugetConfigFile; } } /// /// Gets the loaded file that holds the settings for how to install native runtime dependencies. /// [NotNull] internal static NativeRuntimeSettings NativeRuntimeSettings { get { if (nativeRuntimeSettings is null) { nativeRuntimeSettings = NativeRuntimeSettings.LoadOrCreateDefault(NativeRuntimeSettingsFilePath); } return nativeRuntimeSettings; } } /// /// Gets the path to the directory containing the NuGet.config file. /// [NotNull] internal static string NugetConfigFileDirectoryPath { get; private set; } /// /// Gets a value indicating whether verbose logging is enabled. /// This can be set in the NuGet.config file. /// But this will not load the NuGet.config file to prevent endless loops wen we log while we load the NuGet.config file. /// internal static bool IsVerboseLoggingEnabled => nugetConfigFile?.Verbose ?? false; /// /// Gets a value indicating whether .NET Standard is preferred over .NET Framework as the TargetFramework. /// internal static bool PreferNetStandardOverNetFramework => nugetConfigFile?.PreferNetStandardOverNetFramework ?? false; /// /// Gets the to use. /// [NotNull] private static INugetPackageSource ActivePackageSource { get { if (activePackageSource is null) { LoadNugetConfigFile(); } Debug.Assert(activePackageSource != null, nameof(activePackageSource) + " != null"); return activePackageSource; } } /// /// Loads the NuGet.config file. /// public static void LoadNugetConfigFile() { if (File.Exists(NugetConfigFilePath)) { nugetConfigFile = NugetConfigFile.Load(NugetConfigFilePath); InjectSettingsFromGlobalNugetConfigFile(); } else { Debug.LogFormat("No NuGet.config file found. Creating default at {0}", NugetConfigFilePath); nugetConfigFile = NugetConfigFile.CreateDefaultFile(NugetConfigFilePath); } // parse any command line arguments var packageSourcesFromCommandLine = new List(); var readingSources = false; foreach (var arg in Environment.GetCommandLineArgs()) { if (readingSources) { if (arg.StartsWith("-", StringComparison.Ordinal)) { readingSources = false; } else { var source = NugetPackageSourceCreator.CreatePackageSource( $"CMD_LINE_SRC_{packageSourcesFromCommandLine.Count}", arg, null, null); NugetLogger.LogVerbose("Adding command line package source {0} at {1}", source.Name, arg); packageSourcesFromCommandLine.Add(source); } } if (arg.Equals("-Source", StringComparison.OrdinalIgnoreCase)) { // if the source is being forced, don't install packages from the cache NugetConfigFile.InstallFromCache = false; readingSources = true; } } if (packageSourcesFromCommandLine.Count == 1) { activePackageSource = packageSourcesFromCommandLine[0]; } else if (packageSourcesFromCommandLine.Count > 1) { activePackageSource = new NugetPackageSourceCombined(packageSourcesFromCommandLine); } else { // if there are not command line overrides, use the NuGet.config package sources activePackageSource = NugetConfigFile.ActivePackageSource; } PluginRegistry.InitPlugins(); } /// /// Gets a list of NugetPackages from all active package source's. /// This allows searching for partial IDs or even the empty string (the default) to list ALL packages. /// /// The search term to use to filter packages. Defaults to the empty string. /// True to include pre-release packages (alpha, beta, etc). /// The number of packages to fetch. /// The number of packages to skip before fetching. /// Token that can be used to cancel the asynchronous task. /// The list of available packages. [NotNull] [ItemNotNull] public static Task> SearchAsync( [NotNull] string searchTerm = "", bool includePrerelease = false, int numberToGet = 15, int numberToSkip = 0, CancellationToken cancellationToken = default) { return ActivePackageSource.SearchAsync(searchTerm, includePrerelease, numberToGet, numberToSkip, cancellationToken); } /// /// Queries all active NuGet package source's with the given list of installed packages to get any updates that are available. /// /// The list of currently installed packages for which updates are searched. /// True to include pre-release packages (alpha, beta, etc). /// The specific frameworks to target?. /// The version constraints?. /// The cancellation token?. /// A list of all updates available. [NotNull] [ItemNotNull] public static List GetUpdates( [NotNull] IEnumerable packagesToUpdate, bool includePrerelease = false, string targetFrameworks = "", string versionConstraints = "", CancellationToken token = default) { return ActivePackageSource.GetUpdates(packagesToUpdate, includePrerelease, targetFrameworks, versionConstraints, token); } /// [CanBeNull] public static INugetPackage GetSpecificPackage([NotNull] INugetPackageIdentifier nugetPackageIdentifier) { return ActivePackageSource.GetSpecificPackage(nugetPackageIdentifier); } /// /// Moves the Nuget.config under newPlacement and updated local properties to point to it. /// /// New placement for configs. internal static void MoveConfig(PackageInstallLocation newInstallLocation) { NugetConfigFile.ChangeInstallLocation(newInstallLocation); var newConfigsPath = newInstallLocation == PackageInstallLocation.InPackagesFolder ? UnityPathHelper.AbsoluteUnityPackagesNugetPath : UnityPathHelper.AbsoluteAssetsPath; var newConfigFilePath = Path.Combine(newConfigsPath, NugetConfigFile.FileName); File.Move(NugetConfigFilePath, newConfigFilePath); var configMeta = NugetConfigFilePath + ".meta"; if (File.Exists(configMeta)) { File.Move(configMeta, newConfigFilePath + ".meta"); } NugetConfigFilePath = newConfigFilePath; NugetConfigFileDirectoryPath = newConfigsPath; } /// /// Add package source credentials from an 'external' package config file if the file exists. /// The location of global config is the same as the one used by NuGet CLI /// . /// private static void InjectSettingsFromGlobalNugetConfigFile() { var userSettingsFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NuGet", "NuGet.Config"); nugetConfigFile.FillMissingPackageCredentialsFromExternalFile(userSettingsFilePath); string machineWideBaseDir; var configEnvironmentVariable = Environment.GetEnvironmentVariable("NUGET_COMMON_APPLICATION_DATA"); if (!string.IsNullOrEmpty(configEnvironmentVariable)) { machineWideBaseDir = configEnvironmentVariable; } else if (Application.platform == RuntimePlatform.WindowsEditor) { machineWideBaseDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); if (string.IsNullOrEmpty(machineWideBaseDir)) { // On 32-bit Windows machineWideBaseDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); } } else { machineWideBaseDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); } machineWideBaseDir = Path.Combine(machineWideBaseDir, "NuGet"); var machineWideConfigFilePath = Path.Combine(machineWideBaseDir, "Config", "NuGet.Config"); nugetConfigFile.FillMissingPackageCredentialsFromExternalFile(machineWideConfigFilePath); } } }