From 9d19ed59cd060cac2d60391c94c99009fb66271e Mon Sep 17 00:00:00 2001 From: TheCakeIsNaOH Date: Mon, 19 Dec 2022 16:50:56 -0600 Subject: [PATCH] (#508) Attempt to resolve relative paths for sources When setting up NuGet sources, if NuGet is unable to parse the path, this tries to resolve relative paths to absolute, and then retries setting up the NuGet source. If the path is unable to be resolved, then this ignores the error and lets NuGet handle the resulting invalid source. This path resolution requires the filesystem to be passed in. This means that various method signatures change to allow access to the filesystem. When using NuGet.Core, then relative paths were able to be resolved. But now with NuGet.Client, relative paths are resolved by clients, not by libraries, which is why this change has to be made. https://github.com/NuGet/NuGet.Client/pull/3783 --- .../nuget/NugetCommonSpecs.cs | 4 +- .../infrastructure.app/nuget/NugetCommon.cs | 37 +++++++++++++++++-- .../infrastructure.app/nuget/NugetList.cs | 13 ++++--- .../infrastructure.app/nuget/NugetPush.cs | 5 ++- .../services/NugetService.cs | 12 +++--- .../services/TemplateService.cs | 2 +- 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/chocolatey.tests/infrastructure.app/nuget/NugetCommonSpecs.cs b/src/chocolatey.tests/infrastructure.app/nuget/NugetCommonSpecs.cs index 2453b2c79c..3fa1d43835 100644 --- a/src/chocolatey.tests/infrastructure.app/nuget/NugetCommonSpecs.cs +++ b/src/chocolatey.tests/infrastructure.app/nuget/NugetCommonSpecs.cs @@ -21,6 +21,7 @@ namespace chocolatey.tests.infrastructure.app.nuget using System.Linq; using chocolatey.infrastructure.app.configuration; using chocolatey.infrastructure.app.nuget; + using chocolatey.infrastructure.filesystem; using Moq; using NuGet.Common; using NuGet.Packaging; @@ -35,6 +36,7 @@ private class when_gets_remote_repository : TinySpec private Action because; private readonly Mock nugetLogger = new Mock(); private readonly Mock packageDownloader = new Mock(); + private readonly Mock filesystem = new Mock(); private ChocolateyConfiguration configuration; private IEnumerable packageRepositories; @@ -47,7 +49,7 @@ public override void Context() public override void Because() { - because = () => packageRepositories = NugetCommon.GetRemoteRepositories(configuration, nugetLogger.Object); + because = () => packageRepositories = NugetCommon.GetRemoteRepositories(configuration, nugetLogger.Object, filesystem.Object); } [Fact] diff --git a/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs b/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs index 2c6eff71cd..1fa4af06e3 100644 --- a/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs +++ b/src/chocolatey/infrastructure.app/nuget/NugetCommon.cs @@ -23,6 +23,7 @@ namespace chocolatey.infrastructure.app.nuget using System.Net; using System.Net.Http; using System.Net.Security; + using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; @@ -92,7 +93,7 @@ public static IPackageRepository GetLocalRepository(IPackagePathResolver pathRes } */ - public static IEnumerable GetRemoteRepositories(ChocolateyConfiguration configuration, ILogger nugetLogger) + public static IEnumerable GetRemoteRepositories(ChocolateyConfiguration configuration, ILogger nugetLogger, IFileSystem filesystem) { //TODO, fix @@ -185,9 +186,39 @@ public static IEnumerable GetRemoteRepositories(ChocolateyConf } } - updatedSources.AppendFormat("{0};", source); - var nugetSource = new PackageSource(source); + + // If not parsed as a http(s) or local source, let's try resolving the path + // Since NuGet.Client is not able to parse all relative paths + // Conversion to absolute paths is handled by clients, not by the libraries as per + // https://github.com/NuGet/NuGet.Client/pull/3783 + if (nugetSource.TrySourceAsUri is null) + { + string fullsource; + try + { + fullsource = filesystem.get_full_path(source); + } + catch + { + // If an invalid source was passed in, we don't care here, pass it along + fullsource = source; + } + nugetSource = new PackageSource(fullsource); + + if (!nugetSource.IsLocal) + { + throw new ApplicationException("Source '{0}' is unable to be parsed".format_with(source)); + } + + "chocolatey".Log().Debug("Updating Source path from {0} to {1}".format_with(source, fullsource)); + updatedSources.AppendFormat("{0};", fullsource); + } + else + { + updatedSources.AppendFormat("{0};", source); + } + nugetSource.ClientCertificates = sourceClientCertificates; var repo = Repository.Factory.GetCoreV3(nugetSource); repositories.Add(repo); diff --git a/src/chocolatey/infrastructure.app/nuget/NugetList.cs b/src/chocolatey/infrastructure.app/nuget/NugetList.cs index 1636d92311..3004c9bce7 100644 --- a/src/chocolatey/infrastructure.app/nuget/NugetList.cs +++ b/src/chocolatey/infrastructure.app/nuget/NugetList.cs @@ -26,6 +26,7 @@ namespace chocolatey.infrastructure.app.nuget using System.Threading; using System.Threading.Tasks; using configuration; + using filesystem; using NuGet.Common; using NuGet.Configuration; using NuGet.PackageManagement; @@ -39,19 +40,19 @@ namespace chocolatey.infrastructure.app.nuget public static class NugetList { - public static IEnumerable GetPackages(ChocolateyConfiguration configuration, ILogger nugetLogger) + public static IEnumerable GetPackages(ChocolateyConfiguration configuration, ILogger nugetLogger, IFileSystem filesystem) { - return execute_package_search(configuration, nugetLogger).GetAwaiter().GetResult(); + return execute_package_search(configuration, nugetLogger, filesystem).GetAwaiter().GetResult(); } - public static int GetCount(ChocolateyConfiguration configuration, ILogger nugetLogger) + public static int GetCount(ChocolateyConfiguration configuration, ILogger nugetLogger, IFileSystem filesystem) { - return execute_package_search(configuration, nugetLogger).GetAwaiter().GetResult().Count(); + return execute_package_search(configuration, nugetLogger, filesystem).GetAwaiter().GetResult().Count(); } - private async static Task> execute_package_search(ChocolateyConfiguration configuration, ILogger nugetLogger) + private async static Task> execute_package_search(ChocolateyConfiguration configuration, ILogger nugetLogger, IFileSystem filesystem) { - var packageRepositories = NugetCommon.GetRemoteRepositories(configuration, nugetLogger); + var packageRepositories = NugetCommon.GetRemoteRepositories(configuration, nugetLogger, filesystem); var packageRepositoriesResources = NugetCommon.GetRepositoryResources(packageRepositories); string searchTermLower = configuration.Input.to_lower(); SearchFilter searchFilter = new SearchFilter(configuration.Prerelease); diff --git a/src/chocolatey/infrastructure.app/nuget/NugetPush.cs b/src/chocolatey/infrastructure.app/nuget/NugetPush.cs index c0ee27c585..d2daf958cd 100644 --- a/src/chocolatey/infrastructure.app/nuget/NugetPush.cs +++ b/src/chocolatey/infrastructure.app/nuget/NugetPush.cs @@ -22,6 +22,7 @@ namespace chocolatey.infrastructure.app.nuget using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using filesystem; using NuGet.Common; using NuGet.Configuration; using NuGet.Protocol; @@ -29,7 +30,7 @@ namespace chocolatey.infrastructure.app.nuget public class NugetPush { - public static void push_package(ChocolateyConfiguration config, string nupkgFilePath, ILogger nugetLogger, string nupkgFileName) + public static void push_package(ChocolateyConfiguration config, string nupkgFilePath, ILogger nugetLogger, string nupkgFileName, IFileSystem filesystem) { var timeout = TimeSpan.FromSeconds(Math.Abs(config.CommandExecutionTimeoutSeconds)); if (timeout.Seconds <= 0) @@ -42,7 +43,7 @@ public static void push_package(ChocolateyConfiguration config, string nupkgFile const bool noServiceEndpoint = true; //OK to use FirstOrDefault in this case as the command validates that there is only one source - SourceRepository sourceRepository = NugetCommon.GetRemoteRepositories(config, nugetLogger).FirstOrDefault(); + SourceRepository sourceRepository = NugetCommon.GetRemoteRepositories(config, nugetLogger, filesystem).FirstOrDefault(); PackageUpdateResource packageUpdateResource = sourceRepository.GetResource(); var nupkgFilePaths = new List() { nupkgFilePath }; UserAgent.SetUserAgentString(new UserAgentStringBuilder("{0}/{1} via NuGet Client".format_with(ApplicationParameters.UserAgent, config.Information.ChocolateyProductVersion))); diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index 0d246c0637..e00930c447 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -105,7 +105,7 @@ public virtual int count_run(ChocolateyConfiguration config) int? pageValue = config.ListCommand.Page; try { - return NugetList.GetCount(config, _nugetLogger); + return NugetList.GetCount(config, _nugetLogger, _fileSystem); } finally { @@ -139,7 +139,7 @@ public virtual IEnumerable list_run(ChocolateyConfiguration confi if (config.RegularOutput) this.Log().Debug(() => "Running list with the following filter = '{0}'".format_with(config.Input)); if (config.RegularOutput) this.Log().Debug(ChocolateyLoggers.Verbose, () => "--- Start of List ---"); - foreach (var pkg in NugetList.GetPackages(config, _nugetLogger)) + foreach (var pkg in NugetList.GetPackages(config, _nugetLogger, _fileSystem)) { var package = pkg; // for lamda access @@ -370,7 +370,7 @@ public virtual void push_run(ChocolateyConfiguration config) string nupkgFileName = _fileSystem.get_file_name(nupkgFilePath); if (config.RegularOutput) this.Log().Info(() => "Attempting to push {0} to {1}".format_with(nupkgFileName, config.Sources)); - NugetPush.push_package(config, _fileSystem.get_full_path(nupkgFilePath), _nugetLogger, nupkgFileName); + NugetPush.push_package(config, _fileSystem.get_full_path(nupkgFilePath), _nugetLogger, nupkgFileName, _fileSystem); if (config.RegularOutput && (config.Sources.is_equal_to(ApplicationParameters.ChocolateyCommunityFeedPushSource) || config.Sources.is_equal_to(ApplicationParameters.ChocolateyCommunityFeedPushSourceOld))) { @@ -430,7 +430,7 @@ public virtual ConcurrentDictionary install_run(Chocolate if (config.Force) config.AllowDowngrade = true; var sourceCacheContext = new ChocolateySourceCacheContext(config); - var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger); + var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger, _fileSystem); var localRepositorySource = NugetCommon.GetLocalRepository(); var pathResolver = NugetCommon.GetPathResolver(config, _fileSystem); var nugetProject = new FolderNuGetProject(ApplicationParameters.PackagesLocation, pathResolver, NuGetFramework.AnyFramework); @@ -858,7 +858,7 @@ public virtual ConcurrentDictionary upgrade_run(Chocolate if (config.Force) config.AllowDowngrade = true; var sourceCacheContext = new ChocolateySourceCacheContext(config); - var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger); + var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger, _fileSystem); var localRepositorySource = NugetCommon.GetLocalRepository(); var projectContext = new ChocolateyNuGetProjectContext(config, _nugetLogger); @@ -1353,7 +1353,7 @@ public virtual ConcurrentDictionary upgrade_run(Chocolate public virtual ConcurrentDictionary get_outdated(ChocolateyConfiguration config) { - var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger); + var remoteRepositories = NugetCommon.GetRemoteRepositories(config, _nugetLogger, _fileSystem); var pathResolver = NugetCommon.GetPathResolver(config, _fileSystem); var outdatedPackages = new ConcurrentDictionary(); diff --git a/src/chocolatey/infrastructure.app/services/TemplateService.cs b/src/chocolatey/infrastructure.app/services/TemplateService.cs index 65bba9f55c..09da070e92 100644 --- a/src/chocolatey/infrastructure.app/services/TemplateService.cs +++ b/src/chocolatey/infrastructure.app/services/TemplateService.cs @@ -274,7 +274,7 @@ public void list(ChocolateyConfiguration configuration) protected void list_custom_template_info(ChocolateyConfiguration configuration) { - var packageRepositories = NugetCommon.GetRemoteRepositories(configuration, _nugetLogger); + var packageRepositories = NugetCommon.GetRemoteRepositories(configuration, _nugetLogger, _fileSystem); var sourceCacheContext = new ChocolateySourceCacheContext(configuration); var pkg = NugetList.find_package( "{0}.template".format_with(configuration.TemplateCommand.Name),